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:
authorFabian Schempp <fabianschempp@googlemail.com>2021-08-15 10:13:45 +0300
committerFabian Schempp <fabianschempp@googlemail.com>2021-08-15 10:13:45 +0300
commitfad55ce70bed63b4fee7944bc04ddf0998230b77 (patch)
tree633e6fcc65a273f122eecca3e56cef02729c242d
parentc54bdc7fb6a5db764695b07b871b94ee5b189071 (diff)
parentd5261e973b5624b40b80771903e9d2a0c9ff37e4 (diff)
Merge branch 'master' into soc-2021-porting-modifiers-to-nodes-extrude-and-move
# Conflicts: # source/blender/blenkernel/BKE_node.h
-rw-r--r--build_files/build_environment/CMakeLists.txt2
-rw-r--r--build_files/build_environment/cmake/ispc.cmake6
-rw-r--r--build_files/build_environment/cmake/openmp.cmake6
-rw-r--r--build_files/build_environment/cmake/osl.cmake2
-rw-r--r--build_files/build_environment/cmake/png.cmake2
-rw-r--r--build_files/build_environment/cmake/versions.cmake14
-rw-r--r--build_files/build_environment/patches/openmp.diff23
-rw-r--r--build_files/cmake/platform/platform_apple.cmake13
-rw-r--r--build_files/windows/doc_py.cmd34
-rw-r--r--build_files/windows/find_sphinx.cmd23
-rw-r--r--build_files/windows/parse_arguments.cmd3
-rw-r--r--build_files/windows/reset_variables.cmd3
-rw-r--r--build_files/windows/show_help.cmd4
-rw-r--r--doc/blender_file_format/BlendFileReader.py2
-rw-r--r--doc/python_api/sphinx_doc_gen.py2
-rw-r--r--extern/audaspace/bindings/python/setup.py.in2
-rw-r--r--extern/nanosvg/README.blender7
-rw-r--r--extern/nanosvg/nanosvg.h (renamed from source/blender/io/gpencil/nanosvg/nanosvg.h)0
-rw-r--r--extern/nanosvg/patches/NanoSVG.diff86
-rw-r--r--intern/cycles/blender/blender_python.cpp107
-rw-r--r--intern/cycles/blender/blender_shader.cpp90
-rw-r--r--intern/cycles/blender/blender_util.h2
-rw-r--r--intern/cycles/render/session.cpp287
-rw-r--r--intern/cycles/render/session.h45
-rw-r--r--intern/ghost/GHOST_C-api.h4
-rw-r--r--intern/ghost/intern/GHOST_C-api.cpp4
-rw-r--r--intern/ghost/intern/GHOST_ImeWin32.cpp199
-rw-r--r--intern/ghost/intern/GHOST_ImeWin32.h35
-rw-r--r--intern/ghost/intern/GHOST_SystemCocoa.mm2
-rw-r--r--intern/ghost/intern/GHOST_XrAction.cpp8
-rw-r--r--intern/ghost/intern/GHOST_XrAction.h4
-rw-r--r--intern/ghost/intern/GHOST_XrSession.cpp4
-rw-r--r--intern/ghost/intern/GHOST_XrSession.h4
-rw-r--r--intern/guardedalloc/intern/mallocn_guarded_impl.c2
-rw-r--r--make.bat15
-rw-r--r--release/datafiles/preview.blendbin1453009 -> 1471916 bytes
-rw-r--r--release/scripts/modules/bl_i18n_utils/utils.py6
-rw-r--r--release/scripts/modules/bl_i18n_utils/utils_spell_check.py9
-rw-r--r--release/scripts/modules/bpy/utils/__init__.py2
-rw-r--r--release/scripts/modules/bpy_types.py23
-rw-r--r--release/scripts/presets/keyconfig/keymap_data/blender_default.py10
-rw-r--r--release/scripts/presets/keyconfig/keymap_data/industry_compatible_data.py17
-rw-r--r--release/scripts/startup/bl_app_templates_system/2D_Animation/__init__.py69
-rw-r--r--release/scripts/startup/bl_app_templates_system/Video_Editing/__init__.py11
-rw-r--r--release/scripts/startup/bl_operators/assets.py2
-rw-r--r--release/scripts/startup/bl_ui/properties_mask_common.py3
-rw-r--r--release/scripts/startup/bl_ui/properties_object.py25
-rw-r--r--release/scripts/startup/bl_ui/properties_paint_common.py15
-rw-r--r--release/scripts/startup/bl_ui/space_clip.py39
-rw-r--r--release/scripts/startup/bl_ui/space_filebrowser.py14
-rw-r--r--release/scripts/startup/bl_ui/space_image.py11
-rw-r--r--release/scripts/startup/bl_ui/space_outliner.py2
-rw-r--r--release/scripts/startup/bl_ui/space_sequencer.py18
-rw-r--r--release/scripts/startup/bl_ui/space_spreadsheet.py2
-rw-r--r--release/scripts/startup/bl_ui/space_text.py5
-rw-r--r--release/scripts/startup/bl_ui/space_toolsystem_toolbar.py1
-rw-r--r--release/scripts/startup/bl_ui/space_userpref.py7
-rw-r--r--release/scripts/startup/bl_ui/space_view3d.py1
-rw-r--r--release/scripts/startup/bl_ui/space_view3d_toolbar.py2
-rw-r--r--release/scripts/startup/nodeitems_builtins.py1
-rw-r--r--source/blender/blenfont/intern/blf_font.c93
-rw-r--r--source/blender/blenfont/intern/blf_glyph.c7
-rw-r--r--source/blender/blenfont/intern/blf_internal_types.h18
-rw-r--r--source/blender/blenkernel/BKE_blender_version.h2
-rw-r--r--source/blender/blenkernel/BKE_bvhutils.h2
-rw-r--r--source/blender/blenkernel/BKE_collection.h2
-rw-r--r--source/blender/blenkernel/BKE_constraint.h22
-rw-r--r--source/blender/blenkernel/BKE_context.h2
-rw-r--r--source/blender/blenkernel/BKE_global.h3
-rw-r--r--source/blender/blenkernel/BKE_lib_id.h4
-rw-r--r--source/blender/blenkernel/BKE_mesh.h46
-rw-r--r--source/blender/blenkernel/BKE_node.h3
-rw-r--r--source/blender/blenkernel/intern/DerivedMesh.cc36
-rw-r--r--source/blender/blenkernel/intern/anim_sys.c2
-rw-r--r--source/blender/blenkernel/intern/blendfile.c4
-rw-r--r--source/blender/blenkernel/intern/boids.c30
-rw-r--r--source/blender/blenkernel/intern/brush.c5
-rw-r--r--source/blender/blenkernel/intern/cloth.c12
-rw-r--r--source/blender/blenkernel/intern/collection.c2
-rw-r--r--source/blender/blenkernel/intern/colortools.c20
-rw-r--r--source/blender/blenkernel/intern/constraint.c105
-rw-r--r--source/blender/blenkernel/intern/context.c4
-rw-r--r--source/blender/blenkernel/intern/curve.c7
-rw-r--r--source/blender/blenkernel/intern/customdata.c7
-rw-r--r--source/blender/blenkernel/intern/data_transfer.c6
-rw-r--r--source/blender/blenkernel/intern/deform.c5
-rw-r--r--source/blender/blenkernel/intern/displist.cc2
-rw-r--r--source/blender/blenkernel/intern/dynamicpaint.c10
-rw-r--r--source/blender/blenkernel/intern/fluid.c30
-rw-r--r--source/blender/blenkernel/intern/font.c95
-rw-r--r--source/blender/blenkernel/intern/geometry_set_instances.cc4
-rw-r--r--source/blender/blenkernel/intern/gpencil.c1
-rw-r--r--source/blender/blenkernel/intern/icons.cc2
-rw-r--r--source/blender/blenkernel/intern/image.c2
-rw-r--r--source/blender/blenkernel/intern/key.c11
-rw-r--r--source/blender/blenkernel/intern/layer.c54
-rw-r--r--source/blender/blenkernel/intern/lib_id.c8
-rw-r--r--source/blender/blenkernel/intern/lib_id_delete.c35
-rw-r--r--source/blender/blenkernel/intern/lib_override.c4
-rw-r--r--source/blender/blenkernel/intern/mask_rasterize.c4
-rw-r--r--source/blender/blenkernel/intern/material.c1
-rw-r--r--source/blender/blenkernel/intern/mball.c2
-rw-r--r--source/blender/blenkernel/intern/mesh.c339
-rw-r--r--source/blender/blenkernel/intern/mesh_convert.c9
-rw-r--r--source/blender/blenkernel/intern/mesh_mirror.c17
-rw-r--r--source/blender/blenkernel/intern/mesh_normals.cc565
-rw-r--r--source/blender/blenkernel/intern/mesh_remap.c12
-rw-r--r--source/blender/blenkernel/intern/multires.c10
-rw-r--r--source/blender/blenkernel/intern/node.cc4
-rw-r--r--source/blender/blenkernel/intern/object.c7
-rw-r--r--source/blender/blenkernel/intern/object_deform.c10
-rw-r--r--source/blender/blenkernel/intern/ocean.c10
-rw-r--r--source/blender/blenkernel/intern/ocean_spectrum.c2
-rw-r--r--source/blender/blenkernel/intern/particle.c25
-rw-r--r--source/blender/blenkernel/intern/particle_system.c16
-rw-r--r--source/blender/blenkernel/intern/scene.c3
-rw-r--r--source/blender/blenkernel/intern/softbody.c10
-rw-r--r--source/blender/blenkernel/intern/text_suggestions.c10
-rw-r--r--source/blender/blenkernel/intern/texture.c20
-rw-r--r--source/blender/blenkernel/intern/workspace.c2
-rw-r--r--source/blender/blenlib/BLI_range.h5
-rw-r--r--source/blender/blenlib/intern/math_vector_inline.c11
-rw-r--r--source/blender/blenloader/BLO_readfile.h1
-rw-r--r--source/blender/blenloader/intern/versioning_300.c44
-rw-r--r--source/blender/blenloader/intern/versioning_userdef.c7
-rw-r--r--source/blender/blenloader/intern/writefile.c4
-rw-r--r--source/blender/blentranslation/intern/blt_lang.c5
-rw-r--r--source/blender/bmesh/intern/bmesh_mesh_normals.c11
-rw-r--r--source/blender/compositor/COM_defines.h6
-rw-r--r--source/blender/compositor/intern/COM_BufferOperation.cc13
-rw-r--r--source/blender/compositor/intern/COM_BufferOperation.h1
-rw-r--r--source/blender/compositor/intern/COM_ConstantFolder.cc4
-rw-r--r--source/blender/compositor/intern/COM_Debug.cc16
-rw-r--r--source/blender/compositor/intern/COM_MemoryBuffer.h5
-rw-r--r--source/blender/compositor/intern/COM_TiledExecutionModel.cc2
-rw-r--r--source/blender/compositor/operations/COM_AlphaOverKeyOperation.cc30
-rw-r--r--source/blender/compositor/operations/COM_AlphaOverKeyOperation.h4
-rw-r--r--source/blender/compositor/operations/COM_AlphaOverMixedOperation.cc27
-rw-r--r--source/blender/compositor/operations/COM_AlphaOverMixedOperation.h2
-rw-r--r--source/blender/compositor/operations/COM_AlphaOverPremultiplyOperation.cc29
-rw-r--r--source/blender/compositor/operations/COM_AlphaOverPremultiplyOperation.h4
-rw-r--r--source/blender/compositor/operations/COM_BilateralBlurOperation.cc86
-rw-r--r--source/blender/compositor/operations/COM_BilateralBlurOperation.h11
-rw-r--r--source/blender/compositor/operations/COM_BokehImageOperation.cc25
-rw-r--r--source/blender/compositor/operations/COM_BokehImageOperation.h8
-rw-r--r--source/blender/compositor/operations/COM_ChangeHSVOperation.cc23
-rw-r--r--source/blender/compositor/operations/COM_ChangeHSVOperation.h8
-rw-r--r--source/blender/compositor/operations/COM_ColorCurveOperation.cc53
-rw-r--r--source/blender/compositor/operations/COM_ColorCurveOperation.h8
-rw-r--r--source/blender/compositor/operations/COM_CompositorOperation.cc16
-rw-r--r--source/blender/compositor/operations/COM_CompositorOperation.h8
-rw-r--r--source/blender/compositor/operations/COM_ConstantOperation.cc17
-rw-r--r--source/blender/compositor/operations/COM_ConstantOperation.h16
-rw-r--r--source/blender/compositor/operations/COM_CurveBaseOperation.cc1
-rw-r--r--source/blender/compositor/operations/COM_CurveBaseOperation.h4
-rw-r--r--source/blender/compositor/operations/COM_DilateErodeOperation.cc2
-rw-r--r--source/blender/compositor/operations/COM_HueSaturationValueCorrectOperation.cc27
-rw-r--r--source/blender/compositor/operations/COM_HueSaturationValueCorrectOperation.h4
-rw-r--r--source/blender/compositor/operations/COM_InvertOperation.cc28
-rw-r--r--source/blender/compositor/operations/COM_InvertOperation.h8
-rw-r--r--source/blender/compositor/operations/COM_MaskOperation.cc37
-rw-r--r--source/blender/compositor/operations/COM_MaskOperation.h11
-rw-r--r--source/blender/compositor/operations/COM_MovieClipAttributeOperation.cc19
-rw-r--r--source/blender/compositor/operations/COM_MovieClipAttributeOperation.h9
-rw-r--r--source/blender/compositor/operations/COM_OutputFileOperation.cc33
-rw-r--r--source/blender/compositor/operations/COM_OutputFileOperation.h14
-rw-r--r--source/blender/compositor/operations/COM_SetColorOperation.cc10
-rw-r--r--source/blender/compositor/operations/COM_SetColorOperation.h4
-rw-r--r--source/blender/compositor/operations/COM_SetValueOperation.cc10
-rw-r--r--source/blender/compositor/operations/COM_SetValueOperation.h3
-rw-r--r--source/blender/compositor/operations/COM_SplitOperation.cc13
-rw-r--r--source/blender/compositor/operations/COM_SplitOperation.h8
-rw-r--r--source/blender/compositor/operations/COM_SunBeamsOperation.cc53
-rw-r--r--source/blender/compositor/operations/COM_SunBeamsOperation.h12
-rw-r--r--source/blender/compositor/operations/COM_TonemapOperation.cc124
-rw-r--r--source/blender/compositor/operations/COM_TonemapOperation.h16
-rw-r--r--source/blender/compositor/operations/COM_TrackPositionOperation.cc26
-rw-r--r--source/blender/compositor/operations/COM_TrackPositionOperation.h11
-rw-r--r--source/blender/compositor/operations/COM_VectorCurveOperation.cc10
-rw-r--r--source/blender/compositor/operations/COM_VectorCurveOperation.h4
-rw-r--r--source/blender/compositor/operations/COM_ZCombineOperation.cc70
-rw-r--r--source/blender/compositor/operations/COM_ZCombineOperation.h20
-rw-r--r--source/blender/datatoc/datatoc.c9
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_relations.cc5
-rw-r--r--source/blender/depsgraph/intern/depsgraph_tag.cc4
-rw-r--r--source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.h10
-rw-r--r--source/blender/draw/engines/overlay/overlay_extra.c3
-rw-r--r--source/blender/draw/engines/select/select_debug_engine.c2
-rw-r--r--source/blender/draw/intern/draw_cache_impl_gpencil.c2
-rw-r--r--source/blender/draw/intern/draw_cache_impl_mesh.c12
-rw-r--r--source/blender/draw/intern/draw_manager_texture.c24
-rw-r--r--source/blender/draw/intern/draw_view.c13
-rw-r--r--source/blender/editors/animation/CMakeLists.txt2
-rw-r--r--source/blender/editors/animation/anim_draw.c2
-rw-r--r--source/blender/editors/animation/anim_ipo_utils.c22
-rw-r--r--source/blender/editors/animation/fmodifier_ui.c5
-rw-r--r--source/blender/editors/animation/keyframes_draw.c747
-rw-r--r--source/blender/editors/animation/keyframes_general.c10
-rw-r--r--source/blender/editors/animation/keyframes_keylist.cc (renamed from source/blender/editors/animation/keyframes_keylist.c)296
-rw-r--r--source/blender/editors/armature/meshlaplacian.c5
-rw-r--r--source/blender/editors/armature/pose_lib_2.c12
-rw-r--r--source/blender/editors/armature/pose_slide.c4
-rw-r--r--source/blender/editors/asset/ED_asset_handle.h2
-rw-r--r--source/blender/editors/asset/ED_asset_temp_id_consumer.h2
-rw-r--r--source/blender/editors/asset/intern/asset_handle.cc4
-rw-r--r--source/blender/editors/asset/intern/asset_ops.cc6
-rw-r--r--source/blender/editors/asset/intern/asset_temp_id_consumer.cc10
-rw-r--r--source/blender/editors/curve/editcurve.c10
-rw-r--r--source/blender/editors/curve/editfont.c30
-rw-r--r--source/blender/editors/gpencil/gpencil_convert.c10
-rw-r--r--source/blender/editors/gpencil/gpencil_intern.h1
-rw-r--r--source/blender/editors/gpencil/gpencil_ops.c1
-rw-r--r--source/blender/editors/gpencil/gpencil_paint.c2
-rw-r--r--source/blender/editors/gpencil/gpencil_primitive.c2
-rw-r--r--source/blender/editors/gpencil/gpencil_sculpt_paint.c5
-rw-r--r--source/blender/editors/gpencil/gpencil_select.c235
-rw-r--r--source/blender/editors/gpencil/gpencil_utils.c2
-rw-r--r--source/blender/editors/include/ED_keyframes_draw.h41
-rw-r--r--source/blender/editors/include/ED_keyframes_keylist.h36
-rw-r--r--source/blender/editors/interface/interface_align.c2
-rw-r--r--source/blender/editors/interface/interface_context_menu.c2
-rw-r--r--source/blender/editors/interface/interface_draw.c4
-rw-r--r--source/blender/editors/interface/interface_eyedropper_driver.c5
-rw-r--r--source/blender/editors/interface/interface_handlers.c10
-rw-r--r--source/blender/editors/interface/interface_icons.c17
-rw-r--r--source/blender/editors/interface/interface_layout.c2
-rw-r--r--source/blender/editors/interface/interface_template_asset_view.cc24
-rw-r--r--source/blender/editors/interface/interface_templates.c94
-rw-r--r--source/blender/editors/mesh/editmesh_knife.c41
-rw-r--r--source/blender/editors/mesh/editmesh_knife_project.c43
-rw-r--r--source/blender/editors/mesh/editmesh_utils.c5
-rw-r--r--source/blender/editors/mesh/mesh_data.c11
-rw-r--r--source/blender/editors/mesh/mesh_intern.h5
-rw-r--r--source/blender/editors/mesh/mesh_mirror.c5
-rw-r--r--source/blender/editors/object/object_constraint.c324
-rw-r--r--source/blender/editors/object/object_intern.h3
-rw-r--r--source/blender/editors/object/object_modes.c2
-rw-r--r--source/blender/editors/object/object_ops.c3
-rw-r--r--source/blender/editors/object/object_relations.c28
-rw-r--r--source/blender/editors/object/object_vgroup.c2
-rw-r--r--source/blender/editors/physics/particle_edit.c15
-rw-r--r--source/blender/editors/physics/particle_edit_undo.c5
-rw-r--r--source/blender/editors/render/render_preview.c92
-rw-r--r--source/blender/editors/screen/area.c10
-rw-r--r--source/blender/editors/screen/screen_context.c6
-rw-r--r--source/blender/editors/screen/screen_edit.c10
-rw-r--r--source/blender/editors/screen/screen_ops.c19
-rw-r--r--source/blender/editors/sculpt_paint/paint_image_2d.c10
-rw-r--r--source/blender/editors/sculpt_paint/sculpt.c5
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_dyntopo.c10
-rw-r--r--source/blender/editors/space_action/action_data.c14
-rw-r--r--source/blender/editors/space_action/action_draw.c25
-rw-r--r--source/blender/editors/space_action/action_select.c7
-rw-r--r--source/blender/editors/space_buttons/space_buttons.c3
-rw-r--r--source/blender/editors/space_clip/clip_editor.c1
-rw-r--r--source/blender/editors/space_clip/tracking_ops_solve.c5
-rw-r--r--source/blender/editors/space_file/file_draw.c2
-rw-r--r--source/blender/editors/space_file/file_ops.c49
-rw-r--r--source/blender/editors/space_file/filelist.c149
-rw-r--r--source/blender/editors/space_file/filelist.h2
-rw-r--r--source/blender/editors/space_file/filesel.c6
-rw-r--r--source/blender/editors/space_file/space_file.c39
-rw-r--r--source/blender/editors/space_graph/graph_buttons.c2
-rw-r--r--source/blender/editors/space_image/image_ops.c5
-rw-r--r--source/blender/editors/space_info/info_stats.c5
-rw-r--r--source/blender/editors/space_nla/nla_channels.c3
-rw-r--r--source/blender/editors/space_nla/nla_draw.c19
-rw-r--r--source/blender/editors/space_nla/nla_edit.c4
-rw-r--r--source/blender/editors/space_node/drawnode.cc22
-rw-r--r--source/blender/editors/space_outliner/outliner_edit.c2
-rw-r--r--source/blender/editors/space_outliner/outliner_tools.c81
-rw-r--r--source/blender/editors/space_sequencer/sequencer_add.c7
-rw-r--r--source/blender/editors/space_text/text_draw.c5
-rw-r--r--source/blender/editors/space_text/text_ops.c5
-rw-r--r--source/blender/editors/space_view3d/view3d_buttons.c10
-rw-r--r--source/blender/editors/space_view3d/view3d_edit.c5
-rw-r--r--source/blender/editors/space_view3d/view3d_project.c2
-rw-r--r--source/blender/editors/transform/transform.c3
-rw-r--r--source/blender/editors/transform/transform.h2
-rw-r--r--source/blender/editors/transform/transform_convert.c14
-rw-r--r--source/blender/editors/transform/transform_generics.c3
-rw-r--r--source/blender/editors/transform/transform_mode.c4
-rw-r--r--source/blender/editors/transform/transform_mode_edge_slide.c4
-rw-r--r--source/blender/editors/transform/transform_snap.c29
-rw-r--r--source/blender/editors/uvedit/uvedit_parametrizer.c5
-rw-r--r--source/blender/editors/uvedit/uvedit_smart_stitch.c25
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpenciltint.c5
-rw-r--r--source/blender/gpu/GPU_matrix.h6
-rw-r--r--source/blender/gpu/GPU_texture.h14
-rw-r--r--source/blender/gpu/intern/gpu_material.c1
-rw-r--r--source/blender/gpu/intern/gpu_matrix.cc122
-rw-r--r--source/blender/gpu/tests/gpu_shader_test.cc3
-rw-r--r--source/blender/imbuf/intern/colormanagement.c6
-rw-r--r--source/blender/imbuf/intern/moviecache.c16
-rw-r--r--source/blender/imbuf/intern/openexr/openexr_api.cpp2
-rw-r--r--source/blender/io/alembic/intern/abc_reader_nurbs.cc4
-rw-r--r--source/blender/io/alembic/intern/abc_reader_object.cc2
-rw-r--r--source/blender/io/collada/AnimationImporter.cpp2
-rw-r--r--source/blender/io/gpencil/CMakeLists.txt4
-rw-r--r--source/blender/io/gpencil/intern/gpencil_io_import_svg.cc2
-rw-r--r--source/blender/io/usd/intern/usd_capi_export.cc2
-rw-r--r--source/blender/makesdna/DNA_ID.h23
-rw-r--r--source/blender/makesdna/DNA_asset_types.h2
-rw-r--r--source/blender/makesdna/DNA_gpencil_types.h1
-rw-r--r--source/blender/makesdna/DNA_mesh_types.h1
-rw-r--r--source/blender/makesdna/DNA_modifier_types.h25
-rw-r--r--source/blender/makesdna/DNA_node_types.h7
-rw-r--r--source/blender/makesdna/DNA_object_types.h1
-rw-r--r--source/blender/makesdna/DNA_sequence_types.h1
-rw-r--r--source/blender/makesdna/DNA_space_types.h2
-rw-r--r--source/blender/makesdna/DNA_userdef_types.h2
-rw-r--r--source/blender/makesdna/DNA_workspace_types.h2
-rw-r--r--source/blender/makesdna/intern/makesdna.c69
-rw-r--r--source/blender/makesrna/RNA_access.h2
-rw-r--r--source/blender/makesrna/intern/rna_access.c32
-rw-r--r--source/blender/makesrna/intern/rna_armature.c8
-rw-r--r--source/blender/makesrna/intern/rna_asset.c6
-rw-r--r--source/blender/makesrna/intern/rna_constraint.c6
-rw-r--r--source/blender/makesrna/intern/rna_curveprofile.c27
-rw-r--r--source/blender/makesrna/intern/rna_gpencil.c2
-rw-r--r--source/blender/makesrna/intern/rna_mesh.c2
-rw-r--r--source/blender/makesrna/intern/rna_nodetree.c86
-rw-r--r--source/blender/makesrna/intern/rna_object.c8
-rw-r--r--source/blender/makesrna/intern/rna_particle.c10
-rw-r--r--source/blender/makesrna/intern/rna_sequencer.c8
-rw-r--r--source/blender/makesrna/intern/rna_space.c11
-rw-r--r--source/blender/makesrna/intern/rna_speaker.c70
-rw-r--r--source/blender/makesrna/intern/rna_text.c3
-rw-r--r--source/blender/makesrna/intern/rna_ui.c4
-rw-r--r--source/blender/makesrna/intern/rna_userdef.c14
-rw-r--r--source/blender/makesrna/intern/rna_wm.c28
-rw-r--r--source/blender/makesrna/intern/rna_wm_api.c2
-rw-r--r--source/blender/makesrna/intern/rna_wm_gizmo.c22
-rw-r--r--source/blender/makesrna/intern/rna_workspace.c4
-rw-r--r--source/blender/makesrna/intern/rna_world.c2
-rw-r--r--source/blender/makesrna/intern/rna_xr.c97
-rw-r--r--source/blender/modifiers/intern/MOD_normal_edit.c16
-rw-r--r--source/blender/modifiers/intern/MOD_solidify_extrude.c53
-rw-r--r--source/blender/modifiers/intern/MOD_solidify_nonmanifold.c11
-rw-r--r--source/blender/modifiers/intern/MOD_weighted_normal.c4
-rw-r--r--source/blender/nodes/CMakeLists.txt1
-rw-r--r--source/blender/nodes/NOD_geometry.h1
-rw-r--r--source/blender/nodes/NOD_static_types.h1
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_attribute_sample_texture.cc2
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_convex_hull.cc2
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_curve_select_by_handle_type.cc147
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_circle.cc10
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_cone.cc5
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_grid.cc14
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_line.cc4
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_uv_sphere.cc14
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_raycast.cc152
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_volume_to_mesh.cc3
-rw-r--r--source/blender/nodes/shader/node_shader_tree.c1
-rw-r--r--source/blender/python/gpu/gpu_py_shader.c40
-rw-r--r--source/blender/python/intern/bpy.c3
-rw-r--r--source/blender/python/intern/bpy_interface.c11
-rw-r--r--source/blender/python/intern/bpy_rna.c63
-rw-r--r--source/blender/python/intern/bpy_rna.h1
-rw-r--r--source/blender/python/intern/bpy_rna_array.c2
-rw-r--r--source/blender/python/intern/bpy_rna_id_collection.c2
-rw-r--r--source/blender/python/intern/bpy_rna_operator.c2
-rw-r--r--source/blender/python/mathutils/mathutils.c4
-rw-r--r--source/blender/python/mathutils/mathutils_Vector.c4
-rw-r--r--source/blender/python/mathutils/mathutils_geometry.c2
-rw-r--r--source/blender/render/intern/texture_pointdensity.c5
-rw-r--r--source/blender/render/intern/zbuf.c9
-rw-r--r--source/blender/sequencer/intern/effects.c40
-rw-r--r--source/blender/windowmanager/WM_api.h6
-rw-r--r--source/blender/windowmanager/gizmo/intern/wm_gizmo_map.c8
-rw-r--r--source/blender/windowmanager/intern/wm.c1
-rw-r--r--source/blender/windowmanager/intern/wm_files.c156
-rw-r--r--source/blender/windowmanager/intern/wm_files_link.c32
-rw-r--r--source/blender/windowmanager/intern/wm_init_exit.c124
-rw-r--r--source/blender/windowmanager/intern/wm_operators.c10
-rw-r--r--source/blender/windowmanager/wm_files.h47
-rw-r--r--source/blender/windowmanager/xr/intern/wm_xr.c1
-rw-r--r--source/blender/windowmanager/xr/intern/wm_xr_action.c12
-rw-r--r--source/blender/windowmanager/xr/intern/wm_xr_actionmap.c2
-rw-r--r--source/blender/windowmanager/xr/intern/wm_xr_intern.h4
-rw-r--r--source/creator/CMakeLists.txt5
-rw-r--r--source/creator/creator_args.c5
382 files changed, 5638 insertions, 3382 deletions
diff --git a/build_files/build_environment/CMakeLists.txt b/build_files/build_environment/CMakeLists.txt
index 3a9574b4b2a..af1653de59a 100644
--- a/build_files/build_environment/CMakeLists.txt
+++ b/build_files/build_environment/CMakeLists.txt
@@ -84,7 +84,7 @@ include(cmake/openimageio.cmake)
include(cmake/tiff.cmake)
if(WIN32)
include(cmake/flexbison.cmake)
-else()
+elseif(UNIX AND NOT APPLE)
include(cmake/flex.cmake)
endif()
include(cmake/osl.cmake)
diff --git a/build_files/build_environment/cmake/ispc.cmake b/build_files/build_environment/cmake/ispc.cmake
index 93fc9dc4846..b1cd2cea0c7 100644
--- a/build_files/build_environment/cmake/ispc.cmake
+++ b/build_files/build_environment/cmake/ispc.cmake
@@ -29,13 +29,13 @@ elseif(APPLE)
if("${CMAKE_HOST_SYSTEM_PROCESSOR}" STREQUAL "arm64")
set(ISPC_EXTRA_ARGS_APPLE
-DBISON_EXECUTABLE=/opt/homebrew/opt/bison/bin/bison
- -DFLEX_EXECUTABLE=${LIBDIR}/flex/bin/flex
+ -DFLEX_EXECUTABLE=/opt/homebrew/opt/flex/bin/flex
-DARM_ENABLED=On
)
else()
set(ISPC_EXTRA_ARGS_APPLE
-DBISON_EXECUTABLE=/usr/local/opt/bison/bin/bison
- -DFLEX_EXECUTABLE=${LIBDIR}/flex/bin/flex
+ -DFLEX_EXECUTABLE=/usr/local/opt/flex/bin/flex
-DARM_ENABLED=Off
)
endif()
@@ -84,7 +84,7 @@ if(WIN32)
external_ispc
external_flexbison
)
-else()
+elseif(UNIX AND NOT APPLE)
add_dependencies(
external_ispc
external_flex
diff --git a/build_files/build_environment/cmake/openmp.cmake b/build_files/build_environment/cmake/openmp.cmake
index 0e5323ca513..d4d5e69a5ad 100644
--- a/build_files/build_environment/cmake/openmp.cmake
+++ b/build_files/build_environment/cmake/openmp.cmake
@@ -16,12 +16,18 @@
#
# ***** END GPL LICENSE BLOCK *****
+if(APPLE)
+ set(OPENMP_PATCH_COMMAND ${PATCH_CMD} -p 1 -d ${BUILD_DIR}/openmp/src/external_openmp < ${PATCH_DIR}/openmp.diff)
+else()
+ set(OPENMP_PATCH_COMMAND)
+endif()
ExternalProject_Add(external_openmp
URL file://${PACKAGE_DIR}/${OPENMP_FILE}
DOWNLOAD_DIR ${DOWNLOAD_DIR}
URL_HASH ${OPENMP_HASH_TYPE}=${OPENMP_HASH}
PREFIX ${BUILD_DIR}/openmp
+ PATCH_COMMAND ${OPENMP_PATCH_COMMAND}
CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${LIBDIR}/openmp ${DEFAULT_CMAKE_FLAGS}
INSTALL_COMMAND cd ${BUILD_DIR}/openmp/src/external_openmp-build && install_name_tool -id @rpath/libomp.dylib runtime/src/libomp.dylib && make install
INSTALL_DIR ${LIBDIR}/openmp
diff --git a/build_files/build_environment/cmake/osl.cmake b/build_files/build_environment/cmake/osl.cmake
index 05aedb1f085..c20bf68c0ef 100644
--- a/build_files/build_environment/cmake/osl.cmake
+++ b/build_files/build_environment/cmake/osl.cmake
@@ -96,7 +96,7 @@ if(WIN32)
external_osl
external_flexbison
)
-else()
+elseif(UNIX AND NOT APPLE)
add_dependencies(
external_osl
external_flex
diff --git a/build_files/build_environment/cmake/png.cmake b/build_files/build_environment/cmake/png.cmake
index 458d3a1fd98..3fc53b238c2 100644
--- a/build_files/build_environment/cmake/png.cmake
+++ b/build_files/build_environment/cmake/png.cmake
@@ -23,7 +23,7 @@ set(PNG_EXTRA_ARGS
)
if(BLENDER_PLATFORM_ARM)
- set(PNG_EXTRA_ARGS ${PNG_EXTRA_ARGS} -DPNG_HARDWARE_OPTIMIZATIONS=ON -DPNG_ARM_NEON=ON -DCMAKE_SYSTEM_PROCESSOR="aarch64")
+ set(PNG_EXTRA_ARGS ${PNG_EXTRA_ARGS} -DPNG_HARDWARE_OPTIMIZATIONS=ON -DPNG_ARM_NEON=on -DCMAKE_SYSTEM_PROCESSOR="aarch64")
endif()
ExternalProject_Add(external_png
diff --git a/build_files/build_environment/cmake/versions.cmake b/build_files/build_environment/cmake/versions.cmake
index bc220c596c1..d1675bdddfd 100644
--- a/build_files/build_environment/cmake/versions.cmake
+++ b/build_files/build_environment/cmake/versions.cmake
@@ -158,10 +158,18 @@ set(LLVM_HASH 5a4fab4d7fc84aefffb118ac2c8a4fc0)
set(LLVM_HASH_TYPE MD5)
set(LLVM_FILE llvm-project-${LLVM_VERSION}.src.tar.xz)
-set(OPENMP_URI https://github.com/llvm/llvm-project/releases/download/llvmorg-${LLVM_VERSION}/openmp-${LLVM_VERSION}.src.tar.xz)
-set(OPENMP_HASH ac48ce3e4582ccb82f81ab59eb3fc9dc)
+if(APPLE)
+ # Cloth physics test is crashing due to this bug:
+ # https://bugs.llvm.org/show_bug.cgi?id=50579
+ set(OPENMP_VERSION 9.0.1)
+ set(OPENMP_HASH 6eade16057edbdecb3c4eef9daa2bfcf)
+else()
+ set(OPENMP_VERSION ${LLVM_VERSION})
+ set(OPENMP_HASH ac48ce3e4582ccb82f81ab59eb3fc9dc)
+endif()
+set(OPENMP_URI https://github.com/llvm/llvm-project/releases/download/llvmorg-${OPENMP_VERSION}/openmp-${OPENMP_VERSION}.src.tar.xz)
set(OPENMP_HASH_TYPE MD5)
-set(OPENMP_FILE openmp-${LLVM_VERSION}.src.tar.xz)
+set(OPENMP_FILE openmp-${OPENMP_VERSION}.src.tar.xz)
set(OPENIMAGEIO_VERSION 2.2.15.1)
set(OPENIMAGEIO_URI https://github.com/OpenImageIO/oiio/archive/Release-${OPENIMAGEIO_VERSION}.tar.gz)
diff --git a/build_files/build_environment/patches/openmp.diff b/build_files/build_environment/patches/openmp.diff
new file mode 100644
index 00000000000..201ab5c7713
--- /dev/null
+++ b/build_files/build_environment/patches/openmp.diff
@@ -0,0 +1,23 @@
+diff --git a/runtime/src/z_Linux_asm.S b/runtime/src/z_Linux_asm.S
+index 0d8885e..42aa5ad 100644
+--- a/runtime/src/z_Linux_asm.S
++++ b/runtime/src/z_Linux_asm.S
+@@ -1540,10 +1540,12 @@ __kmp_unnamed_critical_addr:
+ .comm .gomp_critical_user_,32,8
+ .data
+ .align 8
+- .global __kmp_unnamed_critical_addr
+-__kmp_unnamed_critical_addr:
++ .global ___kmp_unnamed_critical_addr
++___kmp_unnamed_critical_addr:
+ .8byte .gomp_critical_user_
+- .size __kmp_unnamed_critical_addr,8
++# if !(KMP_OS_DARWIN)
++ .size ___kmp_unnamed_critical_addr,8
++# endif
+ #endif /* KMP_ARCH_PPC64 || KMP_ARCH_AARCH64 */
+
+ #if KMP_OS_LINUX
+
+
+
diff --git a/build_files/cmake/platform/platform_apple.cmake b/build_files/cmake/platform/platform_apple.cmake
index a130d265dff..dceafb236de 100644
--- a/build_files/cmake/platform/platform_apple.cmake
+++ b/build_files/cmake/platform/platform_apple.cmake
@@ -500,17 +500,10 @@ endif()
# makesdna, tests, etc.), we add an rpath to the OpenMP library dir through
# CMAKE_BUILD_RPATH. This avoids having to make many copies of the dylib next to each binary.
#
-# For the installed Blender executable, CMAKE_INSTALL_RPATH will be used
-# to locate the dylibs at @executable_path, next to the Blender executable.
-#
-# For the installed Python module, CMAKE_INSTALL_RPATH is modified to find the
-# dylib in an adjacent folder.
+# For the installed Python module and installed Blender executable, CMAKE_INSTALL_RPATH
+# is modified to find the dylib in an adjacent folder. Install step puts the libraries there.
set(CMAKE_SKIP_BUILD_RPATH FALSE)
list(APPEND CMAKE_BUILD_RPATH "${OpenMP_LIBRARY_DIR}")
set(CMAKE_SKIP_INSTALL_RPATH FALSE)
-list(APPEND CMAKE_INSTALL_RPATH "@executable_path")
-
-if(WITH_PYTHON_MODULE)
- list(APPEND CMAKE_INSTALL_RPATH "@loader_path/../Resources/${BLENDER_VERSION}/lib")
-endif()
+list(APPEND CMAKE_INSTALL_RPATH "@loader_path/../Resources/${BLENDER_VERSION}/lib")
diff --git a/build_files/windows/doc_py.cmd b/build_files/windows/doc_py.cmd
new file mode 100644
index 00000000000..d33a0289083
--- /dev/null
+++ b/build_files/windows/doc_py.cmd
@@ -0,0 +1,34 @@
+set SOURCEDIR=%BLENDER_DIR%/doc/python_api/sphinx-in
+set BUILDDIR=%BLENDER_DIR%/doc/python_api/sphinx-out
+if "%BF_LANG%" == "" set BF_LANG=en
+set SPHINXOPTS=-j auto -D language=%BF_LANG%
+
+call "%~dp0\find_sphinx.cmd"
+
+if EXIST "%SPHINX_BIN%" (
+ goto detect_sphinx_done
+)
+
+echo unable to locate sphinx-build, run "set sphinx_BIN=full_path_to_sphinx-build.exe"
+exit /b 1
+
+:detect_sphinx_done
+
+call "%~dp0\find_blender.cmd"
+
+if EXIST "%BLENDER_BIN%" (
+ goto detect_blender_done
+)
+
+echo unable to locate blender, run "set BLENDER_BIN=full_path_to_blender.exe"
+exit /b 1
+
+:detect_blender_done
+
+%BLENDER_BIN% ^
+ --background -noaudio --factory-startup ^
+ --python %BLENDER_DIR%/doc/python_api/sphinx_doc_gen.py
+
+"%SPHINX_BIN%" -b html %SPHINXOPTS% %O% %SOURCEDIR% %BUILDDIR%
+
+:EOF
diff --git a/build_files/windows/find_sphinx.cmd b/build_files/windows/find_sphinx.cmd
new file mode 100644
index 00000000000..24238e96768
--- /dev/null
+++ b/build_files/windows/find_sphinx.cmd
@@ -0,0 +1,23 @@
+REM First see if there is an environment variable set
+if EXIST "%SPHINX_BIN%" (
+ goto detect_sphinx_done
+)
+
+REM Then see if inkscape is available in the path
+for %%X in (sphinx-build.exe) do (set SPHINX_BIN=%%~$PATH:X)
+if EXIST "%SPHINX_BIN%" (
+ goto detect_sphinx_done
+)
+
+echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
+echo.installed, then set the SPHINX_BIN environment variable to point
+echo.to the full path of the 'sphinx-build' executable. Alternatively you
+echo.may add the Sphinx directory to PATH.
+echo.
+echo.If you don't have Sphinx installed, grab it from
+echo.http://sphinx-doc.org/
+
+REM If still not found clear the variable
+set SPHINX_BIN=
+
+:detect_sphinx_done
diff --git a/build_files/windows/parse_arguments.cmd b/build_files/windows/parse_arguments.cmd
index c71093f2394..c63f062dfef 100644
--- a/build_files/windows/parse_arguments.cmd
+++ b/build_files/windows/parse_arguments.cmd
@@ -113,6 +113,9 @@ if NOT "%1" == "" (
) else if "%1" == "icons_geom" (
set ICONS_GEOM=1
goto EOF
+ ) else if "%1" == "doc_py" (
+ set DOC_PY=1
+ goto EOF
) else (
echo Command "%1" unknown, aborting!
goto ERR
diff --git a/build_files/windows/reset_variables.cmd b/build_files/windows/reset_variables.cmd
index 590d4ca246a..8ba7b4d3307 100644
--- a/build_files/windows/reset_variables.cmd
+++ b/build_files/windows/reset_variables.cmd
@@ -32,4 +32,5 @@ set FORMAT=
set TEST=
set BUILD_WITH_SCCACHE=
set ICONS=
-set ICONS_GEOM= \ No newline at end of file
+set ICONS_GEOM=
+set DOC_PY=
diff --git a/build_files/windows/show_help.cmd b/build_files/windows/show_help.cmd
index ee5e9d9dbbd..d914ecab2b8 100644
--- a/build_files/windows/show_help.cmd
+++ b/build_files/windows/show_help.cmd
@@ -32,6 +32,10 @@ echo - 2019pre ^(build with visual studio 2019 pre-release^)
echo - 2019b ^(build with visual studio 2019 Build Tools^)
echo.
+echo Documentation Targets ^(Not associated with building^)
+echo - doc_py ^(Generate sphinx python api docs^)
+
+echo.
echo Experimental options
echo - with_opengl_tests ^(enable both the render and draw opengl test suites^)
echo - clang ^(enable building with clang^)
diff --git a/doc/blender_file_format/BlendFileReader.py b/doc/blender_file_format/BlendFileReader.py
index a2f214bc4fc..1e66fc55ab0 100644
--- a/doc/blender_file_format/BlendFileReader.py
+++ b/doc/blender_file_format/BlendFileReader.py
@@ -123,7 +123,7 @@ def Align(handle):
class BlendFile:
'''
Reads a blendfile and store the header, all the fileblocks, and catalogue
- structs foound in the DNA fileblock
+ structs found in the DNA fileblock
- BlendFile.Header (BlendFileHeader instance)
- BlendFile.Blocks (list of BlendFileBlock instances)
diff --git a/doc/python_api/sphinx_doc_gen.py b/doc/python_api/sphinx_doc_gen.py
index d6c1d7b51b8..43d0319b73f 100644
--- a/doc/python_api/sphinx_doc_gen.py
+++ b/doc/python_api/sphinx_doc_gen.py
@@ -1047,7 +1047,7 @@ context_type_map = {
"annotation_data": ("GreasePencil", False),
"annotation_data_owner": ("ID", False),
"armature": ("Armature", False),
- "asset_library": ("AssetLibraryReference", False),
+ "asset_library_ref": ("AssetLibraryReference", False),
"bone": ("Bone", False),
"brush": ("Brush", False),
"camera": ("Camera", False),
diff --git a/extern/audaspace/bindings/python/setup.py.in b/extern/audaspace/bindings/python/setup.py.in
index add1a2d1475..5ad1a37db3a 100644
--- a/extern/audaspace/bindings/python/setup.py.in
+++ b/extern/audaspace/bindings/python/setup.py.in
@@ -1,4 +1,4 @@
-# -*- coding: utf-8 -*-
+# -*- coding: utf-8 -*-
import sys
import os
diff --git a/extern/nanosvg/README.blender b/extern/nanosvg/README.blender
new file mode 100644
index 00000000000..701b5100ca5
--- /dev/null
+++ b/extern/nanosvg/README.blender
@@ -0,0 +1,7 @@
+Project: NanoSVG
+URL: https://github.com/memononen/nanosvg
+License: zlib
+Upstream version:
+Local modifications: Added some functionality to manage grease pencil layers
+
+Added a fix to SVG import arc and float errors (https://developer.blender.org/rB11dc674c78b49fc4e0b7c134c375b6c8b8eacbcc)
diff --git a/source/blender/io/gpencil/nanosvg/nanosvg.h b/extern/nanosvg/nanosvg.h
index 94dad37861a..94dad37861a 100644
--- a/source/blender/io/gpencil/nanosvg/nanosvg.h
+++ b/extern/nanosvg/nanosvg.h
diff --git a/extern/nanosvg/patches/NanoSVG.diff b/extern/nanosvg/patches/NanoSVG.diff
new file mode 100644
index 00000000000..68dbb18573b
--- /dev/null
+++ b/extern/nanosvg/patches/NanoSVG.diff
@@ -0,0 +1,86 @@
+diff --git a/c:/tmp/nanosvg_original.h b/c:/tmp/nanosvg_modif.h
+index 24a01a86d3d..eca0d07e79d 100644
+--- a/c:/tmp/nanosvg_original.h
++++ b/c:/tmp/nanosvg_modif.h
+@@ -24,7 +24,8 @@
+ *
+ * Bounding box calculation based on http://blog.hackers-cafe.net/2009/06/how-to-calculate-bezier-curves-bounding.html
+ *
+- */
++ * This is a modified version for Blender used by importers.
++ **/
+
+ #ifndef NANOSVG_H
+ #define NANOSVG_H
+@@ -148,6 +149,8 @@ extern "C" {
+ typedef struct NSVGshape
+ {
+ char id[64]; // Optional 'id' attr of the shape or its group
++ /* Blender: Parent ID used for layer creation. */
++ char id_parent[64];
+ NSVGpaint fill; // Fill paint
+ NSVGpaint stroke; // Stroke paint
+ float opacity; // Opacity of the shape.
+@@ -370,6 +373,7 @@ int nsvg__parseXML(char* input,
+ /* Simple SVG parser. */
+
+ #define NSVG_MAX_ATTR 128
++#define NSVG_MAX_BREADCRUMB 5
+
+ enum NSVGgradientUnits
+ {
+@@ -471,6 +475,10 @@ typedef struct NSVGparser
+ float dpi;
+ char pathFlag;
+ char defsFlag;
++ /** Blender breadcrumb for layers. */
++ char breadcrumb[NSVG_MAX_BREADCRUMB][64];
++ /** Blender number of elements in breadcrumb. */
++ int breadcrumb_len;
+ } NSVGparser;
+
+ static void nsvg__xformIdentity(float* t)
+@@ -980,6 +988,14 @@ static void nsvg__addShape(NSVGparser* p)
+ memset(shape, 0, sizeof(NSVGshape));
+
+ memcpy(shape->id, attr->id, sizeof shape->id);
++ /* Copy parent id from breadcrumb. */
++ if (p->breadcrumb_len > 0) {
++ memcpy(shape->id_parent, p->breadcrumb[0], sizeof shape->id_parent);
++ }
++ else {
++ memcpy(shape->id_parent, attr->id, sizeof shape->id_parent);
++ }
++
+ scale = nsvg__getAverageScale(attr->xform);
+ shape->strokeWidth = attr->strokeWidth * scale;
+ shape->strokeDashOffset = attr->strokeDashOffset * scale;
+@@ -2814,6 +2830,14 @@ static void nsvg__startElement(void* ud, const char* el, const char** attr)
+ if (strcmp(el, "g") == 0) {
+ nsvg__pushAttr(p);
+ nsvg__parseAttribs(p, attr);
++
++ /* Save the breadcrumb of groups. */
++ if (p->breadcrumb_len < NSVG_MAX_BREADCRUMB) {
++ NSVGattrib *attr_id = nsvg__getAttr(p);
++ memcpy(
++ p->breadcrumb[p->breadcrumb_len], attr_id->id, sizeof(p->breadcrumb[p->breadcrumb_len]));
++ p->breadcrumb_len++;
++ }
+ }
+ else if (strcmp(el, "path") == 0) {
+ if (p->pathFlag) // Do not allow nested paths.
+@@ -2874,7 +2898,12 @@ static void nsvg__endElement(void* ud, const char* el)
+ NSVGparser* p = (NSVGparser*)ud;
+
+ if (strcmp(el, "g") == 0) {
+- nsvg__popAttr(p);
++ /* Remove the breadcrumb level. */
++ if (p->breadcrumb_len > 0) {
++ p->breadcrumb[p->breadcrumb_len - 1][0] = '\0';
++ p->breadcrumb_len--;
++ }
++ nsvg__popAttr(p);
+ }
+ else if (strcmp(el, "path") == 0) {
+ p->pathFlag = 0;
diff --git a/intern/cycles/blender/blender_python.cpp b/intern/cycles/blender/blender_python.cpp
index fd145effde7..6e06b6a468f 100644
--- a/intern/cycles/blender/blender_python.cpp
+++ b/intern/cycles/blender/blender_python.cpp
@@ -487,6 +487,24 @@ static PyObject *osl_update_node_func(PyObject * /*self*/, PyObject *args)
if (param->varlenarray || param->isstruct || param->type.arraylen > 1)
continue;
+ /* Read metadata. */
+ bool is_bool_param = false;
+ ustring param_label = param->name;
+
+ for (const OSL::OSLQuery::Parameter &metadata : param->metadata) {
+ if (metadata.type == TypeDesc::STRING) {
+ if (metadata.name == "widget") {
+ /* Boolean socket. */
+ if (metadata.sdefault[0] == "boolean" || metadata.sdefault[0] == "checkBox") {
+ is_bool_param = true;
+ }
+ }
+ else if (metadata.name == "label") {
+ /* Socket label. */
+ param_label = metadata.sdefault[0];
+ }
+ }
+ }
/* determine socket type */
string socket_type;
BL::NodeSocket::type_enum data_type = BL::NodeSocket::type_VALUE;
@@ -494,6 +512,7 @@ static PyObject *osl_update_node_func(PyObject * /*self*/, PyObject *args)
float default_float = 0.0f;
int default_int = 0;
string default_string = "";
+ bool default_boolean = false;
if (param->isclosure) {
socket_type = "NodeSocketShader";
@@ -523,10 +542,19 @@ static PyObject *osl_update_node_func(PyObject * /*self*/, PyObject *args)
}
else if (param->type.aggregate == TypeDesc::SCALAR) {
if (param->type.basetype == TypeDesc::INT) {
- socket_type = "NodeSocketInt";
- data_type = BL::NodeSocket::type_INT;
- if (param->validdefault)
- default_int = param->idefault[0];
+ if (is_bool_param) {
+ socket_type = "NodeSocketBool";
+ data_type = BL::NodeSocket::type_BOOLEAN;
+ if (param->validdefault) {
+ default_boolean = (bool)param->idefault[0];
+ }
+ }
+ else {
+ socket_type = "NodeSocketInt";
+ data_type = BL::NodeSocket::type_INT;
+ if (param->validdefault)
+ default_int = param->idefault[0];
+ }
}
else if (param->type.basetype == TypeDesc::FLOAT) {
socket_type = "NodeSocketFloat";
@@ -546,33 +574,57 @@ static PyObject *osl_update_node_func(PyObject * /*self*/, PyObject *args)
else
continue;
- /* find socket socket */
- BL::NodeSocket b_sock(PointerRNA_NULL);
+ /* Update existing socket. */
+ bool found_existing = false;
if (param->isoutput) {
- b_sock = b_node.outputs[param->name.string()];
- /* remove if type no longer matches */
- if (b_sock && b_sock.bl_idname() != socket_type) {
- b_node.outputs.remove(b_data, b_sock);
- b_sock = BL::NodeSocket(PointerRNA_NULL);
+ for (BL::NodeSocket &b_sock : b_node.outputs) {
+ if (b_sock.identifier() == param->name) {
+ if (b_sock.bl_idname() != socket_type) {
+ /* Remove if type no longer matches. */
+ b_node.outputs.remove(b_data, b_sock);
+ }
+ else {
+ /* Reuse and update label. */
+ if (b_sock.name() != param_label) {
+ b_sock.name(param_label.string());
+ }
+ used_sockets.insert(b_sock.ptr.data);
+ found_existing = true;
+ }
+ break;
+ }
}
}
else {
- b_sock = b_node.inputs[param->name.string()];
- /* remove if type no longer matches */
- if (b_sock && b_sock.bl_idname() != socket_type) {
- b_node.inputs.remove(b_data, b_sock);
- b_sock = BL::NodeSocket(PointerRNA_NULL);
+ for (BL::NodeSocket &b_sock : b_node.inputs) {
+ if (b_sock.identifier() == param->name) {
+ if (b_sock.bl_idname() != socket_type) {
+ /* Remove if type no longer matches. */
+ b_node.inputs.remove(b_data, b_sock);
+ }
+ else {
+ /* Reuse and update label. */
+ if (b_sock.name() != param_label) {
+ b_sock.name(param_label.string());
+ }
+ used_sockets.insert(b_sock.ptr.data);
+ found_existing = true;
+ }
+ break;
+ }
}
}
- if (!b_sock) {
- /* create new socket */
- if (param->isoutput)
- b_sock = b_node.outputs.create(
- b_data, socket_type.c_str(), param->name.c_str(), param->name.c_str());
- else
- b_sock = b_node.inputs.create(
- b_data, socket_type.c_str(), param->name.c_str(), param->name.c_str());
+ if (!found_existing) {
+ /* Create new socket. */
+ BL::NodeSocket b_sock = (param->isoutput) ? b_node.outputs.create(b_data,
+ socket_type.c_str(),
+ param_label.c_str(),
+ param->name.c_str()) :
+ b_node.inputs.create(b_data,
+ socket_type.c_str(),
+ param_label.c_str(),
+ param->name.c_str());
/* set default value */
if (data_type == BL::NodeSocket::type_VALUE) {
@@ -590,9 +642,12 @@ static PyObject *osl_update_node_func(PyObject * /*self*/, PyObject *args)
else if (data_type == BL::NodeSocket::type_STRING) {
set_string(b_sock.ptr, "default_value", default_string);
}
- }
+ else if (data_type == BL::NodeSocket::type_BOOLEAN) {
+ set_boolean(b_sock.ptr, "default_value", default_boolean);
+ }
- used_sockets.insert(b_sock.ptr.data);
+ used_sockets.insert(b_sock.ptr.data);
+ }
}
/* remove unused parameters */
diff --git a/intern/cycles/blender/blender_shader.cpp b/intern/cycles/blender/blender_shader.cpp
index 7f129310736..1404c58290d 100644
--- a/intern/cycles/blender/blender_shader.cpp
+++ b/intern/cycles/blender/blender_shader.cpp
@@ -149,7 +149,7 @@ BlenderAttributeType blender_attribute_name_split_type(ustring name, string *r_r
static BL::NodeSocket get_node_output(BL::Node &b_node, const string &name)
{
for (BL::NodeSocket &b_out : b_node.outputs) {
- if (b_out.name() == name) {
+ if (b_out.identifier() == name) {
return b_out;
}
}
@@ -215,7 +215,12 @@ static void set_default_value(ShaderInput *input,
break;
}
case SocketType::INT: {
- node->set(socket, get_int(b_sock.ptr, "default_value"));
+ if (b_sock.type() == BL::NodeSocket::type_BOOLEAN) {
+ node->set(socket, get_boolean(b_sock.ptr, "default_value"));
+ }
+ else {
+ node->set(socket, get_int(b_sock.ptr, "default_value"));
+ }
break;
}
case SocketType::COLOR: {
@@ -1002,71 +1007,48 @@ static bool node_use_modified_socket_name(ShaderNode *node)
return true;
}
-static ShaderInput *node_find_input_by_name(ShaderNode *node,
- BL::Node &b_node,
- BL::NodeSocket &b_socket)
+static ShaderInput *node_find_input_by_name(ShaderNode *node, BL::NodeSocket &b_socket)
{
- string name = b_socket.name();
+ string name = b_socket.identifier();
+ ShaderInput *input = node->input(name.c_str());
- if (node_use_modified_socket_name(node)) {
- bool found = false;
- int counter = 0, total = 0;
+ if (!input && node_use_modified_socket_name(node)) {
+ /* Different internal name for shader. */
+ if (string_startswith(name, "Shader")) {
+ string_replace(name, "Shader", "Closure");
+ }
+ input = node->input(name.c_str());
- for (BL::NodeSocket &b_input : b_node.inputs) {
- if (b_input.name() == name) {
- if (!found) {
- counter++;
- }
- total++;
+ if (!input) {
+ /* Different internal numbering of two sockets with same name. */
+ if (string_endswith(name, "_001")) {
+ string_replace(name, "_001", "2");
+ }
+ else {
+ name += "1";
}
- if (b_input.ptr.data == b_socket.ptr.data)
- found = true;
+ input = node->input(name.c_str());
}
-
- /* rename if needed */
- if (name == "Shader")
- name = "Closure";
-
- if (total > 1)
- name = string_printf("%s%d", name.c_str(), counter);
}
- return node->input(name.c_str());
+ return input;
}
-static ShaderOutput *node_find_output_by_name(ShaderNode *node,
- BL::Node &b_node,
- BL::NodeSocket &b_socket)
+static ShaderOutput *node_find_output_by_name(ShaderNode *node, BL::NodeSocket &b_socket)
{
- string name = b_socket.name();
+ string name = b_socket.identifier();
+ ShaderOutput *output = node->output(name.c_str());
- if (node_use_modified_socket_name(node)) {
- bool found = false;
- int counter = 0, total = 0;
-
- for (BL::NodeSocket &b_output : b_node.outputs) {
- if (b_output.name() == name) {
- if (!found) {
- counter++;
- }
- total++;
- }
-
- if (b_output.ptr.data == b_socket.ptr.data) {
- found = true;
- }
- }
-
- /* rename if needed */
- if (name == "Shader")
+ if (!output && node_use_modified_socket_name(node)) {
+ /* Different internal name for shader. */
+ if (name == "Shader") {
name = "Closure";
-
- if (total > 1)
- name = string_printf("%s%d", name.c_str(), counter);
+ output = node->output(name.c_str());
+ }
}
- return node->output(name.c_str());
+ return output;
}
static void add_nodes(Scene *scene,
@@ -1209,7 +1191,7 @@ static void add_nodes(Scene *scene,
if (node) {
/* map node sockets for linking */
for (BL::NodeSocket &b_input : b_node.inputs) {
- ShaderInput *input = node_find_input_by_name(node, b_node, b_input);
+ ShaderInput *input = node_find_input_by_name(node, b_input);
if (!input) {
/* XXX should not happen, report error? */
continue;
@@ -1219,7 +1201,7 @@ static void add_nodes(Scene *scene,
set_default_value(input, b_input, b_data, b_ntree);
}
for (BL::NodeSocket &b_output : b_node.outputs) {
- ShaderOutput *output = node_find_output_by_name(node, b_node, b_output);
+ ShaderOutput *output = node_find_output_by_name(node, b_output);
if (!output) {
/* XXX should not happen, report error? */
continue;
diff --git a/intern/cycles/blender/blender_util.h b/intern/cycles/blender/blender_util.h
index 2b2188b023d..82da3512269 100644
--- a/intern/cycles/blender/blender_util.h
+++ b/intern/cycles/blender/blender_util.h
@@ -145,7 +145,7 @@ static inline void curvemapping_minmax(/*const*/ BL::CurveMapping &cumap,
float *min_x,
float *max_x)
{
- /* const int num_curves = cumap.curves.length(); */ /* Gives linking error so far. */
+ // const int num_curves = cumap.curves.length(); /* Gives linking error so far. */
const int num_curves = rgb_curve ? 4 : 3;
*min_x = FLT_MAX;
*max_x = -FLT_MAX;
diff --git a/intern/cycles/render/session.cpp b/intern/cycles/render/session.cpp
index 19d4a66353d..1b91c49f0ea 100644
--- a/intern/cycles/render/session.cpp
+++ b/intern/cycles/render/session.cpp
@@ -57,23 +57,26 @@ Session::Session(const SessionParams &params_)
stats(),
profiler()
{
- device_use_gl = ((params.device.type != DEVICE_CPU) && !params.background);
+ device_use_gl_ = ((params.device.type != DEVICE_CPU) && !params.background);
TaskScheduler::init(params.threads);
- session_thread = NULL;
+ session_thread_ = NULL;
scene = NULL;
- reset_time = 0.0;
- last_update_time = 0.0;
+ reset_time_ = 0.0;
+ last_update_time_ = 0.0;
- delayed_reset.do_reset = false;
- delayed_reset.samples = 0;
+ delayed_reset_.do_reset = false;
+ delayed_reset_.samples = 0;
- display_outdated = false;
- gpu_draw_ready = false;
- gpu_need_display_buffer_update = false;
- pause = false;
+ display_outdated_ = false;
+ gpu_draw_ready_ = false;
+ gpu_need_display_buffer_update_ = false;
+
+ pause_ = false;
+ cancel_ = false;
+ new_work_added_ = false;
buffers = NULL;
display = NULL;
@@ -127,25 +130,26 @@ Session::~Session()
void Session::start()
{
- if (!session_thread) {
- session_thread = new thread(function_bind(&Session::run, this));
+ if (!session_thread_) {
+ session_thread_ = new thread(function_bind(&Session::run, this));
}
}
void Session::cancel()
{
- if (session_thread) {
+ if (session_thread_) {
/* wait for session thread to end */
progress.set_cancel("Exiting");
- gpu_need_display_buffer_update = false;
- gpu_need_display_buffer_update_cond.notify_all();
+ gpu_need_display_buffer_update_ = false;
+ gpu_need_display_buffer_update_cond_.notify_all();
{
- thread_scoped_lock pause_lock(pause_mutex);
- pause = false;
+ thread_scoped_lock pause_lock(pause_mutex_);
+ pause_ = false;
+ cancel_ = true;
}
- pause_cond.notify_all();
+ pause_cond_.notify_all();
wait();
}
@@ -153,9 +157,9 @@ void Session::cancel()
bool Session::ready_to_reset()
{
- double dt = time_dt() - reset_time;
+ double dt = time_dt() - reset_time_;
- if (!display_outdated)
+ if (!display_outdated_)
return (dt > params.reset_timeout);
else
return (dt > params.cancel_timeout);
@@ -165,48 +169,50 @@ bool Session::ready_to_reset()
void Session::reset_gpu(BufferParams &buffer_params, int samples)
{
- thread_scoped_lock pause_lock(pause_mutex);
+ thread_scoped_lock pause_lock(pause_mutex_);
/* block for buffer access and reset immediately. we can't do this
* in the thread, because we need to allocate an OpenGL buffer, and
* that only works in the main thread */
- thread_scoped_lock display_lock(display_mutex);
- thread_scoped_lock buffers_lock(buffers_mutex);
+ thread_scoped_lock display_lock(display_mutex_);
+ thread_scoped_lock buffers_lock(buffers_mutex_);
- display_outdated = true;
- reset_time = time_dt();
+ display_outdated_ = true;
+ reset_time_ = time_dt();
reset_(buffer_params, samples);
- gpu_need_display_buffer_update = false;
- gpu_need_display_buffer_update_cond.notify_all();
+ gpu_need_display_buffer_update_ = false;
+ gpu_need_display_buffer_update_cond_.notify_all();
+
+ new_work_added_ = true;
- pause_cond.notify_all();
+ pause_cond_.notify_all();
}
bool Session::draw_gpu(BufferParams &buffer_params, DeviceDrawParams &draw_params)
{
/* block for buffer access */
- thread_scoped_lock display_lock(display_mutex);
+ thread_scoped_lock display_lock(display_mutex_);
/* first check we already rendered something */
- if (gpu_draw_ready) {
+ if (gpu_draw_ready_) {
/* then verify the buffers have the expected size, so we don't
* draw previous results in a resized window */
if (buffer_params.width == display->params.width &&
buffer_params.height == display->params.height) {
/* for CUDA we need to do tone-mapping still, since we can
* only access GL buffers from the main thread. */
- if (gpu_need_display_buffer_update) {
- thread_scoped_lock buffers_lock(buffers_mutex);
+ if (gpu_need_display_buffer_update_) {
+ thread_scoped_lock buffers_lock(buffers_mutex_);
copy_to_display_buffer(tile_manager.state.sample);
- gpu_need_display_buffer_update = false;
- gpu_need_display_buffer_update_cond.notify_all();
+ gpu_need_display_buffer_update_ = false;
+ gpu_need_display_buffer_update_cond_.notify_all();
}
display->draw(device, draw_params);
- if (display_outdated && (time_dt() - reset_time) > params.text_timeout)
+ if (display_outdated_ && (time_dt() - reset_time_) > params.text_timeout)
return false;
return true;
@@ -220,9 +226,9 @@ void Session::run_gpu()
{
bool tiles_written = false;
- reset_time = time_dt();
- last_update_time = time_dt();
- last_display_time = last_update_time;
+ reset_time_ = time_dt();
+ last_update_time_ = time_dt();
+ last_display_time_ = last_update_time_;
progress.set_render_start_time();
@@ -255,7 +261,7 @@ void Session::run_gpu()
/* buffers mutex is locked entirely while rendering each
* sample, and released/reacquired on each iteration to allow
* reset and draw in between */
- thread_scoped_lock buffers_lock(buffers_mutex);
+ thread_scoped_lock buffers_lock(buffers_mutex_);
/* update status and timing */
update_status_time();
@@ -273,17 +279,17 @@ void Session::run_gpu()
/* update status and timing */
update_status_time();
- gpu_need_display_buffer_update = !delayed_denoise;
- gpu_draw_ready = true;
+ gpu_need_display_buffer_update_ = !delayed_denoise;
+ gpu_draw_ready_ = true;
progress.set_update();
/* wait for until display buffer is updated */
if (!params.background) {
- while (gpu_need_display_buffer_update) {
+ while (gpu_need_display_buffer_update_) {
if (progress.get_cancel())
break;
- gpu_need_display_buffer_update_cond.wait(buffers_lock);
+ gpu_need_display_buffer_update_cond_.wait(buffers_lock);
}
}
@@ -305,23 +311,23 @@ void Session::run_gpu()
void Session::reset_cpu(BufferParams &buffer_params, int samples)
{
- thread_scoped_lock reset_lock(delayed_reset.mutex);
- thread_scoped_lock pause_lock(pause_mutex);
+ thread_scoped_lock reset_lock(delayed_reset_.mutex);
+ thread_scoped_lock pause_lock(pause_mutex_);
- display_outdated = true;
- reset_time = time_dt();
+ display_outdated_ = true;
+ reset_time_ = time_dt();
- delayed_reset.params = buffer_params;
- delayed_reset.samples = samples;
- delayed_reset.do_reset = true;
+ delayed_reset_.params = buffer_params;
+ delayed_reset_.samples = samples;
+ delayed_reset_.do_reset = true;
device->task_cancel();
- pause_cond.notify_all();
+ pause_cond_.notify_all();
}
bool Session::draw_cpu(BufferParams &buffer_params, DeviceDrawParams &draw_params)
{
- thread_scoped_lock display_lock(display_mutex);
+ thread_scoped_lock display_lock(display_mutex_);
/* first check we already rendered something */
if (display->draw_ready()) {
@@ -331,7 +337,7 @@ bool Session::draw_cpu(BufferParams &buffer_params, DeviceDrawParams &draw_param
buffer_params.height == display->params.height) {
display->draw(device, draw_params);
- if (display_outdated && (time_dt() - reset_time) > params.text_timeout)
+ if (display_outdated_ && (time_dt() - reset_time_) > params.text_timeout)
return false;
return true;
@@ -345,46 +351,46 @@ bool Session::steal_tile(RenderTile &rtile, Device *tile_device, thread_scoped_l
{
/* Devices that can get their tiles stolen don't steal tiles themselves.
* Additionally, if there are no stealable tiles in flight, give up here. */
- if (tile_device->info.type == DEVICE_CPU || stealable_tiles == 0) {
+ if (tile_device->info.type == DEVICE_CPU || stealable_tiles_ == 0) {
return false;
}
/* Wait until no other thread is trying to steal a tile. */
- while (tile_stealing_state != NOT_STEALING && stealable_tiles > 0) {
+ while (tile_stealing_state_ != NOT_STEALING && stealable_tiles_ > 0) {
/* Someone else is currently trying to get a tile.
* Wait on the condition variable and try later. */
- tile_steal_cond.wait(tile_lock);
+ tile_steal_cond_.wait(tile_lock);
}
/* If another thread stole the last stealable tile in the meantime, give up. */
- if (stealable_tiles == 0) {
+ if (stealable_tiles_ == 0) {
return false;
}
/* There are stealable tiles in flight, so signal that one should be released. */
- tile_stealing_state = WAITING_FOR_TILE;
+ tile_stealing_state_ = WAITING_FOR_TILE;
/* Wait until a device notices the signal and releases its tile. */
- while (tile_stealing_state != GOT_TILE && stealable_tiles > 0) {
- tile_steal_cond.wait(tile_lock);
+ while (tile_stealing_state_ != GOT_TILE && stealable_tiles_ > 0) {
+ tile_steal_cond_.wait(tile_lock);
}
/* If the last stealable tile finished on its own, give up. */
- if (tile_stealing_state != GOT_TILE) {
- tile_stealing_state = NOT_STEALING;
+ if (tile_stealing_state_ != GOT_TILE) {
+ tile_stealing_state_ = NOT_STEALING;
return false;
}
/* Successfully stole a tile, now move it to the new device. */
- rtile = stolen_tile;
+ rtile = stolen_tile_;
rtile.buffers->buffer.move_device(tile_device);
rtile.buffer = rtile.buffers->buffer.device_pointer;
rtile.stealing_state = RenderTile::NO_STEALING;
rtile.num_samples -= (rtile.sample - rtile.start_sample);
rtile.start_sample = rtile.sample;
- tile_stealing_state = NOT_STEALING;
+ tile_stealing_state_ = NOT_STEALING;
/* Poke any threads which might be waiting for NOT_STEALING above. */
- tile_steal_cond.notify_one();
+ tile_steal_cond_.notify_one();
return true;
}
@@ -394,7 +400,7 @@ bool Session::get_tile_stolen()
/* If tile_stealing_state is WAITING_FOR_TILE, atomically set it to RELEASING_TILE
* and return true. */
TileStealingState expected = WAITING_FOR_TILE;
- return tile_stealing_state.compare_exchange_weak(expected, RELEASING_TILE);
+ return tile_stealing_state_.compare_exchange_weak(expected, RELEASING_TILE);
}
bool Session::acquire_tile(RenderTile &rtile, Device *tile_device, uint tile_types)
@@ -406,7 +412,7 @@ bool Session::acquire_tile(RenderTile &rtile, Device *tile_device, uint tile_typ
}
}
- thread_scoped_lock tile_lock(tile_mutex);
+ thread_scoped_lock tile_lock(tile_mutex_);
/* get next tile from manager */
Tile *tile;
@@ -423,7 +429,7 @@ bool Session::acquire_tile(RenderTile &rtile, Device *tile_device, uint tile_typ
/* Wait for denoising tiles to become available */
if ((tile_types & RenderTile::DENOISE) && !progress.get_cancel() && tile_manager.has_tiles()) {
- denoising_cond.wait(tile_lock);
+ denoising_cond_.wait(tile_lock);
continue;
}
@@ -446,7 +452,7 @@ bool Session::acquire_tile(RenderTile &rtile, Device *tile_device, uint tile_typ
}
else {
if (tile_device->info.type == DEVICE_CPU) {
- stealable_tiles++;
+ stealable_tiles_++;
rtile.stealing_state = RenderTile::CAN_BE_STOLEN;
}
@@ -515,7 +521,7 @@ bool Session::acquire_tile(RenderTile &rtile, Device *tile_device, uint tile_typ
/* This will read any passes needed as input for baking. */
if (tile_manager.state.sample == tile_manager.range_start_sample) {
{
- thread_scoped_lock tile_lock(tile_mutex);
+ thread_scoped_lock tile_lock(tile_mutex_);
read_bake_tile_cb(rtile);
}
rtile.buffers->buffer.copy_to_device();
@@ -533,7 +539,7 @@ bool Session::acquire_tile(RenderTile &rtile, Device *tile_device, uint tile_typ
void Session::update_tile_sample(RenderTile &rtile)
{
- thread_scoped_lock tile_lock(tile_mutex);
+ thread_scoped_lock tile_lock(tile_mutex_);
if (update_render_tile_cb) {
if (params.progressive_refine == false) {
@@ -548,25 +554,25 @@ void Session::update_tile_sample(RenderTile &rtile)
void Session::release_tile(RenderTile &rtile, const bool need_denoise)
{
- thread_scoped_lock tile_lock(tile_mutex);
+ thread_scoped_lock tile_lock(tile_mutex_);
if (rtile.stealing_state != RenderTile::NO_STEALING) {
- stealable_tiles--;
+ stealable_tiles_--;
if (rtile.stealing_state == RenderTile::WAS_STOLEN) {
/* If the tile is being stolen, don't release it here - the new device will pick up where
* the old one left off. */
- assert(tile_stealing_state == RELEASING_TILE);
+ assert(tile_stealing_state_ == RELEASING_TILE);
assert(rtile.sample < rtile.start_sample + rtile.num_samples);
- tile_stealing_state = GOT_TILE;
- stolen_tile = rtile;
- tile_steal_cond.notify_all();
+ tile_stealing_state_ = GOT_TILE;
+ stolen_tile_ = rtile;
+ tile_steal_cond_.notify_all();
return;
}
- else if (stealable_tiles == 0) {
+ else if (stealable_tiles_ == 0) {
/* If this was the last stealable tile, wake up any threads still waiting for one. */
- tile_steal_cond.notify_all();
+ tile_steal_cond_.notify_all();
}
}
@@ -595,12 +601,12 @@ void Session::release_tile(RenderTile &rtile, const bool need_denoise)
update_status_time();
/* Notify denoising thread that a tile was finished. */
- denoising_cond.notify_all();
+ denoising_cond_.notify_all();
}
void Session::map_neighbor_tiles(RenderTileNeighbors &neighbors, Device *tile_device)
{
- thread_scoped_lock tile_lock(tile_mutex);
+ thread_scoped_lock tile_lock(tile_mutex_);
const int4 image_region = make_int4(
tile_manager.state.buffer.full_x,
@@ -677,7 +683,7 @@ void Session::map_neighbor_tiles(RenderTileNeighbors &neighbors, Device *tile_de
void Session::unmap_neighbor_tiles(RenderTileNeighbors &neighbors, Device *tile_device)
{
- thread_scoped_lock tile_lock(tile_mutex);
+ thread_scoped_lock tile_lock(tile_mutex_);
device->unmap_neighbor_tiles(tile_device, neighbors);
}
@@ -685,8 +691,8 @@ void Session::run_cpu()
{
bool tiles_written = false;
- last_update_time = time_dt();
- last_display_time = last_update_time;
+ last_update_time_ = time_dt();
+ last_display_time_ = last_update_time_;
while (!progress.get_cancel()) {
const bool no_tiles = !run_update_for_next_iteration();
@@ -718,7 +724,7 @@ void Session::run_cpu()
/* buffers mutex is locked entirely while rendering each
* sample, and released/reacquired on each iteration to allow
* reset and draw in between */
- thread_scoped_lock buffers_lock(buffers_mutex);
+ thread_scoped_lock buffers_lock(buffers_mutex_);
/* update status and timing */
update_status_time();
@@ -741,14 +747,14 @@ void Session::run_cpu()
device->task_wait();
{
- thread_scoped_lock reset_lock(delayed_reset.mutex);
- thread_scoped_lock buffers_lock(buffers_mutex);
- thread_scoped_lock display_lock(display_mutex);
+ thread_scoped_lock reset_lock(delayed_reset_.mutex);
+ thread_scoped_lock buffers_lock(buffers_mutex_);
+ thread_scoped_lock display_lock(display_mutex_);
- if (delayed_reset.do_reset) {
+ if (delayed_reset_.do_reset) {
/* reset rendering if request from main thread */
- delayed_reset.do_reset = false;
- reset_(delayed_reset.params, delayed_reset.samples);
+ delayed_reset_.do_reset = false;
+ reset_(delayed_reset_.params, delayed_reset_.samples);
}
else if (need_copy_to_display_buffer) {
/* Only copy to display_buffer if we do not reset, we don't
@@ -783,7 +789,7 @@ void Session::run()
/* reset number of rendered samples */
progress.reset_sample();
- if (device_use_gl)
+ if (device_use_gl_)
run_gpu();
else
run_cpu();
@@ -801,12 +807,12 @@ void Session::run()
bool Session::run_update_for_next_iteration()
{
thread_scoped_lock scene_lock(scene->mutex);
- thread_scoped_lock reset_lock(delayed_reset.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;
+ 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();
@@ -829,35 +835,43 @@ bool Session::run_wait_for_work(bool no_tiles)
return false;
}
- thread_scoped_lock pause_lock(pause_mutex);
+ thread_scoped_lock pause_lock(pause_mutex_);
- if (!pause && !no_tiles) {
+ if (!pause_ && !no_tiles) {
+ /* Rendering is not paused and there is work to be done. No need to wait for anything. */
return false;
}
- update_status_time(pause, no_tiles);
+ update_status_time(pause_, no_tiles);
- while (true) {
+ /* Only leave the loop when rendering is not paused. But even if the current render is un-paused
+ * but there is nothing to render keep waiting until new work is added. */
+ while (!cancel_) {
scoped_timer pause_timer;
- pause_cond.wait(pause_lock);
- if (pause) {
- progress.add_skip_time(pause_timer, params.background);
+
+ if (!pause_ && (!no_tiles || new_work_added_ || delayed_reset_.do_reset)) {
+ break;
}
- update_status_time(pause, no_tiles);
- progress.set_update();
+ /* Wait for either pause state changed, or extra samples added to render. */
+ pause_cond_.wait(pause_lock);
- if (!pause) {
- break;
+ if (pause_) {
+ progress.add_skip_time(pause_timer, params.background);
}
+
+ update_status_time(pause_, no_tiles);
+ progress.set_update();
}
+ new_work_added_ = false;
+
return no_tiles;
}
bool Session::draw(BufferParams &buffer_params, DeviceDrawParams &draw_params)
{
- if (device_use_gl)
+ if (device_use_gl_)
return draw_gpu(buffer_params, draw_params);
else
return draw_cpu(buffer_params, draw_params);
@@ -866,7 +880,7 @@ bool Session::draw(BufferParams &buffer_params, DeviceDrawParams &draw_params)
void Session::reset_(BufferParams &buffer_params, int samples)
{
if (buffers && buffer_params.modified(tile_manager.params)) {
- gpu_draw_ready = false;
+ gpu_draw_ready_ = false;
buffers->reset(buffer_params);
if (display) {
display->reset(buffer_params);
@@ -874,8 +888,8 @@ void Session::reset_(BufferParams &buffer_params, int samples)
}
tile_manager.reset(buffer_params, samples);
- stealable_tiles = 0;
- tile_stealing_state = NOT_STEALING;
+ stealable_tiles_ = 0;
+ tile_stealing_state_ = NOT_STEALING;
progress.reset_sample();
bool show_progress = params.background || tile_manager.get_num_effective_samples() != INT_MAX;
@@ -888,7 +902,7 @@ void Session::reset_(BufferParams &buffer_params, int samples)
void Session::reset(BufferParams &buffer_params, int samples)
{
- if (device_use_gl)
+ if (device_use_gl_)
reset_gpu(buffer_params, samples);
else
reset_cpu(buffer_params, samples);
@@ -896,30 +910,37 @@ void Session::reset(BufferParams &buffer_params, int samples)
void Session::set_samples(int samples)
{
- if (samples != params.samples) {
- params.samples = samples;
- tile_manager.set_samples(samples);
+ if (samples == params.samples) {
+ return;
+ }
+
+ params.samples = samples;
+ tile_manager.set_samples(samples);
- pause_cond.notify_all();
+ {
+ thread_scoped_lock pause_lock(pause_mutex_);
+ new_work_added_ = true;
}
+
+ pause_cond_.notify_all();
}
-void Session::set_pause(bool pause_)
+void Session::set_pause(bool pause)
{
bool notify = false;
{
- thread_scoped_lock pause_lock(pause_mutex);
+ thread_scoped_lock pause_lock(pause_mutex_);
if (pause != pause_) {
- pause = pause_;
+ pause_ = pause;
notify = true;
}
}
- if (session_thread) {
+ if (session_thread_) {
if (notify) {
- pause_cond.notify_all();
+ pause_cond_.notify_all();
}
}
else if (pause_) {
@@ -932,7 +953,7 @@ void Session::set_denoising(const DenoiseParams &denoising)
bool need_denoise = denoising.need_denoising_task();
/* Lock buffers so no denoising operation is triggered while the settings are changed here. */
- thread_scoped_lock buffers_lock(buffers_mutex);
+ thread_scoped_lock buffers_lock(buffers_mutex_);
params.denoising = denoising;
if (!(params.device.denoisers & denoising.type)) {
@@ -957,18 +978,18 @@ void Session::set_denoising_start_sample(int sample)
if (sample != params.denoising.start_sample) {
params.denoising.start_sample = sample;
- pause_cond.notify_all();
+ pause_cond_.notify_all();
}
}
void Session::wait()
{
- if (session_thread) {
- session_thread->join();
- delete session_thread;
+ if (session_thread_) {
+ session_thread_->join();
+ delete session_thread_;
}
- session_thread = NULL;
+ session_thread_ = NULL;
}
bool Session::update_scene()
@@ -1099,7 +1120,7 @@ bool Session::render_need_denoise(bool &delayed)
/* Avoid excessive denoising in viewport after reaching a certain amount of samples. */
delayed = (tile_manager.state.sample >= 20 &&
- (time_dt() - last_display_time) < params.progressive_update_timeout);
+ (time_dt() - last_display_time_) < params.progressive_update_timeout);
return !delayed;
}
@@ -1197,10 +1218,10 @@ void Session::copy_to_display_buffer(int sample)
/* set display to new size */
display->draw_set(task.w, task.h);
- last_display_time = time_dt();
+ last_display_time_ = time_dt();
}
- display_outdated = false;
+ display_outdated_ = false;
}
bool Session::update_progressive_refine(bool cancel)
@@ -1210,7 +1231,7 @@ bool Session::update_progressive_refine(bool cancel)
double current_time = time_dt();
- if (current_time - last_update_time < params.progressive_update_timeout) {
+ if (current_time - last_update_time_ < params.progressive_update_timeout) {
/* If last sample was processed, we need to write buffers anyway. */
if (!write && sample != 1)
return false;
@@ -1241,7 +1262,7 @@ bool Session::update_progressive_refine(bool cancel)
}
}
- last_update_time = current_time;
+ last_update_time_ = current_time;
return write;
}
diff --git a/intern/cycles/render/session.h b/intern/cycles/render/session.h
index bc3b8366c05..05025c10f9c 100644
--- a/intern/cycles/render/session.h
+++ b/intern/cycles/render/session.h
@@ -174,7 +174,7 @@ class Session {
bool do_reset;
BufferParams params;
int samples;
- } delayed_reset;
+ } delayed_reset_;
void run();
@@ -207,38 +207,41 @@ class Session {
void map_neighbor_tiles(RenderTileNeighbors &neighbors, Device *tile_device);
void unmap_neighbor_tiles(RenderTileNeighbors &neighbors, Device *tile_device);
- bool device_use_gl;
+ bool device_use_gl_;
- thread *session_thread;
+ thread *session_thread_;
- volatile bool display_outdated;
+ volatile bool display_outdated_;
- volatile bool gpu_draw_ready;
- volatile bool gpu_need_display_buffer_update;
- thread_condition_variable gpu_need_display_buffer_update_cond;
+ volatile bool gpu_draw_ready_;
+ volatile bool gpu_need_display_buffer_update_;
+ thread_condition_variable gpu_need_display_buffer_update_cond_;
- bool pause;
- thread_condition_variable pause_cond;
- thread_mutex pause_mutex;
- thread_mutex tile_mutex;
- thread_mutex buffers_mutex;
- thread_mutex display_mutex;
- thread_condition_variable denoising_cond;
- thread_condition_variable tile_steal_cond;
+ bool pause_;
+ bool cancel_;
+ bool new_work_added_;
- double reset_time;
- double last_update_time;
- double last_display_time;
+ thread_condition_variable pause_cond_;
+ thread_mutex pause_mutex_;
+ thread_mutex tile_mutex_;
+ thread_mutex buffers_mutex_;
+ thread_mutex display_mutex_;
+ thread_condition_variable denoising_cond_;
+ thread_condition_variable tile_steal_cond_;
- RenderTile stolen_tile;
+ double reset_time_;
+ double last_update_time_;
+ double last_display_time_;
+
+ RenderTile stolen_tile_;
typedef enum {
NOT_STEALING, /* There currently is no tile stealing in progress. */
WAITING_FOR_TILE, /* A device is waiting for another device to release a tile. */
RELEASING_TILE, /* A device has releasing a stealable tile. */
GOT_TILE /* A device has released a stealable tile, which is now stored in stolen_tile. */
} TileStealingState;
- std::atomic<TileStealingState> tile_stealing_state;
- int stealable_tiles;
+ std::atomic<TileStealingState> tile_stealing_state_;
+ int stealable_tiles_;
/* progressive refine */
bool update_progressive_refine(bool cancel);
diff --git a/intern/ghost/GHOST_C-api.h b/intern/ghost/GHOST_C-api.h
index 83c67f83908..b78aac6f5eb 100644
--- a/intern/ghost/GHOST_C-api.h
+++ b/intern/ghost/GHOST_C-api.h
@@ -1102,7 +1102,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 char **subaction_path,
+ const char *subaction_path,
const int64_t *duration,
const float *frequency,
const float *amplitude);
@@ -1113,7 +1113,7 @@ int GHOST_XrApplyHapticAction(GHOST_XrContextHandle xr_context,
void GHOST_XrStopHapticAction(GHOST_XrContextHandle xr_context,
const char *action_set_name,
const char *action_name,
- const char **subaction_path);
+ const char *subaction_path);
/**
* Get action set custom data (owned by Blender, not GHOST).
diff --git a/intern/ghost/intern/GHOST_C-api.cpp b/intern/ghost/intern/GHOST_C-api.cpp
index b1af5c131ab..a2871b46222 100644
--- a/intern/ghost/intern/GHOST_C-api.cpp
+++ b/intern/ghost/intern/GHOST_C-api.cpp
@@ -1005,7 +1005,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 char **subaction_path,
+ const char *subaction_path,
const int64_t *duration,
const float *frequency,
const float *amplitude)
@@ -1022,7 +1022,7 @@ int GHOST_XrApplyHapticAction(GHOST_XrContextHandle xr_contexthandle,
void GHOST_XrStopHapticAction(GHOST_XrContextHandle xr_contexthandle,
const char *action_set_name,
const char *action_name,
- const char **subaction_path)
+ const char *subaction_path)
{
GHOST_IXrContext *xr_context = (GHOST_IXrContext *)xr_contexthandle;
GHOST_XrSession *xr_session = xr_context->getSession();
diff --git a/intern/ghost/intern/GHOST_ImeWin32.cpp b/intern/ghost/intern/GHOST_ImeWin32.cpp
index 343f4d68078..47b5f5688df 100644
--- a/intern/ghost/intern/GHOST_ImeWin32.cpp
+++ b/intern/ghost/intern/GHOST_ImeWin32.cpp
@@ -30,9 +30,15 @@
# include "GHOST_WindowWin32.h"
# include "utfconv.h"
+/* ISO_639-1 2-Letter Abbreviations. */
+# define IMELANG_ENGLISH "en"
+# define IMELANG_CHINESE "zh"
+# define IMELANG_JAPANESE "ja"
+# define IMELANG_KOREAN "ko"
+
GHOST_ImeWin32::GHOST_ImeWin32()
: is_composing_(false),
- input_language_id_(LANG_USER_DEFAULT),
+ language_(IMELANG_ENGLISH),
conversion_modes_(IME_CMODE_ALPHANUMERIC),
sentence_mode_(IME_SMODE_NONE),
system_caret_(false),
@@ -48,16 +54,21 @@ GHOST_ImeWin32::~GHOST_ImeWin32()
void GHOST_ImeWin32::UpdateInputLanguage()
{
- /**
- * Store the current input language.
- */
- HKL input_locale = ::GetKeyboardLayout(0);
- input_language_id_ = LOWORD(input_locale);
+ /* Get the current input locale full name. */
+ WCHAR locale[LOCALE_NAME_MAX_LENGTH];
+ LCIDToLocaleName(
+ MAKELCID(LOWORD(::GetKeyboardLayout(0)), SORT_DEFAULT), locale, LOCALE_NAME_MAX_LENGTH, 0);
+ /* Get the 2-letter ISO-63901 abbreviation of the input locale name. */
+ WCHAR language_u16[W32_ISO639_LEN];
+ GetLocaleInfoEx(locale, LOCALE_SISO639LANGNAME, language_u16, W32_ISO639_LEN);
+ /* Store this as a UTF-8 string. */
+ WideCharToMultiByte(
+ CP_UTF8, 0, language_u16, W32_ISO639_LEN, language_, W32_ISO639_LEN, NULL, NULL);
}
-WORD GHOST_ImeWin32::GetInputLanguage()
+BOOL GHOST_ImeWin32::IsLanguage(const char name[W32_ISO639_LEN])
{
- return input_language_id_;
+ return (strcmp(name, language_) == 0);
}
void GHOST_ImeWin32::UpdateConversionStatus(HWND window_handle)
@@ -92,21 +103,11 @@ bool GHOST_ImeWin32::IsImeKeyEvent(char ascii)
if ((ascii >= 'A' && ascii <= 'Z') || (ascii >= 'a' && ascii <= 'z')) {
return true;
}
- switch (PRIMARYLANGID(GetInputLanguage())) {
- /* In Japanese, all symbolic characters are also processed by IME. */
- case LANG_JAPANESE: {
- if (ascii >= ' ' && ascii <= '~') {
- return true;
- }
- break;
- }
- /* In Chinese, some symbolic characters are also processed by IME. */
- case LANG_CHINESE: {
- if (ascii && strchr("!\"$'(),.:;<>?[\\]^_`", ascii)) {
- return true;
- }
- break;
- }
+ if (IsLanguage(IMELANG_JAPANESE) && (ascii >= ' ' && ascii <= '~')) {
+ return true;
+ }
+ else if (IsLanguage(IMELANG_CHINESE) && ascii && strchr("!\"$'(),.:;<>?[\\]^_`", ascii)) {
+ return true;
}
}
return false;
@@ -126,13 +127,8 @@ void GHOST_ImeWin32::CreateImeWindow(HWND window_handle)
* Since some third-party Japanese IME also uses ::GetCaretPos() to determine
* their window position, we also create a caret for Japanese IMEs.
*/
- if (PRIMARYLANGID(input_language_id_) == LANG_CHINESE ||
- PRIMARYLANGID(input_language_id_) == LANG_JAPANESE) {
- if (!system_caret_) {
- if (::CreateCaret(window_handle, NULL, 1, 1)) {
- system_caret_ = true;
- }
- }
+ if (!system_caret_ && (IsLanguage(IMELANG_CHINESE) || IsLanguage(IMELANG_JAPANESE))) {
+ system_caret_ = ::CreateCaret(window_handle, NULL, 1, 1);
}
/* Restore the positions of the IME windows. */
UpdateImeWindow(window_handle);
@@ -185,16 +181,9 @@ void GHOST_ImeWin32::MoveImeWindow(HWND window_handle, HIMC imm_context)
CANDIDATEFORM candidate_position = {0, CFS_CANDIDATEPOS, {x, y}, {0, 0, 0, 0}};
::ImmSetCandidateWindow(imm_context, &candidate_position);
if (system_caret_) {
- switch (PRIMARYLANGID(input_language_id_)) {
- case LANG_JAPANESE:
- ::SetCaretPos(x, y + caret_rect_.getHeight());
- break;
- default:
- ::SetCaretPos(x, y);
- break;
- }
+ ::SetCaretPos(x, y);
}
- if (PRIMARYLANGID(input_language_id_) == LANG_KOREAN) {
+ if (IsLanguage(IMELANG_KOREAN)) {
/**
* Chinese IMEs and Japanese IMEs require the upper-left corner of
* the caret to move the position of their candidate windows.
@@ -284,83 +273,79 @@ void GHOST_ImeWin32::GetCaret(HIMC imm_context, LPARAM lparam, ImeComposition *c
*/
int target_start = -1;
int target_end = -1;
- switch (PRIMARYLANGID(input_language_id_)) {
- case LANG_KOREAN:
- if (lparam & CS_NOMOVECARET) {
- target_start = 0;
- target_end = 1;
+ if (IsLanguage(IMELANG_KOREAN)) {
+ if (lparam & CS_NOMOVECARET) {
+ target_start = 0;
+ target_end = 1;
+ }
+ }
+ else if (IsLanguage(IMELANG_CHINESE)) {
+ int clause_size = ImmGetCompositionStringW(imm_context, GCS_COMPCLAUSE, NULL, 0);
+ if (clause_size) {
+ static std::vector<unsigned long> clauses;
+ clause_size = clause_size / sizeof(clauses[0]);
+ clauses.resize(clause_size);
+ ImmGetCompositionStringW(
+ imm_context, GCS_COMPCLAUSE, &clauses[0], sizeof(clauses[0]) * clause_size);
+ if (composition->cursor_position == composition->ime_string.size()) {
+ target_start = clauses[clause_size - 2];
+ target_end = clauses[clause_size - 1];
}
- break;
- case LANG_CHINESE: {
- int clause_size = ImmGetCompositionStringW(imm_context, GCS_COMPCLAUSE, NULL, 0);
- if (clause_size) {
- static std::vector<unsigned long> clauses;
- clause_size = clause_size / sizeof(clauses[0]);
- clauses.resize(clause_size);
- ImmGetCompositionStringW(
- imm_context, GCS_COMPCLAUSE, &clauses[0], sizeof(clauses[0]) * clause_size);
- if (composition->cursor_position == composition->ime_string.size()) {
- target_start = clauses[clause_size - 2];
- target_end = clauses[clause_size - 1];
- }
- else {
- for (int i = 0; i < clause_size - 1; i++) {
- if (clauses[i] == composition->cursor_position) {
- target_start = clauses[i];
- target_end = clauses[i + 1];
- break;
- }
+ else {
+ for (int i = 0; i < clause_size - 1; i++) {
+ if (clauses[i] == composition->cursor_position) {
+ target_start = clauses[i];
+ target_end = clauses[i + 1];
+ break;
}
}
}
- else {
- if (composition->cursor_position != -1) {
- target_start = composition->cursor_position;
- target_end = composition->ime_string.size();
- }
+ }
+ else {
+ if (composition->cursor_position != -1) {
+ target_start = composition->cursor_position;
+ target_end = composition->ime_string.size();
}
- break;
}
- case LANG_JAPANESE:
-
- /**
- * For Japanese IMEs, the robustest way to retrieve the caret
- * is scanning the attribute of the latest composition string and
- * retrieving the beginning and the end of the target clause, i.e.
- * a clause being converted.
- */
- if (lparam & GCS_COMPATTR) {
- int attribute_size = ::ImmGetCompositionStringW(imm_context, GCS_COMPATTR, NULL, 0);
- if (attribute_size > 0) {
- char *attribute_data = new char[attribute_size];
- if (attribute_data) {
- ::ImmGetCompositionStringW(imm_context, GCS_COMPATTR, attribute_data, attribute_size);
- for (target_start = 0; target_start < attribute_size; ++target_start) {
- if (IsTargetAttribute(attribute_data[target_start]))
- break;
- }
- for (target_end = target_start; target_end < attribute_size; ++target_end) {
- if (!IsTargetAttribute(attribute_data[target_end]))
- break;
- }
- if (target_start == attribute_size) {
- /**
- * This composition clause does not contain any target clauses,
- * i.e. this clauses is an input clause.
- * We treat whole this clause as a target clause.
- */
- target_end = target_start;
- target_start = 0;
- }
- if (target_start != -1 && target_start < attribute_size &&
- attribute_data[target_start] == ATTR_TARGET_NOTCONVERTED) {
- composition->cursor_position = target_start;
- }
+ }
+ else if (IsLanguage(IMELANG_JAPANESE)) {
+ /**
+ * For Japanese IMEs, the robustest way to retrieve the caret
+ * is scanning the attribute of the latest composition string and
+ * retrieving the beginning and the end of the target clause, i.e.
+ * a clause being converted.
+ */
+ if (lparam & GCS_COMPATTR) {
+ int attribute_size = ::ImmGetCompositionStringW(imm_context, GCS_COMPATTR, NULL, 0);
+ if (attribute_size > 0) {
+ char *attribute_data = new char[attribute_size];
+ if (attribute_data) {
+ ::ImmGetCompositionStringW(imm_context, GCS_COMPATTR, attribute_data, attribute_size);
+ for (target_start = 0; target_start < attribute_size; ++target_start) {
+ if (IsTargetAttribute(attribute_data[target_start]))
+ break;
+ }
+ for (target_end = target_start; target_end < attribute_size; ++target_end) {
+ if (!IsTargetAttribute(attribute_data[target_end]))
+ break;
+ }
+ if (target_start == attribute_size) {
+ /**
+ * This composition clause does not contain any target clauses,
+ * i.e. this clauses is an input clause.
+ * We treat whole this clause as a target clause.
+ */
+ target_end = target_start;
+ target_start = 0;
+ }
+ if (target_start != -1 && target_start < attribute_size &&
+ attribute_data[target_start] == ATTR_TARGET_NOTCONVERTED) {
+ composition->cursor_position = target_start;
}
- delete[] attribute_data;
}
+ delete[] attribute_data;
}
- break;
+ }
}
composition->target_start = target_start;
composition->target_end = target_end;
diff --git a/intern/ghost/intern/GHOST_ImeWin32.h b/intern/ghost/intern/GHOST_ImeWin32.h
index d430a7d745d..ce0e4d64d53 100644
--- a/intern/ghost/intern/GHOST_ImeWin32.h
+++ b/intern/ghost/intern/GHOST_ImeWin32.h
@@ -36,6 +36,9 @@
# include "GHOST_Rect.h"
# include <vector>
+/* MSDN LOCALE_SISO639LANGNAME states maximum length of 9, including terminating null. */
+# define W32_ISO639_LEN 9
+
class GHOST_EventIME : public GHOST_Event {
public:
/**
@@ -146,13 +149,10 @@ class GHOST_ImeWin32 {
return is_composing_;
}
- /**
- * Retrieves the input language from Windows and update it.
- */
+ /* Retrieve the input language from Windows and store it. */
void UpdateInputLanguage();
- /* Returns the current input language id. */
- WORD GetInputLanguage();
+ BOOL IsLanguage(const char name[W32_ISO639_LEN]);
/* Saves the current conversion status. */
void UpdateConversionStatus(HWND window_handle);
@@ -345,29 +345,8 @@ class GHOST_ImeWin32 {
*/
bool is_composing_;
- /**
- * The current input Language ID retrieved from Windows, which consists of:
- * * Primary Language ID (bit 0 to bit 9), which shows a natural language
- * (English, Korean, Chinese, Japanese, etc.) and;
- * * Sub-Language ID (bit 10 to bit 15), which shows a geometrical region
- * the language is spoken (For English, United States, United Kingdom,
- * Australia, Canada, etc.)
- * The following list enumerates some examples for the Language ID:
- * * "en-US" (0x0409)
- * MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US);
- * * "ko-KR" (0x0412)
- * MAKELANGID(LANG_KOREAN, SUBLANG_KOREAN);
- * * "zh-TW" (0x0404)
- * MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_TRADITIONAL);
- * * "zh-CN" (0x0804)
- * MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED);
- * * "ja-JP" (0x0411)
- * MAKELANGID(LANG_JAPANESE, SUBLANG_JAPANESE_JAPAN), etc.
- * (See `winnt.h` for other available values.)
- * This Language ID is used for processing language-specific operations in
- * IME functions.
- */
- LANGID input_language_id_;
+ /* Abbreviated ISO 639-1 name of the input language, such as "en" for English. */
+ char language_[W32_ISO639_LEN];
/* Current Conversion Mode Values. Retrieved with ImmGetConversionStatus. */
DWORD conversion_modes_;
diff --git a/intern/ghost/intern/GHOST_SystemCocoa.mm b/intern/ghost/intern/GHOST_SystemCocoa.mm
index 2b4c3237c73..933e0c70cc8 100644
--- a/intern/ghost/intern/GHOST_SystemCocoa.mm
+++ b/intern/ghost/intern/GHOST_SystemCocoa.mm
@@ -1629,7 +1629,7 @@ GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr)
y_accum + (y_mouse - warped_y_mouse));
/* This is the current time that matches NSEvent timestamp. */
- m_last_warp_timestamp = mach_absolute_time() * 1e-9;
+ m_last_warp_timestamp = [[NSProcessInfo processInfo] systemUptime];
}
// Generate event
diff --git a/intern/ghost/intern/GHOST_XrAction.cpp b/intern/ghost/intern/GHOST_XrAction.cpp
index 07eb42c14e6..704b1ce9fac 100644
--- a/intern/ghost/intern/GHOST_XrAction.cpp
+++ b/intern/ghost/intern/GHOST_XrAction.cpp
@@ -375,7 +375,7 @@ void GHOST_XrAction::updateState(XrSession session,
void GHOST_XrAction::applyHapticFeedback(XrSession session,
const char *action_name,
- const char **subaction_path_str,
+ const char *subaction_path_str,
const int64_t &duration,
const float &frequency,
const float &amplitude)
@@ -390,7 +390,7 @@ void GHOST_XrAction::applyHapticFeedback(XrSession session,
haptic_info.action = m_action;
if (subaction_path_str != nullptr) {
- SubactionIndexMap::iterator it = m_subaction_indices.find(*subaction_path_str);
+ SubactionIndexMap::iterator it = m_subaction_indices.find(subaction_path_str);
if (it != m_subaction_indices.end()) {
haptic_info.subactionPath = m_subaction_paths[it->second];
CHECK_XR(
@@ -410,13 +410,13 @@ void GHOST_XrAction::applyHapticFeedback(XrSession session,
void GHOST_XrAction::stopHapticFeedback(XrSession session,
const char *action_name,
- const char **subaction_path_str)
+ const char *subaction_path_str)
{
XrHapticActionInfo haptic_info{XR_TYPE_HAPTIC_ACTION_INFO};
haptic_info.action = m_action;
if (subaction_path_str != nullptr) {
- SubactionIndexMap::iterator it = m_subaction_indices.find(*subaction_path_str);
+ SubactionIndexMap::iterator it = m_subaction_indices.find(subaction_path_str);
if (it != m_subaction_indices.end()) {
haptic_info.subactionPath = m_subaction_paths[it->second];
CHECK_XR(xrStopHapticFeedback(session, &haptic_info),
diff --git a/intern/ghost/intern/GHOST_XrAction.h b/intern/ghost/intern/GHOST_XrAction.h
index 70eaa694ae9..3e2224fe3ff 100644
--- a/intern/ghost/intern/GHOST_XrAction.h
+++ b/intern/ghost/intern/GHOST_XrAction.h
@@ -103,11 +103,11 @@ class GHOST_XrAction {
const XrTime &predicted_display_time);
void applyHapticFeedback(XrSession session,
const char *action_name,
- const char **subaction_path,
+ const char *subaction_path,
const int64_t &duration,
const float &frequency,
const float &amplitude);
- void stopHapticFeedback(XrSession session, const char *action_name, const char **subaction_path);
+ void stopHapticFeedback(XrSession session, const char *action_name, const char *subaction_path);
void *getCustomdata();
void getBindings(std::map<XrPath, std::vector<XrActionSuggestedBinding>> &r_bindings) const;
diff --git a/intern/ghost/intern/GHOST_XrSession.cpp b/intern/ghost/intern/GHOST_XrSession.cpp
index a63ce5c9344..4cab22ee676 100644
--- a/intern/ghost/intern/GHOST_XrSession.cpp
+++ b/intern/ghost/intern/GHOST_XrSession.cpp
@@ -754,7 +754,7 @@ bool GHOST_XrSession::syncActions(const char *action_set_name)
bool GHOST_XrSession::applyHapticAction(const char *action_set_name,
const char *action_name,
- const char **subaction_path,
+ const char *subaction_path,
const int64_t &duration,
const float &frequency,
const float &amplitude)
@@ -777,7 +777,7 @@ bool GHOST_XrSession::applyHapticAction(const char *action_set_name,
void GHOST_XrSession::stopHapticAction(const char *action_set_name,
const char *action_name,
- const char **subaction_path)
+ const char *subaction_path)
{
GHOST_XrActionSet *action_set = find_action_set(m_oxr.get(), action_set_name);
if (action_set == nullptr) {
diff --git a/intern/ghost/intern/GHOST_XrSession.h b/intern/ghost/intern/GHOST_XrSession.h
index ec15897058f..a76e11aede1 100644
--- a/intern/ghost/intern/GHOST_XrSession.h
+++ b/intern/ghost/intern/GHOST_XrSession.h
@@ -76,13 +76,13 @@ class GHOST_XrSession {
bool syncActions(const char *action_set_name = nullptr);
bool applyHapticAction(const char *action_set_name,
const char *action_name,
- const char **subaction_path,
+ const char *subaction_path,
const int64_t &duration,
const float &frequency,
const float &amplitude);
void stopHapticAction(const char *action_set_name,
const char *action_name,
- const char **subaction_path);
+ const char *subaction_path);
/* Custom data (owned by Blender, not GHOST) accessors. */
void *getActionSetCustomdata(const char *action_set_name);
diff --git a/intern/guardedalloc/intern/mallocn_guarded_impl.c b/intern/guardedalloc/intern/mallocn_guarded_impl.c
index a7c3dc0951e..98a8553a3eb 100644
--- a/intern/guardedalloc/intern/mallocn_guarded_impl.c
+++ b/intern/guardedalloc/intern/mallocn_guarded_impl.c
@@ -871,7 +871,7 @@ void MEM_guarded_freeN(void *vmemh)
if (memh == NULL) {
MemorY_ErroR("free", "attempt to free NULL pointer");
- /* print_error(err_stream, "%d\n", (memh+4000)->tag1); */
+ // print_error(err_stream, "%d\n", (memh+4000)->tag1);
return;
}
diff --git a/make.bat b/make.bat
index 75d424202ae..e94f7637512 100644
--- a/make.bat
+++ b/make.bat
@@ -13,6 +13,14 @@ if errorlevel 1 goto EOF
call "%BLENDER_DIR%\build_files\windows\parse_arguments.cmd" %*
if errorlevel 1 goto EOF
+REM if it is one of the convenience targets and BLENDER_BIN is set
+REM skip compiler detection
+if "%ICONS%%ICONS_GEOM%%DOC_PY%" == "1" (
+ if EXIST "%BLENDER_BIN%" (
+ goto convenience_targets
+ )
+)
+
call "%BLENDER_DIR%\build_files\windows\find_dependencies.cmd"
if errorlevel 1 goto EOF
@@ -58,6 +66,8 @@ if "%BUILD_UPDATE%" == "1" (
call "%BLENDER_DIR%\build_files\windows\set_build_dir.cmd"
+:convenience_targets
+
if "%ICONS%" == "1" (
call "%BLENDER_DIR%\build_files\windows\icons.cmd"
goto EOF
@@ -68,6 +78,11 @@ if "%ICONS_GEOM%" == "1" (
goto EOF
)
+if "%DOC_PY%" == "1" (
+ call "%BLENDER_DIR%\build_files\windows\doc_py.cmd"
+ goto EOF
+)
+
echo Building blender with VS%BUILD_VS_YEAR% for %BUILD_ARCH% in %BUILD_DIR%
call "%BLENDER_DIR%\build_files\windows\check_libraries.cmd"
diff --git a/release/datafiles/preview.blend b/release/datafiles/preview.blend
index f92f68ad029..e342cb85158 100644
--- a/release/datafiles/preview.blend
+++ b/release/datafiles/preview.blend
Binary files differ
diff --git a/release/scripts/modules/bl_i18n_utils/utils.py b/release/scripts/modules/bl_i18n_utils/utils.py
index fda93682dc5..95184853f73 100644
--- a/release/scripts/modules/bl_i18n_utils/utils.py
+++ b/release/scripts/modules/bl_i18n_utils/utils.py
@@ -1355,7 +1355,7 @@ class I18n:
print(prefix.join(lines))
@classmethod
- def check_py_module_has_translations(clss, src, settings=settings):
+ def check_py_module_has_translations(cls, src, settings=settings):
"""
Check whether a given src (a py module, either a directory or a py file) has some i18n translation data,
and returns a tuple (src_file, translations_tuple) if yes, else (None, None).
@@ -1367,11 +1367,11 @@ class I18n:
if not fname.endswith(".py"):
continue
path = os.path.join(root, fname)
- _1, txt, _2, has_trans = clss._parser_check_file(path)
+ _1, txt, _2, has_trans = cls._parser_check_file(path)
if has_trans:
txts.append((path, txt))
elif src.endswith(".py") and os.path.isfile(src):
- _1, txt, _2, has_trans = clss._parser_check_file(src)
+ _1, txt, _2, has_trans = cls._parser_check_file(src)
if has_trans:
txts.append((src, txt))
for path, txt in txts:
diff --git a/release/scripts/modules/bl_i18n_utils/utils_spell_check.py b/release/scripts/modules/bl_i18n_utils/utils_spell_check.py
index c310eee0b14..14fc81821c4 100644
--- a/release/scripts/modules/bl_i18n_utils/utils_spell_check.py
+++ b/release/scripts/modules/bl_i18n_utils/utils_spell_check.py
@@ -48,6 +48,7 @@ class SpellChecker:
"equi", # equi-angular, etc.
"fader",
"globbing",
+ "haptics",
"hasn", # hasn't
"hetero",
"hoc", # ad-hoc
@@ -188,7 +189,7 @@ class SpellChecker:
"reprojection", "reproject", "reprojecting",
"resize",
"restpose",
- "resync",
+ "resync", "resynced",
"retarget", "retargets", "retargeting", "retargeted",
"retiming",
"rigidbody",
@@ -227,6 +228,7 @@ class SpellChecker:
"un",
"unassociate", "unassociated",
"unbake",
+ "uncheck",
"unclosed",
"uncomment",
"unculled",
@@ -381,6 +383,7 @@ class SpellChecker:
"albedo",
"anamorphic",
"anisotropic", "anisotropy",
+ "bimanual", # OpenXR?
"bitangent",
"boid", "boids",
"ceil",
@@ -430,6 +433,7 @@ class SpellChecker:
"spacebar",
"subtractive",
"superellipse",
+ "thumbstick",
"tooltip", "tooltips",
"trackpad",
"tuple",
@@ -493,7 +497,7 @@ class SpellChecker:
"pinlight",
"qi",
"radiosity",
- "raycasting",
+ "raycast", "raycasting",
"raytrace", "raytracing", "raytraced",
"refractions",
"remesher", "remeshing", "remesh",
@@ -698,6 +702,7 @@ class SpellChecker:
"msgid", "msgids",
"mux",
"ndof",
+ "pbr", # Physically Based Rendering
"ppc",
"precisa",
"px",
diff --git a/release/scripts/modules/bpy/utils/__init__.py b/release/scripts/modules/bpy/utils/__init__.py
index 58b20d9e3c8..1fe73f50639 100644
--- a/release/scripts/modules/bpy/utils/__init__.py
+++ b/release/scripts/modules/bpy/utils/__init__.py
@@ -754,12 +754,10 @@ def register_classes_factory(classes):
which simply registers and unregisters a sequence of classes.
"""
def register():
- from bpy.utils import register_class
for cls in classes:
register_class(cls)
def unregister():
- from bpy.utils import unregister_class
for cls in reversed(classes):
unregister_class(cls)
diff --git a/release/scripts/modules/bpy_types.py b/release/scripts/modules/bpy_types.py
index 29b53aedf78..8a1615ad99f 100644
--- a/release/scripts/modules/bpy_types.py
+++ b/release/scripts/modules/bpy_types.py
@@ -477,29 +477,34 @@ class Mesh(bpy_types.ID):
face_lengths = tuple(map(len, faces))
- self.vertices.add(len(vertices))
- self.edges.add(len(edges))
+ # NOTE: check non-empty lists by length because of how `numpy` handles truth tests, see: T90268.
+ vertices_len = len(vertices)
+ edges_len = len(edges)
+ faces_len = len(faces)
+
+ self.vertices.add(vertices_len)
+ self.edges.add(edges_len)
self.loops.add(sum(face_lengths))
- self.polygons.add(len(faces))
+ self.polygons.add(faces_len)
self.vertices.foreach_set("co", tuple(chain.from_iterable(vertices)))
self.edges.foreach_set("vertices", tuple(chain.from_iterable(edges)))
vertex_indices = tuple(chain.from_iterable(faces))
- loop_starts = tuple(islice(chain([0], accumulate(face_lengths)), len(faces)))
+ loop_starts = tuple(islice(chain([0], accumulate(face_lengths)), faces_len))
self.polygons.foreach_set("loop_total", face_lengths)
self.polygons.foreach_set("loop_start", loop_starts)
self.polygons.foreach_set("vertices", vertex_indices)
- if edges or faces:
+ if edges_len or faces_len:
self.update(
# Needed to either:
# - Calculate edges that don't exist for polygons.
# - Assign edges to polygon loops.
- calc_edges=bool(faces),
+ calc_edges=bool(faces_len),
# Flag loose edges.
- calc_edges_loose=bool(edges),
+ calc_edges_loose=bool(edges_len),
)
@property
@@ -761,9 +766,9 @@ class Macro(StructRNA):
__slots__ = ()
@classmethod
- def define(self, opname):
+ def define(cls, opname):
from _bpy import ops
- return ops.macro_define(self, opname)
+ return ops.macro_define(cls, opname)
class PropertyGroup(StructRNA, metaclass=RNAMetaPropGroup):
diff --git a/release/scripts/presets/keyconfig/keymap_data/blender_default.py b/release/scripts/presets/keyconfig/keymap_data/blender_default.py
index a67c5244611..d9538930f33 100644
--- a/release/scripts/presets/keyconfig/keymap_data/blender_default.py
+++ b/release/scripts/presets/keyconfig/keymap_data/blender_default.py
@@ -775,6 +775,8 @@ def km_property_editor(_params):
# Constraint panels
("constraint.delete", {"type": 'X', "value": 'PRESS'}, {"properties": [("report", True)]}),
("constraint.delete", {"type": 'DEL', "value": 'PRESS'}, {"properties": [("report", True)]}),
+ ("constraint.copy", {"type": 'D', "value": 'PRESS', "shift": True}, None),
+ ("constraint.apply", {"type": 'A', "value": 'PRESS', "ctrl": True}, {"properties": [("report", True)]}),
])
return keymap
@@ -1968,8 +1970,8 @@ def km_file_browser(params):
*_template_space_region_type_toggle(
toolbar_key={"type": 'T', "value": 'PRESS'},
),
- ("screen.region_toggle", {"type": 'N', "value": 'PRESS'},
- {"properties": [("region_type", 'TOOL_PROPS')]}),
+ ("wm.context_toggle", {"type": 'N', "value": 'PRESS'},
+ {"properties": [("data_path", 'space_data.show_region_tool_props')]}),
("file.parent", {"type": 'UP_ARROW', "value": 'PRESS', "alt": True}, None),
("file.previous", {"type": 'LEFT_ARROW', "value": 'PRESS', "alt": True}, None),
("file.next", {"type": 'RIGHT_ARROW', "value": 'PRESS', "alt": True}, None),
@@ -1999,6 +2001,10 @@ def km_file_browser(params):
{"properties": [("increment", -10)]}),
("file.filenum", {"type": 'NUMPAD_MINUS', "value": 'PRESS', "ctrl": True, "repeat": True},
{"properties": [("increment", -100)]}),
+
+ # Select file under cursor before spawning the context menu.
+ ("file.select", {"type": 'RIGHTMOUSE', "value": 'PRESS'},
+ {"properties": [("open", False), ("only_activate_if_selected", params.select_mouse == 'LEFTMOUSE'), ("pass_through", True)]}),
*_template_items_context_menu("FILEBROWSER_MT_context_menu", params.context_menu_event),
*_template_items_context_menu("ASSETBROWSER_MT_context_menu", params.context_menu_event),
])
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 9d34b110afe..dba94d71a43 100644
--- a/release/scripts/presets/keyconfig/keymap_data/industry_compatible_data.py
+++ b/release/scripts/presets/keyconfig/keymap_data/industry_compatible_data.py
@@ -139,12 +139,12 @@ def _template_items_basic_tools(*, connected=False):
]
def _template_items_tool_select(params, operator, *, extend):
- return [
- (operator, {"type": 'LEFTMOUSE', "value": 'PRESS'},
- {"properties": [("deselect_all", True)]}),
- (operator, {"type": 'LEFTMOUSE', "value": 'PRESS', "shift": True},
- {"properties": [(extend, True)]}),
- ]
+ return [
+ (operator, {"type": 'LEFTMOUSE', "value": 'PRESS'},
+ {"properties": [("deselect_all", True)]}),
+ (operator, {"type": 'LEFTMOUSE', "value": 'PRESS', "shift": True},
+ {"properties": [(extend, True)]}),
+ ]
def _template_items_tool_select_actions(operator, *, type, value):
@@ -465,6 +465,7 @@ def km_property_editor(params):
# Constraint panels
("constraint.delete", {"type": 'BACK_SPACE', "value": 'PRESS'}, {"properties": [("report", True)]}),
("constraint.delete", {"type": 'DEL', "value": 'PRESS'}, {"properties": [("report", True)]}),
+ ("constraint.copy", {"type": 'D', "value": 'PRESS', "ctrl": True}, None),
])
return keymap
@@ -1248,6 +1249,10 @@ def km_file_browser(params):
{"properties": [("increment", -10)]}),
("file.filenum", {"type": 'NUMPAD_MINUS', "value": 'PRESS', "ctrl": True, "repeat": True},
{"properties": [("increment", -100)]}),
+
+ # Select file under cursor before spawning the context menu.
+ ("file.select", {"type": 'RIGHTMOUSE', "value": 'PRESS'},
+ {"properties": [("open", False), ("only_activate_if_selected", True), ("pass_through", True)]}),
*_template_items_context_menu("FILEBROWSER_MT_context_menu", {"type": 'RIGHTMOUSE', "value": 'PRESS'}),
*_template_items_context_menu("ASSETBROWSER_MT_context_menu", {"type": 'RIGHTMOUSE', "value": 'PRESS'}),
])
diff --git a/release/scripts/startup/bl_app_templates_system/2D_Animation/__init__.py b/release/scripts/startup/bl_app_templates_system/2D_Animation/__init__.py
index 40dd0729fec..be47890a002 100644
--- a/release/scripts/startup/bl_app_templates_system/2D_Animation/__init__.py
+++ b/release/scripts/startup/bl_app_templates_system/2D_Animation/__init__.py
@@ -21,48 +21,43 @@
import bpy
from bpy.app.handlers import persistent
-
-@persistent
-def load_handler(_):
- import bpy
-
- # 2D Animation
- screen = bpy.data.screens['2D Animation']
- if screen:
- for area in screen.areas:
+def update_factory_startup_screens():
+ # 2D Animation.
+ screen = bpy.data.screens["2D Animation"]
+ for area in screen.areas:
+ if area.type == 'PROPERTIES':
# Set Tool settings as default in properties panel.
- if area.type == 'PROPERTIES':
- for space in area.spaces:
- if space.type != 'PROPERTIES':
- continue
- space.context = 'TOOL'
-
+ space = area.spaces.active
+ space.context = 'TOOL'
+ elif area.type == 'DOPESHEET_EDITOR':
# Open sidebar in Dopesheet.
- elif area.type == 'DOPESHEET_EDITOR':
- for space in area.spaces:
- if space.type != 'DOPESHEET_EDITOR':
- continue
- space.show_region_ui = True
+ space = area.spaces.active
+ space.show_region_ui = True
+
+ # 2D Full Canvas.
+ screen = bpy.data.screens["2D Full Canvas"]
+ for area in screen.areas:
+ if area.type == 'VIEW_3D':
+ space = area.spaces.active
+ space.shading.type = 'MATERIAL'
+ space.shading.use_scene_world = True
- # 2D Full Canvas
- screen = bpy.data.screens['2D Full Canvas']
- if screen:
- for area in screen.areas:
- if area.type == 'VIEW_3D':
- for space in area.spaces:
- if space.type != 'VIEW_3D':
- continue
- space.shading.type = 'MATERIAL'
- space.shading.use_scene_world = True
- # Grease pencil object
- scene = bpy.data.scenes[0]
- if scene:
+def update_factory_startup_scenes():
+ for scene in bpy.data.scenes:
scene.tool_settings.use_keyframe_insert_auto = True
- for ob in scene.objects:
- if ob.type == 'GPENCIL':
- gpd = ob.data
- gpd.onion_keyframe_type = 'ALL'
+
+
+def update_factory_startup_grease_pencils():
+ for gpd in bpy.data.grease_pencils:
+ gpd.onion_keyframe_type = 'ALL'
+
+
+@persistent
+def load_handler(_):
+ update_factory_startup_screens()
+ update_factory_startup_scenes()
+ update_factory_startup_grease_pencils()
def register():
diff --git a/release/scripts/startup/bl_app_templates_system/Video_Editing/__init__.py b/release/scripts/startup/bl_app_templates_system/Video_Editing/__init__.py
index ae3fdee56ac..247a1ec342e 100644
--- a/release/scripts/startup/bl_app_templates_system/Video_Editing/__init__.py
+++ b/release/scripts/startup/bl_app_templates_system/Video_Editing/__init__.py
@@ -20,10 +20,8 @@ import bpy
from bpy.app.handlers import persistent
-@persistent
-def load_handler(_):
- from bpy import context
- screen = context.screen
+def update_factory_startup_screens():
+ screen = bpy.data.screens["Video Editing"]
for area in screen.areas:
if area.type == 'FILE_BROWSER':
space = area.spaces.active
@@ -31,6 +29,11 @@ def load_handler(_):
params.use_filter_folder = True
+@persistent
+def load_handler(_):
+ update_factory_startup_screens()
+
+
def register():
bpy.app.handlers.load_factory_startup_post.append(load_handler)
diff --git a/release/scripts/startup/bl_operators/assets.py b/release/scripts/startup/bl_operators/assets.py
index c782cd0646e..8c76018b7a1 100644
--- a/release/scripts/startup/bl_operators/assets.py
+++ b/release/scripts/startup/bl_operators/assets.py
@@ -130,7 +130,7 @@ class ASSET_OT_open_containing_blend_file(Operator):
return {'RUNNING_MODAL'}
if returncode:
- self.report({'WARNING'}, "Blender subprocess exited with error code %d" % returncode)
+ self.report({'WARNING'}, "Blender sub-process 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.
diff --git a/release/scripts/startup/bl_ui/properties_mask_common.py b/release/scripts/startup/bl_ui/properties_mask_common.py
index 09a1f40d3a9..40a704a65dd 100644
--- a/release/scripts/startup/bl_ui/properties_mask_common.py
+++ b/release/scripts/startup/bl_ui/properties_mask_common.py
@@ -237,9 +237,8 @@ class MASK_PT_point:
class MASK_PT_display:
# subclasses must define...
# ~ bl_space_type = 'CLIP_EDITOR'
- # ~ bl_region_type = 'UI'
+ # ~ bl_region_type = 'HEADER'
bl_label = "Mask Display"
- bl_options = {'DEFAULT_CLOSED'}
@classmethod
def poll(cls, context):
diff --git a/release/scripts/startup/bl_ui/properties_object.py b/release/scripts/startup/bl_ui/properties_object.py
index 46a16a70dca..52af4fafd09 100644
--- a/release/scripts/startup/bl_ui/properties_object.py
+++ b/release/scripts/startup/bl_ui/properties_object.py
@@ -216,6 +216,7 @@ class OBJECT_PT_display(ObjectButtonsPanel, Panel):
obj = context.object
obj_type = obj.type
is_geometry = (obj_type in {'MESH', 'CURVE', 'SURFACE', 'META', 'FONT', 'VOLUME', 'HAIR', 'POINTCLOUD'})
+ has_bounds = (is_geometry or obj_type in {'LATTICE', 'ARMATURE'})
is_wire = (obj_type in {'CAMERA', 'EMPTY'})
is_empty_image = (obj_type == 'EMPTY' and obj.empty_display_type == 'IMAGE')
is_dupli = (obj.instance_type != 'NONE')
@@ -247,21 +248,27 @@ class OBJECT_PT_display(ObjectButtonsPanel, Panel):
# Only useful with object having faces/materials...
col.prop(obj, "color")
- col = layout.column(align=False, heading="Bounds")
- col.use_property_decorate = False
- row = col.row(align=True)
- sub = row.row(align=True)
- sub.prop(obj, "show_bounds", text="")
- sub = sub.row(align=True)
- sub.active = obj.show_bounds or (obj.display_type == 'BOUNDS')
- sub.prop(obj, "display_bounds_type", text="")
- row.prop_decorator(obj, "display_bounds_type")
+ if has_bounds:
+ col = layout.column(align=False, heading="Bounds")
+ col.use_property_decorate = False
+ row = col.row(align=True)
+ sub = row.row(align=True)
+ sub.prop(obj, "show_bounds", text="")
+ sub = sub.row(align=True)
+ sub.active = obj.show_bounds or (obj.display_type == 'BOUNDS')
+ sub.prop(obj, "display_bounds_type", text="")
+ row.prop_decorator(obj, "display_bounds_type")
class OBJECT_PT_instancing(ObjectButtonsPanel, Panel):
bl_label = "Instancing"
bl_options = {'DEFAULT_CLOSED'}
+ @classmethod
+ def poll(cls, context):
+ ob = context.object
+ return (ob.type in {'MESH', 'EMPTY', 'POINTCLOUD'})
+
def draw(self, context):
layout = self.layout
diff --git a/release/scripts/startup/bl_ui/properties_paint_common.py b/release/scripts/startup/bl_ui/properties_paint_common.py
index 97a0c5abf24..c038f5f906a 100644
--- a/release/scripts/startup/bl_ui/properties_paint_common.py
+++ b/release/scripts/startup/bl_ui/properties_paint_common.py
@@ -1141,14 +1141,15 @@ def brush_basic__draw_color_selector(context, layout, brush, gp_settings, props)
if not gp_settings.use_material_pin:
ma = context.object.active_material
icon_id = 0
+ txt_ma = ""
if ma:
- icon_id = ma.id_data.preview.icon_id
- txt_ma = ma.name
- maxw = 25
- if len(txt_ma) > maxw:
- txt_ma = txt_ma[:maxw - 5] + '..' + txt_ma[-3:]
- else:
- txt_ma = ""
+ ma.id_data.preview_ensure()
+ if ma.id_data.preview:
+ icon_id = ma.id_data.preview.icon_id
+ txt_ma = ma.name
+ maxw = 25
+ if len(txt_ma) > maxw:
+ txt_ma = txt_ma[:maxw - 5] + '..' + txt_ma[-3:]
sub = row.row()
sub.ui_units_x = 8
diff --git a/release/scripts/startup/bl_ui/space_clip.py b/release/scripts/startup/bl_ui/space_clip.py
index afbc3abf302..a1e5b509295 100644
--- a/release/scripts/startup/bl_ui/space_clip.py
+++ b/release/scripts/startup/bl_ui/space_clip.py
@@ -1075,6 +1075,31 @@ class CLIP_PT_stabilization(CLIP_PT_reconstruction_panel, Panel):
layout.prop(stab, "filter_type")
+class CLIP_PT_2d_cursor(Panel):
+ bl_space_type = 'CLIP_EDITOR'
+ bl_region_type = 'UI'
+ bl_category = "View"
+ bl_label = "2D Cursor"
+
+ @classmethod
+ def poll(cls, context):
+ sc = context.space_data
+
+ if CLIP_PT_clip_view_panel.poll(context):
+ return sc.pivot_point == 'CURSOR' or sc.mode == 'MASK'
+
+ def draw(self, context):
+ layout = self.layout
+
+ sc = context.space_data
+
+ layout.use_property_split = True
+ layout.use_property_decorate = False
+
+ col = layout.column()
+ col.prop(sc, "cursor_location", text="Location")
+
+
class CLIP_PT_proxy(CLIP_PT_clip_view_panel, Panel):
bl_space_type = 'CLIP_EDITOR'
bl_region_type = 'UI'
@@ -1156,12 +1181,6 @@ class CLIP_PT_mask_layers(MASK_PT_layers, Panel):
bl_category = "Mask"
-class CLIP_PT_mask_display(MASK_PT_display, Panel):
- bl_space_type = 'CLIP_EDITOR'
- bl_region_type = 'HEADER'
- bl_category = "Mask"
-
-
class CLIP_PT_active_mask_spline(MASK_PT_spline, Panel):
bl_space_type = 'CLIP_EDITOR'
bl_region_type = 'UI'
@@ -1191,6 +1210,11 @@ class CLIP_PT_tools_mask_tools(MASK_PT_tools, Panel):
bl_region_type = 'TOOLS'
bl_category = "Mask"
+
+class CLIP_PT_mask_display(MASK_PT_display, Panel):
+ bl_space_type = 'CLIP_EDITOR'
+ bl_region_type = 'HEADER'
+
# --- end mask ---
@@ -1240,7 +1264,7 @@ class CLIP_PT_tools_scenesetup(Panel):
class CLIP_PT_annotation(AnnotationDataPanel, CLIP_PT_clip_view_panel, Panel):
bl_space_type = 'CLIP_EDITOR'
bl_region_type = 'UI'
- bl_category = "Annotation"
+ bl_category = "View"
bl_options = set()
# NOTE: this is just a wrapper around the generic GP Panel
@@ -1863,6 +1887,7 @@ classes = (
CLIP_PT_proxy,
CLIP_PT_footage,
CLIP_PT_stabilization,
+ CLIP_PT_2d_cursor,
CLIP_PT_mask,
CLIP_PT_mask_layers,
CLIP_PT_mask_display,
diff --git a/release/scripts/startup/bl_ui/space_filebrowser.py b/release/scripts/startup/bl_ui/space_filebrowser.py
index 9f70d26c71b..aea2b76e07b 100644
--- a/release/scripts/startup/bl_ui/space_filebrowser.py
+++ b/release/scripts/startup/bl_ui/space_filebrowser.py
@@ -37,9 +37,9 @@ class FILEBROWSER_HT_header(Header):
params = space_data.params
row = layout.row(align=True)
- row.prop(params, "asset_library", text="")
+ row.prop(params, "asset_library_ref", text="")
# External libraries don't auto-refresh, add refresh button.
- if params.asset_library != 'LOCAL':
+ if params.asset_library_ref != 'LOCAL':
row.operator("file.refresh", text="", icon='FILE_REFRESH')
layout.separator_spacer()
@@ -195,7 +195,7 @@ class FILEBROWSER_PT_filter(FileBrowserPanel, Panel):
sub = row.column(align=True)
- if context.preferences.experimental.use_asset_browser:
+ if context.preferences.experimental.use_extended_asset_browser:
sub.prop(params, "use_filter_asset_only")
filter_id = params.filter_id
@@ -653,6 +653,10 @@ class ASSETBROWSER_PT_navigation_bar(asset_utils.AssetBrowserPanel, Panel):
bl_region_type = 'TOOLS'
bl_options = {'HIDE_HEADER'}
+ @classmethod
+ def poll(cls, context):
+ return context.preferences.experimental.use_extended_asset_browser
+
def draw(self, context):
layout = self.layout
@@ -678,8 +682,8 @@ class ASSETBROWSER_PT_metadata(asset_utils.AssetBrowserPanel, Panel):
layout.label(text="No asset selected", icon='INFO')
return
- asset_library = context.asset_library
- asset_lib_path = bpy.types.AssetHandle.get_full_library_path(asset_file_handle, asset_library)
+ asset_library_ref = context.asset_library_ref
+ asset_lib_path = bpy.types.AssetHandle.get_full_library_path(asset_file_handle, asset_library_ref)
if asset_file_handle.local_id:
# If the active file is an ID, use its name directly so renaming is possible from right here.
diff --git a/release/scripts/startup/bl_ui/space_image.py b/release/scripts/startup/bl_ui/space_image.py
index 0fceb864ac2..dcb0ab2e9e5 100644
--- a/release/scripts/startup/bl_ui/space_image.py
+++ b/release/scripts/startup/bl_ui/space_image.py
@@ -817,7 +817,7 @@ class IMAGE_HT_header(Header):
row.prop(sima, "show_stereo_3d", text="")
if show_maskedit:
row = layout.row()
- row.popover(panel='CLIP_PT_mask_display')
+ row.popover(panel='IMAGE_PT_mask_display')
# layers.
layout.template_image_layers(ima, iuser)
@@ -826,12 +826,6 @@ class IMAGE_HT_header(Header):
row = layout.row()
row.prop(sima, "display_channels", icon_only=True)
- row = layout.row(align=True)
- if ima.type == 'COMPOSITE':
- row.operator("image.record_composite", icon='REC')
- if ima.type == 'COMPOSITE' and ima.source in {'MOVIE', 'SEQUENCE'}:
- row.operator("image.play_composite", icon='PLAY')
-
class IMAGE_MT_editor_menus(Menu):
bl_idname = "IMAGE_MT_editor_menus"
@@ -917,8 +911,7 @@ class IMAGE_PT_active_mask_point(MASK_PT_point, Panel):
class IMAGE_PT_mask_display(MASK_PT_display, Panel):
bl_space_type = 'IMAGE_EDITOR'
- bl_region_type = 'UI'
- bl_category = "Mask"
+ bl_region_type = 'HEADER'
# --- end mask ---
diff --git a/release/scripts/startup/bl_ui/space_outliner.py b/release/scripts/startup/bl_ui/space_outliner.py
index 0a4f419362d..febd064147f 100644
--- a/release/scripts/startup/bl_ui/space_outliner.py
+++ b/release/scripts/startup/bl_ui/space_outliner.py
@@ -315,7 +315,7 @@ class OUTLINER_MT_asset(Menu):
@classmethod
def poll(cls, context):
- return context.preferences.experimental.use_asset_browser
+ return context.preferences.experimental.use_extended_asset_browser
def draw(self, context):
layout = self.layout
diff --git a/release/scripts/startup/bl_ui/space_sequencer.py b/release/scripts/startup/bl_ui/space_sequencer.py
index 30467521c3d..20fb39e8c1f 100644
--- a/release/scripts/startup/bl_ui/space_sequencer.py
+++ b/release/scripts/startup/bl_ui/space_sequencer.py
@@ -148,20 +148,6 @@ class SEQUENCER_HT_header(Header):
layout.separator_spacer()
- if st.view_type in {'PREVIEW', 'SEQUENCER_PREVIEW'}:
- layout.prop(st, "display_mode", text="", icon_only=True)
- layout.prop(st, "preview_channels", text="", icon_only=True)
-
- gpd = context.gpencil_data
- tool_settings = context.tool_settings
-
- # Proportional editing
- if gpd and gpd.use_stroke_edit_mode:
- row = layout.row(align=True)
- row.prop(tool_settings, "use_proportional_edit", icon_only=True)
- if tool_settings.use_proportional_edit:
- row.prop(tool_settings, "proportional_edit_falloff", icon_only=True)
-
if st.view_type in {'SEQUENCER', 'SEQUENCER_PREVIEW'}:
tool_settings = context.tool_settings
row = layout.row(align=True)
@@ -170,6 +156,10 @@ class SEQUENCER_HT_header(Header):
sub.popover(panel="SEQUENCER_PT_snapping")
layout.separator_spacer()
+ if st.view_type in {'PREVIEW', 'SEQUENCER_PREVIEW'}:
+ layout.prop(st, "display_mode", text="", icon_only=True)
+ layout.prop(st, "preview_channels", text="", icon_only=True)
+
row = layout.row(align=True)
row.prop(st, "show_strip_overlay", text="", icon='OVERLAY')
sub = row.row(align=True)
diff --git a/release/scripts/startup/bl_ui/space_spreadsheet.py b/release/scripts/startup/bl_ui/space_spreadsheet.py
index afdbfea5091..51f8841419b 100644
--- a/release/scripts/startup/bl_ui/space_spreadsheet.py
+++ b/release/scripts/startup/bl_ui/space_spreadsheet.py
@@ -55,7 +55,7 @@ class SPREADSHEET_HT_header(bpy.types.Header):
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.label(text="No active viewer node", icon='INFO')
layout.separator_spacer()
diff --git a/release/scripts/startup/bl_ui/space_text.py b/release/scripts/startup/bl_ui/space_text.py
index 93ab12e8462..811e7fd41c5 100644
--- a/release/scripts/startup/bl_ui/space_text.py
+++ b/release/scripts/startup/bl_ui/space_text.py
@@ -268,10 +268,7 @@ class TEXT_MT_text(Menu):
layout.operator("text.make_internal")
layout.separator()
- row = layout.row()
- row.active = text.name.endswith(".py")
- row.prop(text, "use_module")
- row = layout.row()
+ layout.prop(text, "use_module")
layout.prop(st, "use_live_edit")
diff --git a/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py b/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py
index 46a6944d2ea..bde710d8dbf 100644
--- a/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py
+++ b/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py
@@ -1903,6 +1903,7 @@ class _defs_gpencil_paint:
brush_basic__draw_color_selector(context, layout, brush, gp_settings, props)
brush_basic_gpencil_paint_settings(layout, context, brush, compact=True)
+ return True
@staticmethod
def generate_from_brushes(context):
diff --git a/release/scripts/startup/bl_ui/space_userpref.py b/release/scripts/startup/bl_ui/space_userpref.py
index 91bd5f04b9d..003f2f223ea 100644
--- a/release/scripts/startup/bl_ui/space_userpref.py
+++ b/release/scripts/startup/bl_ui/space_userpref.py
@@ -1366,11 +1366,6 @@ class USERPREF_PT_saveload_autorun(FilePathsPanel, Panel):
class USERPREF_PT_file_paths_asset_libraries(FilePathsPanel, Panel):
bl_label = "Asset Libraries"
- @classmethod
- def poll(cls, context):
- prefs = context.preferences
- return prefs.experimental.use_asset_browser
-
def draw(self, context):
layout = self.layout
layout.use_property_split = False
@@ -2258,7 +2253,7 @@ class USERPREF_PT_experimental_new_features(ExperimentalPanel, Panel):
context, (
({"property": "use_sculpt_vertex_colors"}, "T71947"),
({"property": "use_sculpt_tools_tilt"}, "T82877"),
- ({"property": "use_asset_browser"}, ("project/profile/124/", "Milestone 1")),
+ ({"property": "use_extended_asset_browser"}, ("project/view/130/", "Project Page")),
({"property": "use_override_templates"}, ("T73318", "Milestone 4")),
),
)
diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py
index 20b706f5004..c6bc6d9b5d3 100644
--- a/release/scripts/startup/bl_ui/space_view3d.py
+++ b/release/scripts/startup/bl_ui/space_view3d.py
@@ -1854,6 +1854,7 @@ class VIEW3D_MT_select_gpencil(Menu):
layout.operator("gpencil.select_linked", text="Linked")
layout.operator("gpencil.select_alternate")
+ layout.operator("gpencil.select_random")
layout.operator_menu_enum("gpencil.select_grouped", "type", text="Grouped")
if context.mode == 'VERTEX_GPENCIL':
diff --git a/release/scripts/startup/bl_ui/space_view3d_toolbar.py b/release/scripts/startup/bl_ui/space_view3d_toolbar.py
index 46fed79332d..16b5ed33f3f 100644
--- a/release/scripts/startup/bl_ui/space_view3d_toolbar.py
+++ b/release/scripts/startup/bl_ui/space_view3d_toolbar.py
@@ -1029,7 +1029,7 @@ class VIEW3D_PT_tools_vertexpaint_options(Panel, View3DPaintPanel):
bl_options = {'DEFAULT_CLOSED'}
@classmethod
- def poll(self, _context):
+ def poll(cls, _context):
# This is currently unused, since there aren't any Vertex Paint mode specific options.
return False
diff --git a/release/scripts/startup/nodeitems_builtins.py b/release/scripts/startup/nodeitems_builtins.py
index 1bc1a2555a5..16201d868a6 100644
--- a/release/scripts/startup/nodeitems_builtins.py
+++ b/release/scripts/startup/nodeitems_builtins.py
@@ -512,6 +512,7 @@ geometry_node_categories = [
NodeItem("GeometryNodeCurveReverse"),
NodeItem("GeometryNodeCurveSplineType"),
NodeItem("GeometryNodeCurveSetHandles"),
+ NodeItem("GeometryNodeCurveSelectHandles"),
]),
GeometryNodeCategory("GEO_PRIMITIVES_CURVE", "Curve Primitives", items=[
NodeItem("GeometryNodeCurvePrimitiveLine"),
diff --git a/source/blender/blenfont/intern/blf_font.c b/source/blender/blenfont/intern/blf_font.c
index 6e2be4a8353..28039ff11ac 100644
--- a/source/blender/blenfont/intern/blf_font.c
+++ b/source/blender/blenfont/intern/blf_font.c
@@ -308,28 +308,6 @@ void blf_font_size(FontBLF *font, unsigned int size, unsigned int dpi)
blf_glyph_cache_release(font);
}
-static GlyphBLF **blf_font_ensure_ascii_table(FontBLF *font, GlyphCacheBLF *gc)
-{
- GlyphBLF **glyph_ascii_table;
-
- glyph_ascii_table = gc->glyph_ascii_table;
-
- /* build ascii on demand */
- if (glyph_ascii_table['0'] == NULL) {
- GlyphBLF *g;
- for (uint i = 0; i < 256; i++) {
- g = blf_glyph_search(gc, i);
- if (!g) {
- FT_UInt glyph_index = FT_Get_Char_Index(font->face, i);
- g = blf_glyph_add(font, gc, glyph_index, i);
- }
- glyph_ascii_table[i] = g;
- }
- }
-
- return glyph_ascii_table;
-}
-
static void blf_font_ensure_ascii_kerning(FontBLF *font,
GlyphCacheBLF *gc,
const FT_UInt kern_mode)
@@ -351,11 +329,12 @@ static void blf_font_ensure_ascii_kerning(FontBLF *font,
* characters.
*/
-/* 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) { \
- _g = (_glyph_ascii_table)[_c]; \
+#define BLF_UTF8_NEXT_FAST(_font, _gc, _g, _str, _i, _c) \
+ if (((_c) = (_str)[_i]) < GLYPH_ASCII_TABLE_SIZE) { \
+ if ((_g = (_gc->glyph_ascii_table)[_c]) == NULL) { \
+ _g = blf_glyph_add(_font, _gc, FT_Get_Char_Index((_font)->face, _c), _c); \
+ _gc->glyph_ascii_table[_c] = _g; \
+ } \
_i++; \
} \
else if ((_c = BLI_str_utf8_as_unicode_step(_str, &(_i))) != BLI_UTF8_ERR) { \
@@ -369,11 +348,10 @@ static void blf_font_ensure_ascii_kerning(FontBLF *font,
(void)0
#define BLF_KERNING_VARS(_font, _has_kerning, _kern_mode) \
- const bool _has_kerning = FT_HAS_KERNING((_font)->face) != 0; \
- const FT_UInt _kern_mode = (_has_kerning == 0) ? 0 : \
- (((_font)->flags & BLF_KERNING_DEFAULT) ? \
- ft_kerning_default : \
- (FT_UInt)FT_KERNING_UNFITTED)
+ const bool _has_kerning = FT_HAS_KERNING((_font)->face); \
+ const FT_UInt _kern_mode = (_has_kerning && !((_font)->flags & BLF_KERNING_DEFAULT)) ? \
+ FT_KERNING_UNFITTED : \
+ FT_KERNING_DEFAULT;
/* NOTE: `blf_font_ensure_ascii_kerning(font, gc, kern_mode);` must be called before this macro. */
@@ -381,7 +359,7 @@ static void blf_font_ensure_ascii_kerning(FontBLF *font,
{ \
if (_g_prev) { \
FT_Vector _delta; \
- if (_c_prev < 0x80 && _c < 0x80) { \
+ if (_c_prev < KERNING_CACHE_TABLE_SIZE && _c < GLYPH_ASCII_TABLE_SIZE) { \
_pen_x += (_font)->kerning_cache->table[_c][_c_prev]; \
} \
else if (FT_Get_Kerning((_font)->face, (_g_prev)->idx, (_g)->idx, _kern_mode, &(_delta)) == \
@@ -420,8 +398,6 @@ static void blf_font_draw_ex(FontBLF *font,
return;
}
- GlyphBLF **glyph_ascii_table = blf_font_ensure_ascii_table(font, gc);
-
BLF_KERNING_VARS(font, has_kerning, kern_mode);
blf_font_ensure_ascii_kerning(font, gc, kern_mode);
@@ -429,7 +405,7 @@ static void blf_font_draw_ex(FontBLF *font,
blf_batch_draw_begin(font);
while ((i < len) && str[i]) {
- BLF_UTF8_NEXT_FAST(font, gc, g, str, i, c, glyph_ascii_table);
+ BLF_UTF8_NEXT_FAST(font, gc, g, str, i, c);
if (UNLIKELY(c == BLI_UTF8_ERR)) {
break;
@@ -472,7 +448,6 @@ static void blf_font_draw_ascii_ex(
int pen_x = 0;
GlyphCacheBLF *gc = blf_glyph_cache_acquire(font);
- GlyphBLF **glyph_ascii_table = blf_font_ensure_ascii_table(font, gc);
BLF_KERNING_VARS(font, has_kerning, kern_mode);
@@ -481,9 +456,12 @@ static void blf_font_draw_ascii_ex(
blf_batch_draw_begin(font);
while ((c = *(str++)) && len--) {
- BLI_assert(c < 128);
- if ((g = glyph_ascii_table[c]) == NULL) {
- continue;
+ BLI_assert(c < GLYPH_ASCII_TABLE_SIZE);
+ if ((g = gc->glyph_ascii_table[c]) == NULL) {
+ g = blf_glyph_add(font, gc, FT_Get_Char_Index((font)->face, c), c);
+ if ((gc->glyph_ascii_table[c] = g) == NULL) {
+ continue;
+ }
}
if (has_kerning) {
BLF_KERNING_STEP_FAST(font, kern_mode, g_prev, g, c_prev, c, pen_x);
@@ -522,12 +500,11 @@ int blf_font_draw_mono(FontBLF *font, const char *str, size_t len, int cwidth)
size_t i = 0;
GlyphCacheBLF *gc = blf_glyph_cache_acquire(font);
- GlyphBLF **glyph_ascii_table = blf_font_ensure_ascii_table(font, gc);
blf_batch_draw_begin(font);
while ((i < len) && str[i]) {
- BLF_UTF8_NEXT_FAST(font, gc, g, str, i, c, glyph_ascii_table);
+ BLF_UTF8_NEXT_FAST(font, gc, g, str, i, c);
if (UNLIKELY(c == BLI_UTF8_ERR)) {
break;
@@ -568,8 +545,6 @@ static void blf_font_draw_buffer_ex(FontBLF *font,
int pen_y_basis = (int)font->pos[1] + pen_y;
size_t i = 0;
- GlyphBLF **glyph_ascii_table = blf_font_ensure_ascii_table(font, gc);
-
/* buffer specific vars */
FontBufInfoBLF *buf_info = &font->buf_info;
const float *b_col_float = buf_info->col_float;
@@ -584,7 +559,7 @@ static void blf_font_draw_buffer_ex(FontBLF *font,
/* another buffer specific call for color conversion */
while ((i < len) && str[i]) {
- BLF_UTF8_NEXT_FAST(font, gc, g, str, i, c, glyph_ascii_table);
+ BLF_UTF8_NEXT_FAST(font, gc, g, str, i, c);
if (UNLIKELY(c == BLI_UTF8_ERR)) {
break;
@@ -741,7 +716,6 @@ size_t blf_font_width_to_strlen(
size_t i, i_prev;
GlyphCacheBLF *gc = blf_glyph_cache_acquire(font);
- GlyphBLF **glyph_ascii_table = blf_font_ensure_ascii_table(font, gc);
const int width_i = (int)width;
BLF_KERNING_VARS(font, has_kerning, kern_mode);
@@ -752,7 +726,7 @@ size_t blf_font_width_to_strlen(
for (i_prev = i = 0, width_new = pen_x = 0, g_prev = NULL, c_prev = 0; (i < len) && str[i];
i_prev = i, width_new = pen_x, c_prev = c, g_prev = g) {
- BLF_UTF8_NEXT_FAST(font, gc, g, str, i, c, glyph_ascii_table);
+ BLF_UTF8_NEXT_FAST(font, gc, g, str, i, c);
if (blf_font_width_to_strlen_glyph_process(
font, has_kerning, kern_mode, c_prev, c, g_prev, g, &pen_x, width_i)) {
@@ -778,7 +752,6 @@ size_t blf_font_width_to_rstrlen(
char *s, *s_prev;
GlyphCacheBLF *gc = blf_glyph_cache_acquire(font);
- GlyphBLF **glyph_ascii_table = blf_font_ensure_ascii_table(font, gc);
const int width_i = (int)width;
BLF_KERNING_VARS(font, has_kerning, kern_mode);
@@ -794,7 +767,7 @@ size_t blf_font_width_to_rstrlen(
i_prev = (size_t)((s_prev != NULL) ? s_prev - str : 0);
i_tmp = i;
- BLF_UTF8_NEXT_FAST(font, gc, g, str, i_tmp, c, glyph_ascii_table);
+ BLF_UTF8_NEXT_FAST(font, gc, g, str, i_tmp, c);
for (width_new = pen_x = 0; (s != NULL);
i = i_prev, s = s_prev, c = c_prev, g = g_prev, g_prev = NULL, width_new = pen_x) {
s_prev = BLI_str_find_prev_char_utf8(str, s);
@@ -802,7 +775,7 @@ size_t blf_font_width_to_rstrlen(
if (s_prev != NULL) {
i_tmp = i_prev;
- BLF_UTF8_NEXT_FAST(font, gc, g_prev, str, i_tmp, c_prev, glyph_ascii_table);
+ BLF_UTF8_NEXT_FAST(font, gc, g_prev, str, i_tmp, c_prev);
BLI_assert(i_tmp == i);
}
@@ -832,9 +805,6 @@ static void blf_font_boundbox_ex(FontBLF *font,
GlyphBLF *g, *g_prev = NULL;
int pen_x = 0;
size_t i = 0;
-
- GlyphBLF **glyph_ascii_table = blf_font_ensure_ascii_table(font, gc);
-
rctf gbox;
BLF_KERNING_VARS(font, has_kerning, kern_mode);
@@ -847,7 +817,7 @@ static void blf_font_boundbox_ex(FontBLF *font,
blf_font_ensure_ascii_kerning(font, gc, kern_mode);
while ((i < len) && str[i]) {
- BLF_UTF8_NEXT_FAST(font, gc, g, str, i, c, glyph_ascii_table);
+ BLF_UTF8_NEXT_FAST(font, gc, g, str, i, c);
if (UNLIKELY(c == BLI_UTF8_ERR)) {
break;
@@ -937,7 +907,6 @@ static void blf_font_wrap_apply(FontBLF *font,
int pen_x_next = 0;
GlyphCacheBLF *gc = blf_glyph_cache_acquire(font);
- GlyphBLF **glyph_ascii_table = blf_font_ensure_ascii_table(font, gc);
BLF_KERNING_VARS(font, has_kerning, kern_mode);
@@ -953,7 +922,7 @@ static void blf_font_wrap_apply(FontBLF *font,
size_t i_curr = i;
bool do_draw = false;
- BLF_UTF8_NEXT_FAST(font, gc, g, str, i, c, glyph_ascii_table);
+ BLF_UTF8_NEXT_FAST(font, gc, g, str, i, c);
if (UNLIKELY(c == BLI_UTF8_ERR)) {
break;
@@ -1154,8 +1123,6 @@ float blf_font_fixed_width(FontBLF *font)
const unsigned int c = ' ';
GlyphCacheBLF *gc = blf_glyph_cache_acquire(font);
- blf_font_ensure_ascii_table(font, gc);
-
GlyphBLF *g = blf_glyph_search(gc, c);
if (!g) {
g = blf_glyph_add(font, gc, FT_Get_Char_Index(font->face, c), c);
@@ -1195,15 +1162,13 @@ static void blf_font_boundbox_foreach_glyph_ex(FontBLF *font,
return;
}
- GlyphBLF **glyph_ascii_table = blf_font_ensure_ascii_table(font, gc);
-
BLF_KERNING_VARS(font, has_kerning, kern_mode);
blf_font_ensure_ascii_kerning(font, gc, kern_mode);
while ((i < len) && str[i]) {
i_curr = i;
- BLF_UTF8_NEXT_FAST(font, gc, g, str, i, c, glyph_ascii_table);
+ BLF_UTF8_NEXT_FAST(font, gc, g, str, i, c);
if (UNLIKELY(c == BLI_UTF8_ERR)) {
break;
@@ -1261,7 +1226,7 @@ int blf_font_count_missing_chars(FontBLF *font,
while (i < len) {
unsigned int c;
- if ((c = str[i]) < 0x80) {
+ if ((c = str[i]) < GLYPH_ASCII_TABLE_SIZE) {
i++;
}
else if ((c = BLI_str_utf8_as_unicode_step(str, &i)) != BLI_UTF8_ERR) {
@@ -1429,7 +1394,6 @@ int blf_font_height_max(FontBLF *font)
int height_max;
GlyphCacheBLF *gc = blf_glyph_cache_acquire(font);
- blf_font_ensure_ascii_table(font, gc);
height_max = gc->glyph_height_max;
blf_glyph_cache_release(font);
@@ -1441,7 +1405,6 @@ int blf_font_width_max(FontBLF *font)
int width_max;
GlyphCacheBLF *gc = blf_glyph_cache_acquire(font);
- blf_font_ensure_ascii_table(font, gc);
width_max = gc->glyph_width_max;
blf_glyph_cache_release(font);
@@ -1453,7 +1416,6 @@ float blf_font_descender(FontBLF *font)
float descender;
GlyphCacheBLF *gc = blf_glyph_cache_acquire(font);
- blf_font_ensure_ascii_table(font, gc);
descender = gc->descender;
blf_glyph_cache_release(font);
@@ -1465,7 +1427,6 @@ float blf_font_ascender(FontBLF *font)
float ascender;
GlyphCacheBLF *gc = blf_glyph_cache_acquire(font);
- blf_font_ensure_ascii_table(font, gc);
ascender = gc->ascender;
blf_glyph_cache_release(font);
diff --git a/source/blender/blenfont/intern/blf_glyph.c b/source/blender/blenfont/intern/blf_glyph.c
index 3f01501fda4..35938a7d5c3 100644
--- a/source/blender/blenfont/intern/blf_glyph.c
+++ b/source/blender/blenfont/intern/blf_glyph.c
@@ -80,8 +80,8 @@ KerningCacheBLF *blf_kerning_cache_new(FontBLF *font, GlyphCacheBLF *gc)
kc->mode = font->kerning_mode;
unsigned int i, j;
- for (i = 0; i < 0x80; i++) {
- for (j = 0; j < 0x80; j++) {
+ for (i = 0; i < KERNING_CACHE_TABLE_SIZE; i++) {
+ for (j = 0; j < KERNING_CACHE_TABLE_SIZE; j++) {
GlyphBLF *g = blf_glyph_search(gc, i);
if (!g) {
FT_UInt glyph_index = FT_Get_Char_Index(font->face, i);
@@ -144,8 +144,6 @@ GlyphCacheBLF *blf_glyph_cache_new(FontBLF *font)
memset(gc->glyph_ascii_table, 0, sizeof(gc->glyph_ascii_table));
memset(gc->bucket, 0, sizeof(gc->bucket));
- gc->glyphs_len_max = (int)font->face->num_glyphs;
- gc->glyphs_len_free = (int)font->face->num_glyphs;
gc->ascender = ((float)font->face->size->metrics.ascender) / 64.0f;
gc->descender = ((float)font->face->size->metrics.descender) / 64.0f;
@@ -514,7 +512,6 @@ void blf_glyph_render(FontBLF *font, GlyphCacheBLF *gc, GlyphBLF *g, float x, fl
memcpy(&gc->bitmap_result[gc->bitmap_len], g->bitmap, (size_t)buff_size);
gc->bitmap_len = bitmap_len;
- gc->glyphs_len_free--;
g->glyph_cache = gc;
}
diff --git a/source/blender/blenfont/intern/blf_internal_types.h b/source/blender/blenfont/intern/blf_internal_types.h
index 36bb8769306..6bcacc62a30 100644
--- a/source/blender/blenfont/intern/blf_internal_types.h
+++ b/source/blender/blenfont/intern/blf_internal_types.h
@@ -28,6 +28,12 @@
#define BLF_BATCH_DRAW_LEN_MAX 2048 /* in glyph */
+/* Number of characters in GlyphCacheBLF.glyph_ascii_table. */
+#define GLYPH_ASCII_TABLE_SIZE 128
+
+/* Number of characters in KerningCacheBLF.table. */
+#define KERNING_CACHE_TABLE_SIZE 128
+
typedef struct BatchBLF {
struct FontBLF *font; /* can only batch glyph from the same font */
struct GPUBatch *batch;
@@ -51,7 +57,7 @@ typedef struct KerningCacheBLF {
/* only cache a ascii glyph pairs. Only store the x
* offset we are interested in, instead of the full FT_Vector. */
- int table[0x80][0x80];
+ int table[KERNING_CACHE_TABLE_SIZE][KERNING_CACHE_TABLE_SIZE];
} KerningCacheBLF;
typedef struct GlyphCacheBLF {
@@ -71,7 +77,7 @@ typedef struct GlyphCacheBLF {
ListBase bucket[257];
/* fast ascii lookup */
- struct GlyphBLF *glyph_ascii_table[256];
+ struct GlyphBLF *glyph_ascii_table[GLYPH_ASCII_TABLE_SIZE];
/* texture array, to draw the glyphs. */
GPUTexture *texture;
@@ -84,12 +90,6 @@ typedef struct GlyphCacheBLF {
int glyph_width_max;
int glyph_height_max;
- /* number of glyphs in the font. */
- int glyphs_len_max;
-
- /* number of glyphs not yet loaded (decreases every glyph loaded). */
- int glyphs_len_free;
-
/* ascender and descender value. */
float ascender;
float descender;
@@ -99,7 +99,7 @@ typedef struct GlyphBLF {
struct GlyphBLF *next;
struct GlyphBLF *prev;
- /* and the character, as UTF8 */
+ /* and the character, as UTF-32 */
unsigned int c;
/* freetype2 index, to speed-up the search. */
diff --git a/source/blender/blenkernel/BKE_blender_version.h b/source/blender/blenkernel/BKE_blender_version.h
index 5ef56fab9cb..4ed4225c836 100644
--- a/source/blender/blenkernel/BKE_blender_version.h
+++ b/source/blender/blenkernel/BKE_blender_version.h
@@ -39,7 +39,7 @@ extern "C" {
/* Blender file format version. */
#define BLENDER_FILE_VERSION BLENDER_VERSION
-#define BLENDER_FILE_SUBVERSION 17
+#define BLENDER_FILE_SUBVERSION 18
/* Minimum Blender version that supports reading file written with the current
* version. Older Blender versions will test this and show a warning if the file
diff --git a/source/blender/blenkernel/BKE_bvhutils.h b/source/blender/blenkernel/BKE_bvhutils.h
index 8be2fcbdb83..06be8ec80fc 100644
--- a/source/blender/blenkernel/BKE_bvhutils.h
+++ b/source/blender/blenkernel/BKE_bvhutils.h
@@ -69,7 +69,7 @@ typedef struct BVHTreeFromMesh {
BVHTree_NearestPointCallback nearest_callback;
BVHTree_RayCastCallback raycast_callback;
- /* Vertex array, so that callbacks have instante access to data */
+ /* Vertex array, so that callbacks have instant access to data. */
const struct MVert *vert;
const struct MEdge *edge; /* only used for BVHTreeFromMeshEdges */
const struct MFace *face;
diff --git a/source/blender/blenkernel/BKE_collection.h b/source/blender/blenkernel/BKE_collection.h
index 8b8d0f7b107..2c7143be60e 100644
--- a/source/blender/blenkernel/BKE_collection.h
+++ b/source/blender/blenkernel/BKE_collection.h
@@ -65,7 +65,7 @@ void BKE_collection_add_from_collection(struct Main *bmain,
struct Scene *scene,
struct Collection *collection_src,
struct Collection *collection_dst);
-void BKE_collection_free(struct Collection *collection);
+void BKE_collection_free_data(struct Collection *collection);
bool BKE_collection_delete(struct Main *bmain, struct Collection *collection, bool hierarchy);
struct Collection *BKE_collection_duplicate(struct Main *bmain,
diff --git a/source/blender/blenkernel/BKE_constraint.h b/source/blender/blenkernel/BKE_constraint.h
index 575df93a9fc..784b395dfa5 100644
--- a/source/blender/blenkernel/BKE_constraint.h
+++ b/source/blender/blenkernel/BKE_constraint.h
@@ -192,6 +192,28 @@ bool BKE_constraint_remove_ex(ListBase *list,
bool clear_dep);
bool BKE_constraint_remove(ListBase *list, struct bConstraint *con);
+bool BKE_constraint_apply_for_object(struct Depsgraph *depsgraph,
+ struct Scene *scene,
+ struct Object *ob,
+ struct bConstraint *con);
+bool BKE_constraint_apply_and_remove_for_object(struct Depsgraph *depsgraph,
+ struct Scene *scene,
+ ListBase /*bConstraint*/ *constraints,
+ struct Object *ob,
+ struct bConstraint *con);
+
+bool BKE_constraint_apply_for_pose(struct Depsgraph *depsgraph,
+ struct Scene *scene,
+ struct Object *ob,
+ struct bPoseChannel *pchan,
+ struct bConstraint *con);
+bool BKE_constraint_apply_and_remove_for_pose(struct Depsgraph *depsgraph,
+ struct Scene *scene,
+ ListBase /*bConstraint*/ *constraints,
+ struct Object *ob,
+ struct bConstraint *con,
+ struct bPoseChannel *pchan);
+
void BKE_constraint_panel_expand(struct bConstraint *con);
/* Constraints + Proxies function prototypes */
diff --git a/source/blender/blenkernel/BKE_context.h b/source/blender/blenkernel/BKE_context.h
index 8917580689d..eda6a03fa1a 100644
--- a/source/blender/blenkernel/BKE_context.h
+++ b/source/blender/blenkernel/BKE_context.h
@@ -360,7 +360,7 @@ 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);
+const struct AssetLibraryReference *CTX_wm_asset_library_ref(const bContext *C);
struct AssetHandle CTX_wm_asset_handle(const bContext *C, bool *r_is_valid);
bool CTX_wm_interface_locked(const bContext *C);
diff --git a/source/blender/blenkernel/BKE_global.h b/source/blender/blenkernel/BKE_global.h
index 31928b5e80a..89713e9ad0a 100644
--- a/source/blender/blenkernel/BKE_global.h
+++ b/source/blender/blenkernel/BKE_global.h
@@ -145,7 +145,8 @@ enum {
G_DEBUG_DEPSGRAPH_TIME = (1 << 11), /* depsgraph timing statistics and messages */
G_DEBUG_DEPSGRAPH_NO_THREADS = (1 << 12), /* single threaded depsgraph */
G_DEBUG_DEPSGRAPH_PRETTY = (1 << 13), /* use pretty colors in depsgraph messages */
- G_DEBUG_DEPSGRAPH_UUID = (1 << 14), /* use pretty colors in depsgraph messages */
+ G_DEBUG_DEPSGRAPH_UUID = (1 << 14), /* Verify validness of session-wide identifiers
+ * assigned to ID datablocks */
G_DEBUG_DEPSGRAPH = (G_DEBUG_DEPSGRAPH_BUILD | G_DEBUG_DEPSGRAPH_EVAL | G_DEBUG_DEPSGRAPH_TAG |
G_DEBUG_DEPSGRAPH_TIME | G_DEBUG_DEPSGRAPH_UUID),
G_DEBUG_SIMDATA = (1 << 15), /* sim debug data display */
diff --git a/source/blender/blenkernel/BKE_lib_id.h b/source/blender/blenkernel/BKE_lib_id.h
index fac5dc8c010..bb875f8d1c9 100644
--- a/source/blender/blenkernel/BKE_lib_id.h
+++ b/source/blender/blenkernel/BKE_lib_id.h
@@ -152,8 +152,6 @@ void BKE_libblock_copy_ex(struct Main *bmain,
const int orig_flag);
void *BKE_libblock_copy(struct Main *bmain, const struct ID *id) ATTR_WARN_UNUSED_RESULT
ATTR_NONNULL();
-/* Special version: used by data-block localization. */
-void *BKE_libblock_copy_for_localize(const struct ID *id);
void BKE_libblock_rename(struct Main *bmain, struct ID *id, const char *name) ATTR_NONNULL();
void BLI_libblock_ensure_unique_name(struct Main *bmain, const char *name) ATTR_NONNULL();
@@ -201,6 +199,8 @@ enum {
void BKE_libblock_free_datablock(struct ID *id, const int flag) ATTR_NONNULL();
void BKE_libblock_free_data(struct ID *id, const bool do_id_user) ATTR_NONNULL();
+void BKE_libblock_free_data_py(struct ID *id);
+
void BKE_id_free_ex(struct Main *bmain, void *idv, int flag, const bool use_flag_from_idtag);
void BKE_id_free(struct Main *bmain, void *idv);
diff --git a/source/blender/blenkernel/BKE_mesh.h b/source/blender/blenkernel/BKE_mesh.h
index ef1384c804b..8000e57e08e 100644
--- a/source/blender/blenkernel/BKE_mesh.h
+++ b/source/blender/blenkernel/BKE_mesh.h
@@ -281,39 +281,21 @@ void BKE_mesh_recalc_looptri_with_normals(const struct MLoop *mloop,
/* *** mesh_normals.cc *** */
void BKE_mesh_normals_tag_dirty(struct Mesh *mesh);
-void BKE_mesh_calc_normals_mapping_simple(struct Mesh *me);
-void BKE_mesh_calc_normals_mapping(struct MVert *mverts,
- int numVerts,
- const struct MLoop *mloop,
- const struct MPoly *mpolys,
- int numLoops,
- int numPolys,
- float (*r_polyNors)[3],
- const struct MFace *mfaces,
- int numFaces,
- const int *origIndexFace,
- float (*r_faceNors)[3]);
-void BKE_mesh_calc_normals_mapping_ex(struct MVert *mverts,
- int numVerts,
- const struct MLoop *mloop,
- const struct MPoly *mpolys,
- int numLoops,
- int numPolys,
- float (*r_polyNors)[3],
- const struct MFace *mfaces,
- int numFaces,
- const int *origIndexFace,
- float (*r_faceNors)[3],
- const bool only_face_normals);
-void BKE_mesh_calc_normals_poly(struct MVert *mverts,
- float (*r_vertnors)[3],
- int numVerts,
+void BKE_mesh_calc_normals_poly(const struct MVert *mvert,
+ int mvert_len,
const struct MLoop *mloop,
- const struct MPoly *mpolys,
- int numLoops,
- int numPolys,
- float (*r_polyNors)[3],
- const bool only_face_normals);
+ int mloop_len,
+ const struct MPoly *mpoly,
+ int mpoly_len,
+ float (*r_poly_normals)[3]);
+void BKE_mesh_calc_normals_poly_and_vertex(struct MVert *mvert,
+ int mvert_len,
+ const struct MLoop *mloop,
+ int mloop_len,
+ const struct MPoly *mpolys,
+ int mpoly_len,
+ float (*r_poly_normals)[3],
+ float (*r_vert_normals)[3]);
void BKE_mesh_calc_normals(struct Mesh *me);
void BKE_mesh_ensure_normals(struct Mesh *me);
void BKE_mesh_ensure_normals_for_display(struct Mesh *mesh);
diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h
index c9f5777109a..3b8ab619510 100644
--- a/source/blender/blenkernel/BKE_node.h
+++ b/source/blender/blenkernel/BKE_node.h
@@ -1476,7 +1476,8 @@ int ntreeTexExecTree(struct bNodeTree *ntree,
#define GEO_NODE_CURVE_TRIM 1071
#define GEO_NODE_CURVE_SET_HANDLES 1072
#define GEO_NODE_CURVE_SPLINE_TYPE 1073
-#define GEO_NODE_MESH_INSET 1074
+#define GEO_NODE_CURVE_SELECT_HANDLES 1074
+#define GEO_NODE_MESH_INSET 1075
/** \} */
diff --git a/source/blender/blenkernel/intern/DerivedMesh.cc b/source/blender/blenkernel/intern/DerivedMesh.cc
index ba8cf8debe9..59e81938e79 100644
--- a/source/blender/blenkernel/intern/DerivedMesh.cc
+++ b/source/blender/blenkernel/intern/DerivedMesh.cc
@@ -360,7 +360,7 @@ void DM_init(DerivedMesh *dm,
dm->needsFree = 1;
dm->dirty = (DMDirtyFlag)0;
- /* Don't use CustomData_reset(...); because we don't want to touch custom-data. */
+ /* Don't use #CustomData_reset because we don't want to touch custom-data. */
copy_vn_i(dm->vertData.typemap, CD_NUMTYPES, -1);
copy_vn_i(dm->edgeData.typemap, CD_NUMTYPES, -1);
copy_vn_i(dm->faceData.typemap, CD_NUMTYPES, -1);
@@ -816,15 +816,14 @@ static void mesh_calc_modifier_final_normals(const Mesh *mesh_input,
if (!CustomData_has_layer(&mesh_final->pdata, CD_NORMAL)) {
float(*polynors)[3] = (float(*)[3])CustomData_add_layer(
&mesh_final->pdata, CD_NORMAL, CD_CALLOC, nullptr, mesh_final->totpoly);
- BKE_mesh_calc_normals_poly(mesh_final->mvert,
- nullptr,
- mesh_final->totvert,
- mesh_final->mloop,
- mesh_final->mpoly,
- mesh_final->totloop,
- mesh_final->totpoly,
- polynors,
- false);
+ BKE_mesh_calc_normals_poly_and_vertex(mesh_final->mvert,
+ mesh_final->totvert,
+ mesh_final->mloop,
+ mesh_final->totloop,
+ mesh_final->mpoly,
+ mesh_final->totpoly,
+ polynors,
+ nullptr);
}
}
@@ -1536,15 +1535,14 @@ static void editbmesh_calc_modifier_final_normals(Mesh *mesh_final,
if (!CustomData_has_layer(&mesh_final->pdata, CD_NORMAL)) {
float(*polynors)[3] = (float(*)[3])CustomData_add_layer(
&mesh_final->pdata, CD_NORMAL, CD_CALLOC, nullptr, mesh_final->totpoly);
- BKE_mesh_calc_normals_poly(mesh_final->mvert,
- nullptr,
- mesh_final->totvert,
- mesh_final->mloop,
- mesh_final->mpoly,
- mesh_final->totloop,
- mesh_final->totpoly,
- polynors,
- false);
+ BKE_mesh_calc_normals_poly_and_vertex(mesh_final->mvert,
+ mesh_final->totvert,
+ mesh_final->mloop,
+ mesh_final->totloop,
+ mesh_final->mpoly,
+ mesh_final->totpoly,
+ polynors,
+ nullptr);
}
}
diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c
index 10a865880f2..92b0db5b214 100644
--- a/source/blender/blenkernel/intern/anim_sys.c
+++ b/source/blender/blenkernel/intern/anim_sys.c
@@ -2671,7 +2671,7 @@ static void animsys_create_action_track_strip(const AnimData *adt,
static bool is_nlatrack_evaluatable(const AnimData *adt, const NlaTrack *nlt)
{
/* Skip disabled tracks unless it contains the tweaked strip. */
- const bool contains_tweak_strip = (adt->flag & ADT_NLA_EDIT_ON) &&
+ const bool contains_tweak_strip = (adt->flag & ADT_NLA_EDIT_ON) && adt->act_track &&
(nlt->index == adt->act_track->index);
if ((nlt->flag & NLATRACK_DISABLED) && !contains_tweak_strip) {
return false;
diff --git a/source/blender/blenkernel/intern/blendfile.c b/source/blender/blenkernel/intern/blendfile.c
index 61827be08e5..1c5d8804280 100644
--- a/source/blender/blenkernel/intern/blendfile.c
+++ b/source/blender/blenkernel/intern/blendfile.c
@@ -660,10 +660,6 @@ UserDef *BKE_blendfile_userdef_from_defaults(void)
BKE_studiolight_default(userdef->light_param, userdef->light_ambient);
BKE_preferences_asset_library_default_add(userdef);
- /* Enable asset browser features by default for alpha testing.
- * BLO_sanitize_experimental_features_userpref_blend() will disable it again for non-alpha
- * builds. */
- userdef->experimental.use_asset_browser = true;
return userdef;
}
diff --git a/source/blender/blenkernel/intern/boids.c b/source/blender/blenkernel/intern/boids.c
index 9caf416cd0c..a7257133821 100644
--- a/source/blender/blenkernel/intern/boids.c
+++ b/source/blender/blenkernel/intern/boids.c
@@ -342,10 +342,7 @@ static bool rule_avoid_collision(BoidRule *rule,
}
}
}
- if (ptn) {
- MEM_freeN(ptn);
- ptn = NULL;
- }
+ MEM_SAFE_FREE(ptn);
/* check boids in other systems */
for (pt = bbd->sim->psys->targets.first; pt; pt = pt->next) {
@@ -401,10 +398,7 @@ static bool rule_avoid_collision(BoidRule *rule,
}
}
- if (ptn) {
- MEM_freeN(ptn);
- ptn = NULL;
- }
+ MEM_SAFE_FREE(ptn);
}
}
@@ -435,10 +429,7 @@ static bool rule_separate(BoidRule *UNUSED(rule),
len = ptn[1].dist;
ret = 1;
}
- if (ptn) {
- MEM_freeN(ptn);
- ptn = NULL;
- }
+ MEM_SAFE_FREE(ptn);
/* check other boid systems */
for (pt = bbd->sim->psys->targets.first; pt; pt = pt->next) {
@@ -457,10 +448,7 @@ static bool rule_separate(BoidRule *UNUSED(rule),
ret = true;
}
- if (ptn) {
- MEM_freeN(ptn);
- ptn = NULL;
- }
+ MEM_SAFE_FREE(ptn);
}
}
return ret;
@@ -723,10 +711,7 @@ static bool rule_fight(BoidRule *rule, BoidBrainData *bbd, BoidValues *val, Part
f_strength += bbd->part->boids->strength * health;
- if (ptn) {
- MEM_freeN(ptn);
- ptn = NULL;
- }
+ MEM_SAFE_FREE(ptn);
/* add other friendlies and calculate enemy strength and find closest enemy */
for (pt = bbd->sim->psys->targets.first; pt; pt = pt->next) {
@@ -755,10 +740,7 @@ static bool rule_fight(BoidRule *rule, BoidBrainData *bbd, BoidValues *val, Part
f_strength += epsys->part->boids->strength * health;
}
- if (ptn) {
- MEM_freeN(ptn);
- ptn = NULL;
- }
+ MEM_SAFE_FREE(ptn);
}
}
/* decide action if enemy presence found */
diff --git a/source/blender/blenkernel/intern/brush.c b/source/blender/blenkernel/intern/brush.c
index abf7bab7612..3418e37642c 100644
--- a/source/blender/blenkernel/intern/brush.c
+++ b/source/blender/blenkernel/intern/brush.c
@@ -660,10 +660,7 @@ static void brush_gpencil_curvemap_reset(CurveMap *cuma, int tot, int preset)
break;
}
- if (cuma->table) {
- MEM_freeN(cuma->table);
- cuma->table = NULL;
- }
+ MEM_SAFE_FREE(cuma->table);
}
void BKE_gpencil_brush_preset_set(Main *bmain, Brush *brush, const short type)
diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c
index 0fa58a74f2b..f5ff936e18b 100644
--- a/source/blender/blenkernel/intern/cloth.c
+++ b/source/blender/blenkernel/intern/cloth.c
@@ -447,11 +447,7 @@ void cloth_free_modifier(ClothModifierData *clmd)
SIM_cloth_solver_free(clmd);
/* Free the verts. */
- if (cloth->verts != NULL) {
- MEM_freeN(cloth->verts);
- }
-
- cloth->verts = NULL;
+ MEM_SAFE_FREE(cloth->verts);
cloth->mvert_num = 0;
/* Free the springs. */
@@ -529,11 +525,7 @@ void cloth_free_modifier_extern(ClothModifierData *clmd)
SIM_cloth_solver_free(clmd);
/* Free the verts. */
- if (cloth->verts != NULL) {
- MEM_freeN(cloth->verts);
- }
-
- cloth->verts = NULL;
+ MEM_SAFE_FREE(cloth->verts);
cloth->mvert_num = 0;
/* Free the springs. */
diff --git a/source/blender/blenkernel/intern/collection.c b/source/blender/blenkernel/intern/collection.c
index dbcd80fe065..b62e33ff564 100644
--- a/source/blender/blenkernel/intern/collection.c
+++ b/source/blender/blenkernel/intern/collection.c
@@ -508,7 +508,7 @@ void BKE_collection_add_from_collection(Main *bmain,
* \{ */
/** Free (or release) any data used by this collection (does not free the collection itself). */
-void BKE_collection_free(Collection *collection)
+void BKE_collection_free_data(Collection *collection)
{
BKE_libblock_free_data(&collection->id, false);
collection_free_data(&collection->id);
diff --git a/source/blender/blenkernel/intern/colortools.c b/source/blender/blenkernel/intern/colortools.c
index a9f0f69b855..f2c2e552a9f 100644
--- a/source/blender/blenkernel/intern/colortools.c
+++ b/source/blender/blenkernel/intern/colortools.c
@@ -1716,22 +1716,10 @@ void BKE_scopes_update(Scopes *scopes,
void BKE_scopes_free(Scopes *scopes)
{
- if (scopes->waveform_1) {
- MEM_freeN(scopes->waveform_1);
- scopes->waveform_1 = NULL;
- }
- if (scopes->waveform_2) {
- MEM_freeN(scopes->waveform_2);
- scopes->waveform_2 = NULL;
- }
- if (scopes->waveform_3) {
- MEM_freeN(scopes->waveform_3);
- scopes->waveform_3 = NULL;
- }
- if (scopes->vecscope) {
- MEM_freeN(scopes->vecscope);
- scopes->vecscope = NULL;
- }
+ MEM_SAFE_FREE(scopes->waveform_1);
+ MEM_SAFE_FREE(scopes->waveform_2);
+ MEM_SAFE_FREE(scopes->waveform_3);
+ MEM_SAFE_FREE(scopes->vecscope);
}
void BKE_scopes_new(Scopes *scopes)
diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c
index 0da29ded13d..4b26022039e 100644
--- a/source/blender/blenkernel/intern/constraint.c
+++ b/source/blender/blenkernel/intern/constraint.c
@@ -5677,6 +5677,111 @@ bool BKE_constraint_remove_ex(ListBase *list, Object *ob, bConstraint *con, bool
return false;
}
+/* Apply the specified constraint in the given constraint stack */
+bool BKE_constraint_apply_for_object(Depsgraph *depsgraph,
+ Scene *scene,
+ Object *ob,
+ bConstraint *con)
+{
+ if (!con) {
+ return false;
+ }
+
+ const float ctime = BKE_scene_frame_get(scene);
+
+ bConstraint *new_con = BKE_constraint_duplicate_ex(con, 0, !ID_IS_LINKED(ob));
+ ListBase single_con = {new_con, new_con};
+
+ bConstraintOb *cob = BKE_constraints_make_evalob(
+ depsgraph, scene, ob, NULL, CONSTRAINT_OBTYPE_OBJECT);
+ /* Undo the effect of the current constraint stack evaluation. */
+ mul_m4_m4m4(cob->matrix, ob->constinv, cob->matrix);
+
+ /* Evaluate single constraint. */
+ BKE_constraints_solve(depsgraph, &single_con, cob, ctime);
+ /* Copy transforms back. This will leave the object in a bad state
+ * as ob->constinv will be wrong until next evaluation. */
+ BKE_constraints_clear_evalob(cob);
+
+ /* Free the copied constraint. */
+ BKE_constraint_free_data(new_con);
+ BLI_freelinkN(&single_con, new_con);
+
+ /* Apply transform from matrix. */
+ BKE_object_apply_mat4(ob, ob->obmat, true, true);
+
+ return true;
+}
+
+bool BKE_constraint_apply_and_remove_for_object(Depsgraph *depsgraph,
+ Scene *scene,
+ ListBase /*bConstraint*/ *constraints,
+ Object *ob,
+ bConstraint *con)
+{
+ if (!BKE_constraint_apply_for_object(depsgraph, scene, ob, con)) {
+ return false;
+ }
+
+ return BKE_constraint_remove_ex(constraints, ob, con, true);
+}
+
+bool BKE_constraint_apply_for_pose(
+ Depsgraph *depsgraph, Scene *scene, Object *ob, bPoseChannel *pchan, bConstraint *con)
+{
+ if (!con) {
+ return false;
+ }
+
+ const float ctime = BKE_scene_frame_get(scene);
+
+ bConstraint *new_con = BKE_constraint_duplicate_ex(con, 0, !ID_IS_LINKED(ob));
+ ListBase single_con;
+ single_con.first = new_con;
+ single_con.last = new_con;
+
+ float vec[3];
+ copy_v3_v3(vec, pchan->pose_mat[3]);
+
+ bConstraintOb *cob = BKE_constraints_make_evalob(
+ depsgraph, scene, ob, pchan, CONSTRAINT_OBTYPE_BONE);
+ /* Undo the effects of currently applied constraints. */
+ mul_m4_m4m4(cob->matrix, pchan->constinv, cob->matrix);
+ /* Evaluate single constraint. */
+ BKE_constraints_solve(depsgraph, &single_con, cob, ctime);
+ BKE_constraints_clear_evalob(cob);
+
+ /* Free the copied constraint. */
+ BKE_constraint_free_data(new_con);
+ BLI_freelinkN(&single_con, new_con);
+
+ /* Prevent constraints breaking a chain. */
+ if (pchan->bone->flag & BONE_CONNECTED) {
+ copy_v3_v3(pchan->pose_mat[3], vec);
+ }
+
+ /* Apply transform from matrix. */
+ float mat[4][4];
+ BKE_armature_mat_pose_to_bone(pchan, pchan->pose_mat, mat);
+ BKE_pchan_apply_mat4(pchan, mat, true);
+
+ return true;
+}
+
+bool BKE_constraint_apply_and_remove_for_pose(Depsgraph *depsgraph,
+ Scene *scene,
+ ListBase /*bConstraint*/ *constraints,
+ Object *ob,
+ bConstraint *con,
+ bPoseChannel *pchan)
+{
+ if (!BKE_constraint_apply_for_pose(depsgraph, scene, ob, pchan, con)) {
+ return false;
+ }
+
+ return BKE_constraint_remove_ex(constraints, ob, con, true);
+}
+
void BKE_constraint_panel_expand(bConstraint *con)
{
con->ui_expand_flag |= UI_PANEL_DATA_EXPAND_ROOT;
diff --git a/source/blender/blenkernel/intern/context.c b/source/blender/blenkernel/intern/context.c
index dced945bea0..7763bb9ca08 100644
--- a/source/blender/blenkernel/intern/context.c
+++ b/source/blender/blenkernel/intern/context.c
@@ -1448,9 +1448,9 @@ 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)
+const AssetLibraryReference *CTX_wm_asset_library_ref(const bContext *C)
{
- return ctx_data_pointer_get(C, "asset_library");
+ return ctx_data_pointer_get(C, "asset_library_ref");
}
AssetHandle CTX_wm_asset_handle(const bContext *C, bool *r_is_valid)
diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c
index f1369254347..db0ea71e233 100644
--- a/source/blender/blenkernel/intern/curve.c
+++ b/source/blender/blenkernel/intern/curve.c
@@ -638,7 +638,7 @@ void BKE_nurb_free(Nurb *nu)
MEM_freeN(nu->knotsv);
}
nu->knotsv = NULL;
- /* if (nu->trim.first) freeNurblist(&(nu->trim)); */
+ // if (nu->trim.first) freeNurblist(&(nu->trim));
MEM_freeN(nu);
}
@@ -5010,10 +5010,7 @@ bool BKE_nurb_type_convert(Nurb *nu,
MEM_freeN(nu->knotsu); /* python created nurbs have a knotsu of zero */
}
nu->knotsu = NULL;
- if (nu->knotsv) {
- MEM_freeN(nu->knotsv);
- }
- nu->knotsv = NULL;
+ MEM_SAFE_FREE(nu->knotsv);
}
else if (type == CU_BEZIER) { /* to Bezier */
nr = nu->pntsu / 3;
diff --git a/source/blender/blenkernel/intern/customdata.c b/source/blender/blenkernel/intern/customdata.c
index 7aa9d1958eb..1a3200a9b6c 100644
--- a/source/blender/blenkernel/intern/customdata.c
+++ b/source/blender/blenkernel/intern/customdata.c
@@ -724,10 +724,7 @@ static void layerFree_grid_paint_mask(void *data, int count, int UNUSED(size))
GridPaintMask *gpm = data;
for (int i = 0; i < count; i++) {
- if (gpm[i].data) {
- MEM_freeN(gpm[i].data);
- }
- gpm[i].data = NULL;
+ MEM_SAFE_FREE(gpm[i].data);
gpm[i].level = 0;
}
}
@@ -4249,7 +4246,7 @@ void CustomData_blend_write_prepare(CustomData *data,
CustomDataLayer *layer = &data->layers[i];
if (layer->flag & CD_FLAG_NOCOPY) { /* Layers with this flag set are not written to file. */
data->totlayer--;
- /* CLOG_WARN(&LOG, "skipping layer %p (%s)", layer, layer->name); */
+ // CLOG_WARN(&LOG, "skipping layer %p (%s)", layer, layer->name);
}
else {
if (UNLIKELY((size_t)j >= write_layers_size)) {
diff --git a/source/blender/blenkernel/intern/data_transfer.c b/source/blender/blenkernel/intern/data_transfer.c
index 605061570b8..b83621e8b79 100644
--- a/source/blender/blenkernel/intern/data_transfer.c
+++ b/source/blender/blenkernel/intern/data_transfer.c
@@ -301,14 +301,12 @@ static void data_transfer_dtdata_type_preprocess(Mesh *me_src,
}
if (dirty_nors_dst || do_poly_nors_dst) {
BKE_mesh_calc_normals_poly(verts_dst,
- NULL,
num_verts_dst,
loops_dst,
- polys_dst,
num_loops_dst,
+ polys_dst,
num_polys_dst,
- poly_nors_dst,
- true);
+ poly_nors_dst);
}
/* Cache loop nors into a temp CDLayer. */
loop_nors_dst = CustomData_get_layer(ldata_dst, CD_NORMAL);
diff --git a/source/blender/blenkernel/intern/deform.c b/source/blender/blenkernel/intern/deform.c
index f7ef84728b6..13222747a52 100644
--- a/source/blender/blenkernel/intern/deform.c
+++ b/source/blender/blenkernel/intern/deform.c
@@ -894,10 +894,7 @@ void BKE_defvert_remove_group(MDeformVert *dvert, MDeformWeight *dw)
void BKE_defvert_clear(MDeformVert *dvert)
{
- if (dvert->dw) {
- MEM_freeN(dvert->dw);
- dvert->dw = NULL;
- }
+ MEM_SAFE_FREE(dvert->dw);
dvert->totweight = 0;
}
diff --git a/source/blender/blenkernel/intern/displist.cc b/source/blender/blenkernel/intern/displist.cc
index 99dc1db9d38..c97e07ad487 100644
--- a/source/blender/blenkernel/intern/displist.cc
+++ b/source/blender/blenkernel/intern/displist.cc
@@ -1003,7 +1003,7 @@ static void curve_calc_modifiers_post(Depsgraph *depsgraph,
modified = temp_mesh;
BKE_mesh_vert_coords_apply(modified, vertCos);
- BKE_mesh_calc_normals_mapping_simple(modified);
+ BKE_mesh_calc_normals(modified);
MEM_freeN(vertCos);
}
diff --git a/source/blender/blenkernel/intern/dynamicpaint.c b/source/blender/blenkernel/intern/dynamicpaint.c
index 52996e3bcc7..8f94c407cae 100644
--- a/source/blender/blenkernel/intern/dynamicpaint.c
+++ b/source/blender/blenkernel/intern/dynamicpaint.c
@@ -844,10 +844,7 @@ static void surfaceGenerateGrid(struct DynamicPaintSurface *surface)
if (temp_s_num) {
MEM_freeN(temp_s_num);
}
- if (temp_t_index) {
- MEM_freeN(temp_t_index);
- }
- grid->temp_t_index = NULL;
+ MEM_SAFE_FREE(temp_t_index);
if (error || !grid->s_num) {
setError(surface->canvas, N_("Not enough free memory"));
@@ -988,10 +985,7 @@ void dynamicPaint_freeSurface(const DynamicPaintModifierData *pmd, DynamicPaintS
}
surface->pointcache = NULL;
- if (surface->effector_weights) {
- MEM_freeN(surface->effector_weights);
- }
- surface->effector_weights = NULL;
+ MEM_SAFE_FREE(surface->effector_weights);
BLI_remlink(&(surface->canvas->surfaces), surface);
dynamicPaint_freeSurfaceData(surface);
diff --git a/source/blender/blenkernel/intern/fluid.c b/source/blender/blenkernel/intern/fluid.c
index d33697d551e..799d6553682 100644
--- a/source/blender/blenkernel/intern/fluid.c
+++ b/source/blender/blenkernel/intern/fluid.c
@@ -4766,20 +4766,14 @@ static void BKE_fluid_modifier_freeDomain(FluidModifierData *fmd)
BLI_rw_mutex_free(fmd->domain->fluid_mutex);
}
- if (fmd->domain->effector_weights) {
- MEM_freeN(fmd->domain->effector_weights);
- }
- fmd->domain->effector_weights = NULL;
+ MEM_SAFE_FREE(fmd->domain->effector_weights);
if (!(fmd->modifier.flag & eModifierFlag_SharedCaches)) {
BKE_ptcache_free_list(&(fmd->domain->ptcaches[0]));
fmd->domain->point_cache[0] = NULL;
}
- if (fmd->domain->mesh_velocities) {
- MEM_freeN(fmd->domain->mesh_velocities);
- }
- fmd->domain->mesh_velocities = NULL;
+ MEM_SAFE_FREE(fmd->domain->mesh_velocities);
if (fmd->domain->coba) {
MEM_freeN(fmd->domain->coba);
@@ -4798,10 +4792,7 @@ static void BKE_fluid_modifier_freeFlow(FluidModifierData *fmd)
}
fmd->flow->mesh = NULL;
- if (fmd->flow->verts_old) {
- MEM_freeN(fmd->flow->verts_old);
- }
- fmd->flow->verts_old = NULL;
+ MEM_SAFE_FREE(fmd->flow->verts_old);
fmd->flow->numverts = 0;
fmd->flow->flags &= ~FLUID_FLOW_NEEDS_UPDATE;
@@ -4818,10 +4809,7 @@ static void BKE_fluid_modifier_freeEffector(FluidModifierData *fmd)
}
fmd->effector->mesh = NULL;
- if (fmd->effector->verts_old) {
- MEM_freeN(fmd->effector->verts_old);
- }
- fmd->effector->verts_old = NULL;
+ MEM_SAFE_FREE(fmd->effector->verts_old);
fmd->effector->numverts = 0;
fmd->effector->flags &= ~FLUID_EFFECTOR_NEEDS_UPDATE;
@@ -4857,18 +4845,12 @@ static void BKE_fluid_modifier_reset_ex(struct FluidModifierData *fmd, bool need
fmd->domain->active_fields = 0;
}
else if (fmd->flow) {
- if (fmd->flow->verts_old) {
- MEM_freeN(fmd->flow->verts_old);
- }
- fmd->flow->verts_old = NULL;
+ MEM_SAFE_FREE(fmd->flow->verts_old);
fmd->flow->numverts = 0;
fmd->flow->flags &= ~FLUID_FLOW_NEEDS_UPDATE;
}
else if (fmd->effector) {
- if (fmd->effector->verts_old) {
- MEM_freeN(fmd->effector->verts_old);
- }
- fmd->effector->verts_old = NULL;
+ MEM_SAFE_FREE(fmd->effector->verts_old);
fmd->effector->numverts = 0;
fmd->effector->flags &= ~FLUID_EFFECTOR_NEEDS_UPDATE;
}
diff --git a/source/blender/blenkernel/intern/font.c b/source/blender/blenkernel/intern/font.c
index 37fc14911fe..de838f1b3cd 100644
--- a/source/blender/blenkernel/intern/font.c
+++ b/source/blender/blenkernel/intern/font.c
@@ -715,6 +715,11 @@ typedef struct VFontToCurveIter {
float max;
} bisect;
bool ok;
+ /**
+ * Disables checking if word wrapping is needed to fit the text-box width.
+ * Currently only used when scale-to-fit is enabled.
+ */
+ bool word_wrap;
int status;
} VFontToCurveIter;
@@ -777,6 +782,7 @@ static bool vfont_to_curve(Object *ob,
char32_t ascii;
bool ok = false;
const float font_size = cu->fsize * iter_data->scale_to_fit;
+ const bool word_wrap = iter_data->word_wrap;
const float xof_scale = cu->xof / font_size;
const float yof_scale = cu->yof / font_size;
int last_line = -1;
@@ -947,43 +953,59 @@ static bool vfont_to_curve(Object *ob,
twidth = char_width(cu, che, info);
- /* Calculate positions */
- if ((tb_scale.w != 0.0f) && (ct->dobreak == 0) &&
- (((xof - tb_scale.x) + twidth) > xof_scale + tb_scale.w)) {
- // CLOG_WARN(&LOG, "linewidth exceeded: %c%c%c...", mem[i], mem[i+1], mem[i+2]);
- for (j = i; j && (mem[j] != '\n') && (chartransdata[j].dobreak == 0); j--) {
- bool dobreak = false;
- if (ELEM(mem[j], ' ', '-')) {
- ct -= (i - (j - 1));
- cnr -= (i - (j - 1));
- if (mem[j] == ' ') {
- wsnr--;
+ /* Calculate positions. */
+
+ if ((tb_scale.w != 0.0f) && (ct->dobreak == 0)) { /* May need wrapping. */
+ const float x_available = xof_scale + tb_scale.w;
+ const float x_used = (xof - tb_scale.x) + twidth;
+
+ if (word_wrap == false) {
+ /* When scale to fit is used, don't do any wrapping.
+ *
+ * Floating precision error can cause the text to be slightly larger.
+ * Assert this is a small value as large values indicate incorrect
+ * calculations with scale-to-fit which shouldn't be ignored. See T89241. */
+ if (x_used > x_available) {
+ BLI_assert_msg(compare_ff_relative(x_used, x_available, FLT_EPSILON, 64),
+ "VFontToCurveIter.scale_to_fit not set correctly!");
+ }
+ }
+ else if (x_used > x_available) {
+ // CLOG_WARN(&LOG, "linewidth exceeded: %c%c%c...", mem[i], mem[i+1], mem[i+2]);
+ for (j = i; j && (mem[j] != '\n') && (chartransdata[j].dobreak == 0); j--) {
+ bool dobreak = false;
+ if (ELEM(mem[j], ' ', '-')) {
+ ct -= (i - (j - 1));
+ cnr -= (i - (j - 1));
+ if (mem[j] == ' ') {
+ wsnr--;
+ }
+ if (mem[j] == '-') {
+ wsnr++;
+ }
+ i = j - 1;
+ xof = ct->xof;
+ ct[1].dobreak = 1;
+ custrinfo[i + 1].flag |= CU_CHINFO_WRAP;
+ dobreak = true;
}
- if (mem[j] == '-') {
- wsnr++;
+ else if (chartransdata[j].dobreak) {
+ // CLOG_WARN(&LOG, "word too long: %c%c%c...", mem[j], mem[j+1], mem[j+2]);
+ ct->dobreak = 1;
+ custrinfo[i + 1].flag |= CU_CHINFO_WRAP;
+ ct -= 1;
+ cnr -= 1;
+ i--;
+ xof = ct->xof;
+ dobreak = true;
}
- i = j - 1;
- xof = ct->xof;
- ct[1].dobreak = 1;
- custrinfo[i + 1].flag |= CU_CHINFO_WRAP;
- dobreak = true;
- }
- else if (chartransdata[j].dobreak) {
- // CLOG_WARN(&LOG, "word too long: %c%c%c...", mem[j], mem[j+1], mem[j+2]);
- ct->dobreak = 1;
- custrinfo[i + 1].flag |= CU_CHINFO_WRAP;
- ct -= 1;
- cnr -= 1;
- i--;
- xof = ct->xof;
- dobreak = true;
- }
- if (dobreak) {
- if (tb_scale.h == 0.0f) {
- /* NOTE: If underlined text is truncated away, the extra space is also truncated. */
- custrinfo[i + 1].flag |= CU_CHINFO_OVERFLOW;
+ if (dobreak) {
+ if (tb_scale.h == 0.0f) {
+ /* NOTE: If underlined text is truncated away, the extra space is also truncated. */
+ custrinfo[i + 1].flag |= CU_CHINFO_OVERFLOW;
+ }
+ goto makebreak;
}
- goto makebreak;
}
}
}
@@ -1545,6 +1567,7 @@ static bool vfont_to_curve(Object *ob,
const float total_text_height = lnr * linedist;
iter_data->scale_to_fit = tb_scale.h / total_text_height;
iter_data->status = VFONT_TO_CURVE_SCALE_ONCE;
+ iter_data->word_wrap = false;
}
}
else if (tb_scale.h == 0.0f) {
@@ -1552,10 +1575,10 @@ static bool vfont_to_curve(Object *ob,
if (longest_line_length > tb_scale.w) {
/* We make sure longest line before it broke can fit here. */
float scale_to_fit = tb_scale.w / longest_line_length;
- scale_to_fit -= FLT_EPSILON;
iter_data->scale_to_fit = scale_to_fit;
iter_data->status = VFONT_TO_CURVE_SCALE_ONCE;
+ iter_data->word_wrap = false;
}
}
}
@@ -1616,6 +1639,7 @@ static bool vfont_to_curve(Object *ob,
else {
iter_data->scale_to_fit = iter_data->bisect.min;
iter_data->status = VFONT_TO_CURVE_SCALE_ONCE;
+ iter_data->word_wrap = false;
}
}
}
@@ -1685,6 +1709,7 @@ bool BKE_vfont_to_curve_ex(Object *ob,
VFontToCurveIter data = {
.iteraction = cu->totbox * FONT_TO_CURVE_SCALE_ITERATIONS,
.scale_to_fit = 1.0f,
+ .word_wrap = true,
.ok = true,
.status = VFONT_TO_CURVE_INIT,
};
diff --git a/source/blender/blenkernel/intern/geometry_set_instances.cc b/source/blender/blenkernel/intern/geometry_set_instances.cc
index 90a97264c8f..32a65ab47bf 100644
--- a/source/blender/blenkernel/intern/geometry_set_instances.cc
+++ b/source/blender/blenkernel/intern/geometry_set_instances.cc
@@ -491,6 +491,10 @@ static Mesh *join_mesh_topology_and_builtin_attributes(Span<GeometryInstanceGrou
}
}
+ /* A possible optimization is to only tag the normals dirty when there are transforms that change
+ * normals. */
+ BKE_mesh_normals_tag_dirty(new_mesh);
+
return new_mesh;
}
diff --git a/source/blender/blenkernel/intern/gpencil.c b/source/blender/blenkernel/intern/gpencil.c
index 38397f8f307..f566e18fb2f 100644
--- a/source/blender/blenkernel/intern/gpencil.c
+++ b/source/blender/blenkernel/intern/gpencil.c
@@ -521,6 +521,7 @@ void BKE_gpencil_eval_delete(bGPdata *gpd_eval)
{
BKE_gpencil_free(gpd_eval, true);
BKE_libblock_free_data(&gpd_eval->id, false);
+ BLI_assert(!gpd_eval->id.py_instance); /* Or call #BKE_libblock_free_data_py. */
MEM_freeN(gpd_eval);
}
diff --git a/source/blender/blenkernel/intern/icons.cc b/source/blender/blenkernel/intern/icons.cc
index 12a0a1e3ae7..5a4b2448a73 100644
--- a/source/blender/blenkernel/intern/icons.cc
+++ b/source/blender/blenkernel/intern/icons.cc
@@ -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
diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c
index f4ba1ff8b92..ba54858ba84 100644
--- a/source/blender/blenkernel/intern/image.c
+++ b/source/blender/blenkernel/intern/image.c
@@ -1020,7 +1020,7 @@ Image *BKE_image_add_generated(Main *bmain,
int view_id;
const char *names[2] = {STEREO_LEFT_NAME, STEREO_RIGHT_NAME};
- /* STRNCPY(ima->filepath, name); */ /* don't do this, this writes in ain invalid filepath! */
+ // STRNCPY(ima->filepath, name); /* don't do this, this writes in ain invalid filepath! */
ima->gen_x = width;
ima->gen_y = height;
ima->gen_type = gen_type;
diff --git a/source/blender/blenkernel/intern/key.c b/source/blender/blenkernel/intern/key.c
index 0f8c9bad798..724216bee6c 100644
--- a/source/blender/blenkernel/intern/key.c
+++ b/source/blender/blenkernel/intern/key.c
@@ -2281,15 +2281,8 @@ void BKE_keyblock_mesh_calc_normals(struct KeyBlock *kb,
r_polynors = MEM_mallocN(sizeof(float[3]) * me.totpoly, __func__);
free_polynors = true;
}
- BKE_mesh_calc_normals_poly(me.mvert,
- r_vertnors,
- me.totvert,
- me.mloop,
- me.mpoly,
- me.totloop,
- me.totpoly,
- r_polynors,
- false);
+ BKE_mesh_calc_normals_poly_and_vertex(
+ me.mvert, me.totvert, me.mloop, me.totloop, me.mpoly, me.totpoly, r_polynors, r_vertnors);
if (r_loopnors) {
short(*clnors)[2] = CustomData_get_layer(&mesh->ldata, CD_CUSTOMLOOPNORMAL); /* May be NULL. */
diff --git a/source/blender/blenkernel/intern/layer.c b/source/blender/blenkernel/intern/layer.c
index e7d83c668c8..b489675cd74 100644
--- a/source/blender/blenkernel/intern/layer.c
+++ b/source/blender/blenkernel/intern/layer.c
@@ -1174,6 +1174,52 @@ static void layer_collection_sync(ViewLayer *view_layer,
parent_local_collections_bits);
}
+#ifndef NDEBUG
+static bool view_layer_objects_base_cache_validate(ViewLayer *view_layer, LayerCollection *layer)
+{
+ bool is_valid = true;
+
+ if (layer == NULL) {
+ layer = view_layer->layer_collections.first;
+ }
+
+ /* Only check for a collection's objects if its layer is not excluded. */
+ if ((layer->flag & LAYER_COLLECTION_EXCLUDE) == 0) {
+ LISTBASE_FOREACH (CollectionObject *, cob, &layer->collection->gobject) {
+ if (cob->ob == NULL) {
+ continue;
+ }
+ if (BLI_ghash_lookup(view_layer->object_bases_hash, cob->ob) == NULL) {
+ CLOG_FATAL(
+ &LOG,
+ "Object '%s' from collection '%s' has no entry in view layer's object bases cache",
+ cob->ob->id.name + 2,
+ layer->collection->id.name + 2);
+ is_valid = false;
+ break;
+ }
+ }
+ }
+
+ if (is_valid) {
+ LISTBASE_FOREACH (LayerCollection *, layer_child, &layer->layer_collections) {
+ if (!view_layer_objects_base_cache_validate(view_layer, layer_child)) {
+ is_valid = false;
+ break;
+ }
+ }
+ }
+
+ return is_valid;
+}
+#else
+static bool view_layer_objects_base_cache_validate(ViewLayer *UNUSED(view_layer),
+ LayerCollection *UNUSED(layer))
+{
+ return true;
+}
+#endif
+
/**
* Update view layer collection tree from collections used in the scene.
* This is used when collections are removed or added, both while editing
@@ -1240,6 +1286,12 @@ void BKE_layer_collection_sync(const Scene *scene, ViewLayer *view_layer)
}
if (base->object) {
+ /* Those asserts are commented, since they are too expensive to perform even in debug, as
+ * this layer resync function currently gets called way too often. */
+#if 0
+ BLI_assert(BLI_findindex(&new_object_bases, base) == -1);
+ BLI_assert(BLI_findptr(&new_object_bases, base->object, offsetof(Base, object)) == NULL);
+#endif
BLI_ghash_remove(view_layer->object_bases_hash, base->object, NULL, NULL);
}
}
@@ -1247,6 +1299,8 @@ void BKE_layer_collection_sync(const Scene *scene, ViewLayer *view_layer)
BLI_freelistN(&view_layer->object_bases);
view_layer->object_bases = new_object_bases;
+ view_layer_objects_base_cache_validate(view_layer, NULL);
+
LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) {
BKE_base_eval_flags(base);
}
diff --git a/source/blender/blenkernel/intern/lib_id.c b/source/blender/blenkernel/intern/lib_id.c
index 5e1027c62af..0f880d16358 100644
--- a/source/blender/blenkernel/intern/lib_id.c
+++ b/source/blender/blenkernel/intern/lib_id.c
@@ -1321,14 +1321,6 @@ void *BKE_libblock_copy(Main *bmain, const ID *id)
return idn;
}
-/* XXX TODO: get rid of this useless wrapper at some point... */
-void *BKE_libblock_copy_for_localize(const ID *id)
-{
- ID *idn;
- BKE_libblock_copy_ex(NULL, id, &idn, LIB_ID_COPY_LOCALIZE | LIB_ID_COPY_NO_ANIMDATA);
- return idn;
-}
-
/* ***************** ID ************************ */
ID *BKE_libblock_find_name(struct Main *bmain, const short type, const char *name)
{
diff --git a/source/blender/blenkernel/intern/lib_id_delete.c b/source/blender/blenkernel/intern/lib_id_delete.c
index a9407860c06..43afac5a376 100644
--- a/source/blender/blenkernel/intern/lib_id_delete.c
+++ b/source/blender/blenkernel/intern/lib_id_delete.c
@@ -142,14 +142,7 @@ void BKE_id_free_ex(Main *bmain, void *idv, int flag, const bool use_flag_from_i
DEG_id_type_tag(bmain, type);
}
-#ifdef WITH_PYTHON
-# ifdef WITH_PYTHON_SAFETY
- BPY_id_release(id);
-# endif
- if (id->py_instance) {
- BPY_DECREF_RNA_INVALIDATE(id->py_instance);
- }
-#endif
+ BKE_libblock_free_data_py(id);
Key *key = ((flag & LIB_ID_FREE_NO_MAIN) == 0) ? BKE_key_from_id(id) : NULL;
@@ -406,3 +399,29 @@ size_t BKE_id_multi_tagged_delete(Main *bmain)
{
return id_delete(bmain, true);
}
+
+/* -------------------------------------------------------------------- */
+/** \name Python Data Handling
+ * \{ */
+
+/**
+ * In most cases #BKE_id_free_ex handles this, when lower level functions are called directly
+ * this function will need to be called too, if Python has access to the data.
+ *
+ * ID data-blocks such as #Material.nodetree are not stored in #Main.
+ */
+void BKE_libblock_free_data_py(ID *id)
+{
+#ifdef WITH_PYTHON
+# ifdef WITH_PYTHON_SAFETY
+ BPY_id_release(id);
+# endif
+ if (id->py_instance) {
+ BPY_DECREF_RNA_INVALIDATE(id->py_instance);
+ }
+#else
+ UNUSED_VARS(id);
+#endif
+}
+
+/** \} */
diff --git a/source/blender/blenkernel/intern/lib_override.c b/source/blender/blenkernel/intern/lib_override.c
index 67ed7d1b394..8083585b594 100644
--- a/source/blender/blenkernel/intern/lib_override.c
+++ b/source/blender/blenkernel/intern/lib_override.c
@@ -1020,7 +1020,7 @@ bool BKE_lib_override_library_resync(Main *bmain,
if (id_root_reference->tag & LIB_TAG_MISSING) {
BKE_reportf(reports != NULL ? reports->reports : NULL,
RPT_ERROR,
- "impossible to resync data-block %s and its dependencies, as its linked reference "
+ "Impossible to resync data-block %s and its dependencies, as its linked reference "
"is missing",
id_root->name + 2);
return false;
@@ -1631,7 +1631,7 @@ static void lib_override_library_main_resync_on_library_indirect_level(
CLOG_INFO(&LOG, 2, "\tSuccess: %d", success);
if (success) {
reports->count.resynced_lib_overrides++;
- if (library_indirect_level > 0 &&
+ if (library_indirect_level > 0 && reports->do_resynced_lib_overrides_libraries_list &&
BLI_linklist_index(reports->resynced_lib_overrides_libraries, library) < 0) {
BLI_linklist_prepend(&reports->resynced_lib_overrides_libraries, library);
reports->resynced_lib_overrides_libraries_count++;
diff --git a/source/blender/blenkernel/intern/mask_rasterize.c b/source/blender/blenkernel/intern/mask_rasterize.c
index 8acc929a089..e04e5fceec6 100644
--- a/source/blender/blenkernel/intern/mask_rasterize.c
+++ b/source/blender/blenkernel/intern/mask_rasterize.c
@@ -292,10 +292,10 @@ static void maskrasterize_spline_differentiate_point_outset(float (*diff_feather
co_curr = diff_points[k_curr];
co_next = diff_points[k_next];
- /* sub_v2_v2v2(d_prev, co_prev, co_curr); */ /* precalc */
+ // sub_v2_v2v2(d_prev, co_prev, co_curr); /* precalc */
sub_v2_v2v2(d_next, co_curr, co_next);
- /* normalize_v2(d_prev); */ /* precalc */
+ // normalize_v2(d_prev); /* precalc */
normalize_v2(d_next);
if ((do_test == false) ||
diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c
index 4f0b2a718ed..ca57038f1c4 100644
--- a/source/blender/blenkernel/intern/material.c
+++ b/source/blender/blenkernel/intern/material.c
@@ -1802,6 +1802,7 @@ void BKE_material_copybuf_free(void)
{
if (matcopybuf.nodetree) {
ntreeFreeLocalTree(matcopybuf.nodetree);
+ BLI_assert(!matcopybuf.nodetree->id.py_instance); /* Or call #BKE_libblock_free_data_py. */
MEM_freeN(matcopybuf.nodetree);
matcopybuf.nodetree = NULL;
}
diff --git a/source/blender/blenkernel/intern/mball.c b/source/blender/blenkernel/intern/mball.c
index 6a2b56306d6..d6b189d484b 100644
--- a/source/blender/blenkernel/intern/mball.c
+++ b/source/blender/blenkernel/intern/mball.c
@@ -289,7 +289,7 @@ void BKE_mball_texspace_calc(Object *ob)
bb = ob->runtime.bb;
/* Weird one, this. */
- /* INIT_MINMAX(min, max); */
+ // INIT_MINMAX(min, max);
(min)[0] = (min)[1] = (min)[2] = 1.0e30f;
(max)[0] = (max)[1] = (max)[2] = -1.0e30f;
diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c
index b00670aad4c..b32d58de1e2 100644
--- a/source/blender/blenkernel/intern/mesh.c
+++ b/source/blender/blenkernel/intern/mesh.c
@@ -262,7 +262,7 @@ static void mesh_blend_write(BlendWriter *writer, ID *id, const void *id_address
CD_LAYERS_FREE(vlayers);
CD_LAYERS_FREE(elayers);
- /* CD_LAYER_FREE(flayers); */ /* Never allocated. */
+ // CD_LAYER_FREE(flayers); /* Never allocated. */
CD_LAYERS_FREE(llayers);
CD_LAYERS_FREE(players);
@@ -430,57 +430,159 @@ static int customdata_compare(
{
const float thresh_sq = thresh * thresh;
CustomDataLayer *l1, *l2;
- int i1 = 0, i2 = 0, tot, j;
+ int layer_count1 = 0, layer_count2 = 0, j;
+ const uint64_t cd_mask_non_generic = CD_MASK_MVERT | CD_MASK_MEDGE | CD_MASK_MPOLY |
+ CD_MASK_MLOOPUV | CD_MASK_MLOOPCOL | CD_MASK_MDEFORMVERT;
+ const uint64_t cd_mask_all_attr = CD_MASK_PROP_ALL | cd_mask_non_generic;
for (int i = 0; i < c1->totlayer; i++) {
- if (ELEM(c1->layers[i].type,
- CD_MVERT,
- CD_MEDGE,
- CD_MPOLY,
- CD_MLOOPUV,
- CD_MLOOPCOL,
- CD_MDEFORMVERT)) {
- i1++;
+ if (CD_TYPE_AS_MASK(c1->layers[i].type) & cd_mask_all_attr) {
+ layer_count1++;
}
}
for (int i = 0; i < c2->totlayer; i++) {
- if (ELEM(c2->layers[i].type,
- CD_MVERT,
- CD_MEDGE,
- CD_MPOLY,
- CD_MLOOPUV,
- CD_MLOOPCOL,
- CD_MDEFORMVERT)) {
- i2++;
+ if (CD_TYPE_AS_MASK(c2->layers[i].type) & cd_mask_all_attr) {
+ layer_count2++;
}
}
- if (i1 != i2) {
+ if (layer_count1 != layer_count2) {
return MESHCMP_CDLAYERS_MISMATCH;
}
l1 = c1->layers;
l2 = c2->layers;
- for (i1 = 0; i1 < c1->totlayer; i1++) {
+ for (int i1 = 0; i1 < c1->totlayer; i1++) {
l1 = c1->layers + i1;
- if ((CD_TYPE_AS_MASK(l1->type) & CD_MASK_PROP_ALL) == 0) {
- /* Skip non generic attribute layers. */
- continue;
- }
-
- bool found_corresponding_layer = false;
- for (i2 = 0; i2 < c2->totlayer; i2++) {
+ for (int i2 = 0; i2 < c2->totlayer; i2++) {
l2 = c2->layers + i2;
if (l1->type != l2->type || !STREQ(l1->name, l2->name)) {
continue;
}
- found_corresponding_layer = true;
/* At this point `l1` and `l2` have the same name and type, so they should be compared. */
switch (l1->type) {
+ case CD_MVERT: {
+ MVert *v1 = l1->data;
+ MVert *v2 = l2->data;
+ int vtot = m1->totvert;
+
+ for (j = 0; j < vtot; j++, v1++, v2++) {
+ if (len_squared_v3v3(v1->co, v2->co) > thresh_sq) {
+ return MESHCMP_VERTCOMISMATCH;
+ }
+ /* I don't care about normals, let's just do coordinates. */
+ }
+ break;
+ }
+
+ /* We're order-agnostic for edges here. */
+ case CD_MEDGE: {
+ MEdge *e1 = l1->data;
+ MEdge *e2 = l2->data;
+ int etot = m1->totedge;
+ EdgeHash *eh = BLI_edgehash_new_ex(__func__, etot);
+
+ for (j = 0; j < etot; j++, e1++) {
+ BLI_edgehash_insert(eh, e1->v1, e1->v2, e1);
+ }
+
+ for (j = 0; j < etot; j++, e2++) {
+ if (!BLI_edgehash_lookup(eh, e2->v1, e2->v2)) {
+ return MESHCMP_EDGEUNKNOWN;
+ }
+ }
+ BLI_edgehash_free(eh, NULL);
+ break;
+ }
+ case CD_MPOLY: {
+ MPoly *p1 = l1->data;
+ MPoly *p2 = l2->data;
+ int ptot = m1->totpoly;
+
+ for (j = 0; j < ptot; j++, p1++, p2++) {
+ MLoop *lp1, *lp2;
+ int k;
+
+ if (p1->totloop != p2->totloop) {
+ return MESHCMP_POLYMISMATCH;
+ }
+
+ lp1 = m1->mloop + p1->loopstart;
+ lp2 = m2->mloop + p2->loopstart;
+
+ for (k = 0; k < p1->totloop; k++, lp1++, lp2++) {
+ if (lp1->v != lp2->v) {
+ return MESHCMP_POLYVERTMISMATCH;
+ }
+ }
+ }
+ break;
+ }
+ case CD_MLOOP: {
+ MLoop *lp1 = l1->data;
+ MLoop *lp2 = l2->data;
+ int ltot = m1->totloop;
+
+ for (j = 0; j < ltot; j++, lp1++, lp2++) {
+ if (lp1->v != lp2->v) {
+ return MESHCMP_LOOPMISMATCH;
+ }
+ }
+ break;
+ }
+ case CD_MLOOPUV: {
+ MLoopUV *lp1 = l1->data;
+ MLoopUV *lp2 = l2->data;
+ int ltot = m1->totloop;
+
+ for (j = 0; j < ltot; j++, lp1++, lp2++) {
+ if (len_squared_v2v2(lp1->uv, lp2->uv) > thresh_sq) {
+ return MESHCMP_LOOPUVMISMATCH;
+ }
+ }
+ break;
+ }
+ case CD_MLOOPCOL: {
+ MLoopCol *lp1 = l1->data;
+ MLoopCol *lp2 = l2->data;
+ int ltot = m1->totloop;
+
+ for (j = 0; j < ltot; j++, lp1++, lp2++) {
+ if (abs(lp1->r - lp2->r) > thresh || abs(lp1->g - lp2->g) > thresh ||
+ abs(lp1->b - lp2->b) > thresh || abs(lp1->a - lp2->a) > thresh) {
+ return MESHCMP_LOOPCOLMISMATCH;
+ }
+ }
+ break;
+ }
+ case CD_MDEFORMVERT: {
+ MDeformVert *dv1 = l1->data;
+ MDeformVert *dv2 = l2->data;
+ int dvtot = m1->totvert;
+
+ for (j = 0; j < dvtot; j++, dv1++, dv2++) {
+ int k;
+ MDeformWeight *dw1 = dv1->dw, *dw2 = dv2->dw;
+
+ if (dv1->totweight != dv2->totweight) {
+ return MESHCMP_DVERT_TOTGROUPMISMATCH;
+ }
+
+ for (k = 0; k < dv1->totweight; k++, dw1++, dw2++) {
+ if (dw1->def_nr != dw2->def_nr) {
+ return MESHCMP_DVERT_GROUPMISMATCH;
+ }
+ if (fabsf(dw1->weight - dw2->weight) > thresh) {
+ return MESHCMP_DVERT_WEIGHTMISMATCH;
+ }
+ }
+ }
+ break;
+ }
case CD_PROP_FLOAT: {
const float *l1_data = l1->data;
const float *l2_data = l2->data;
@@ -514,157 +616,30 @@ static int customdata_compare(
}
break;
}
- default: {
- int element_size = CustomData_sizeof(l1->type);
+ case CD_PROP_INT32: {
+ const int *l1_data = l1->data;
+ const int *l2_data = l2->data;
+
for (int i = 0; i < total_length; i++) {
- int offset = element_size * i;
- if (!CustomData_data_equals(l1->type,
- POINTER_OFFSET(l1->data, offset),
- POINTER_OFFSET(l2->data, offset))) {
+ if (l1_data[i] != l2_data[i]) {
return MESHCMP_ATTRIBUTE_VALUE_MISMATCH;
}
}
break;
}
- }
- }
-
- if (!found_corresponding_layer) {
- return MESHCMP_CDLAYERS_MISMATCH;
- }
- }
+ case CD_PROP_BOOL: {
+ const bool *l1_data = l1->data;
+ const bool *l2_data = l2->data;
- l1 = c1->layers;
- l2 = c2->layers;
- tot = i1;
- i1 = 0;
- i2 = 0;
- for (int i = 0; i < tot; i++) {
- while (
- i1 < c1->totlayer &&
- !ELEM(l1->type, CD_MVERT, CD_MEDGE, CD_MPOLY, CD_MLOOPUV, CD_MLOOPCOL, CD_MDEFORMVERT)) {
- i1++;
- l1++;
- }
-
- while (
- i2 < c2->totlayer &&
- !ELEM(l2->type, CD_MVERT, CD_MEDGE, CD_MPOLY, CD_MLOOPUV, CD_MLOOPCOL, CD_MDEFORMVERT)) {
- i2++;
- l2++;
- }
-
- if (l1->type == CD_MVERT) {
- MVert *v1 = l1->data;
- MVert *v2 = l2->data;
- int vtot = m1->totvert;
-
- for (j = 0; j < vtot; j++, v1++, v2++) {
- if (len_squared_v3v3(v1->co, v2->co) > thresh_sq) {
- return MESHCMP_VERTCOMISMATCH;
- }
- /* I don't care about normals, let's just do coordinates. */
- }
- }
-
- /* We're order-agnostic for edges here. */
- if (l1->type == CD_MEDGE) {
- MEdge *e1 = l1->data;
- MEdge *e2 = l2->data;
- int etot = m1->totedge;
- EdgeHash *eh = BLI_edgehash_new_ex(__func__, etot);
-
- for (j = 0; j < etot; j++, e1++) {
- BLI_edgehash_insert(eh, e1->v1, e1->v2, e1);
- }
-
- for (j = 0; j < etot; j++, e2++) {
- if (!BLI_edgehash_lookup(eh, e2->v1, e2->v2)) {
- return MESHCMP_EDGEUNKNOWN;
- }
- }
- BLI_edgehash_free(eh, NULL);
- }
-
- if (l1->type == CD_MPOLY) {
- MPoly *p1 = l1->data;
- MPoly *p2 = l2->data;
- int ptot = m1->totpoly;
-
- for (j = 0; j < ptot; j++, p1++, p2++) {
- MLoop *lp1, *lp2;
- int k;
-
- if (p1->totloop != p2->totloop) {
- return MESHCMP_POLYMISMATCH;
- }
-
- lp1 = m1->mloop + p1->loopstart;
- lp2 = m2->mloop + p2->loopstart;
-
- for (k = 0; k < p1->totloop; k++, lp1++, lp2++) {
- if (lp1->v != lp2->v) {
- return MESHCMP_POLYVERTMISMATCH;
+ for (int i = 0; i < total_length; i++) {
+ if (l1_data[i] != l2_data[i]) {
+ return MESHCMP_ATTRIBUTE_VALUE_MISMATCH;
+ }
}
+ break;
}
- }
- }
- if (l1->type == CD_MLOOP) {
- MLoop *lp1 = l1->data;
- MLoop *lp2 = l2->data;
- int ltot = m1->totloop;
-
- for (j = 0; j < ltot; j++, lp1++, lp2++) {
- if (lp1->v != lp2->v) {
- return MESHCMP_LOOPMISMATCH;
- }
- }
- }
- if (l1->type == CD_MLOOPUV) {
- MLoopUV *lp1 = l1->data;
- MLoopUV *lp2 = l2->data;
- int ltot = m1->totloop;
-
- for (j = 0; j < ltot; j++, lp1++, lp2++) {
- if (len_squared_v2v2(lp1->uv, lp2->uv) > thresh_sq) {
- return MESHCMP_LOOPUVMISMATCH;
- }
- }
- }
-
- if (l1->type == CD_MLOOPCOL) {
- MLoopCol *lp1 = l1->data;
- MLoopCol *lp2 = l2->data;
- int ltot = m1->totloop;
-
- for (j = 0; j < ltot; j++, lp1++, lp2++) {
- if (abs(lp1->r - lp2->r) > thresh || abs(lp1->g - lp2->g) > thresh ||
- abs(lp1->b - lp2->b) > thresh || abs(lp1->a - lp2->a) > thresh) {
- return MESHCMP_LOOPCOLMISMATCH;
- }
- }
- }
-
- if (l1->type == CD_MDEFORMVERT) {
- MDeformVert *dv1 = l1->data;
- MDeformVert *dv2 = l2->data;
- int dvtot = m1->totvert;
-
- for (j = 0; j < dvtot; j++, dv1++, dv2++) {
- int k;
- MDeformWeight *dw1 = dv1->dw, *dw2 = dv2->dw;
-
- if (dv1->totweight != dv2->totweight) {
- return MESHCMP_DVERT_TOTGROUPMISMATCH;
- }
-
- for (k = 0; k < dv1->totweight; k++, dw1++, dw2++) {
- if (dw1->def_nr != dw2->def_nr) {
- return MESHCMP_DVERT_GROUPMISMATCH;
- }
- if (fabsf(dw1->weight - dw2->weight) > thresh) {
- return MESHCMP_DVERT_WEIGHTMISMATCH;
- }
+ default: {
+ break;
}
}
}
@@ -967,7 +942,7 @@ Mesh *BKE_mesh_new_nomain(
NULL, ID_ME, BKE_idtype_idcode_to_name(ID_ME), LIB_ID_CREATE_LOCALIZE);
BKE_libblock_init_empty(&mesh->id);
- /* Don't use CustomData_reset(...); because we don't want to touch custom-data. */
+ /* Don't use #CustomData_reset because we don't want to touch custom-data. */
copy_vn_i(mesh->vdata.typemap, CD_NUMTYPES, -1);
copy_vn_i(mesh->edata.typemap, CD_NUMTYPES, -1);
copy_vn_i(mesh->fdata.typemap, CD_NUMTYPES, -1);
@@ -1698,10 +1673,7 @@ void BKE_mesh_do_versions_cd_flag_init(Mesh *mesh)
void BKE_mesh_mselect_clear(Mesh *me)
{
- if (me->mselect) {
- MEM_freeN(me->mselect);
- me->mselect = NULL;
- }
+ MEM_SAFE_FREE(me->mselect);
me->totselect = 0;
}
@@ -1918,15 +1890,14 @@ void BKE_mesh_calc_normals_split_ex(Mesh *mesh, MLoopNorSpaceArray *r_lnors_spac
}
else {
polynors = MEM_malloc_arrayN(mesh->totpoly, sizeof(float[3]), __func__);
- BKE_mesh_calc_normals_poly(mesh->mvert,
- NULL,
- mesh->totvert,
- mesh->mloop,
- mesh->mpoly,
- mesh->totloop,
- mesh->totpoly,
- polynors,
- false);
+ BKE_mesh_calc_normals_poly_and_vertex(mesh->mvert,
+ mesh->totvert,
+ mesh->mloop,
+ mesh->totloop,
+ mesh->mpoly,
+ mesh->totpoly,
+ polynors,
+ NULL);
free_polynors = true;
}
diff --git a/source/blender/blenkernel/intern/mesh_convert.c b/source/blender/blenkernel/intern/mesh_convert.c
index 0e4fe91e577..4b1eb5b39ce 100644
--- a/source/blender/blenkernel/intern/mesh_convert.c
+++ b/source/blender/blenkernel/intern/mesh_convert.c
@@ -38,6 +38,7 @@
#include "BLI_utildefines.h"
#include "BKE_DerivedMesh.h"
+#include "BKE_deform.h"
#include "BKE_displist.h"
#include "BKE_editmesh.h"
#include "BKE_key.h"
@@ -271,8 +272,8 @@ static int mesh_nurbs_displist_to_mdata(const Curve *cu,
}
if (totvert == 0) {
- /* error("can't convert"); */
- /* Make Sure you check ob->data is a curve */
+ /* Make Sure you check ob->data is a curve. */
+ // error("can't convert");
return -1;
}
@@ -1665,6 +1666,10 @@ void BKE_mesh_nomain_to_mesh(Mesh *mesh_src,
/* skip the listbase */
MEMCPY_STRUCT_AFTER(mesh_dst, &tmp, id.prev);
+ BLI_freelistN(&mesh_dst->vertex_group_names);
+ BKE_defgroup_copy_list(&mesh_dst->vertex_group_names, &mesh_src->vertex_group_names);
+ mesh_dst->vertex_group_active_index = mesh_src->vertex_group_active_index;
+
if (take_ownership) {
if (alloctype == CD_ASSIGN) {
CustomData_free_typemask(&mesh_src->vdata, mesh_src->totvert, ~mask->vmask);
diff --git a/source/blender/blenkernel/intern/mesh_mirror.c b/source/blender/blenkernel/intern/mesh_mirror.c
index 9aeaa1ada52..b20d81e7b9c 100644
--- a/source/blender/blenkernel/intern/mesh_mirror.c
+++ b/source/blender/blenkernel/intern/mesh_mirror.c
@@ -393,15 +393,14 @@ Mesh *BKE_mesh_mirror_apply_mirror_on_axis_for_modifier(MirrorModifierData *mmd,
/* calculate custom normals into loop_normals, then mirror first half into second half */
- BKE_mesh_calc_normals_poly(result->mvert,
- NULL,
- result->totvert,
- result->mloop,
- result->mpoly,
- totloop,
- totpoly,
- poly_normals,
- false);
+ BKE_mesh_calc_normals_poly_and_vertex(result->mvert,
+ result->totvert,
+ result->mloop,
+ totloop,
+ result->mpoly,
+ totpoly,
+ poly_normals,
+ NULL);
BKE_mesh_normals_loop_split(result->mvert,
result->totvert,
diff --git a/source/blender/blenkernel/intern/mesh_normals.cc b/source/blender/blenkernel/intern/mesh_normals.cc
index 87b11904f90..9a761c6fa11 100644
--- a/source/blender/blenkernel/intern/mesh_normals.cc
+++ b/source/blender/blenkernel/intern/mesh_normals.cc
@@ -27,8 +27,6 @@
#include <climits>
-#include "CLG_log.h"
-
#include "MEM_guardedalloc.h"
#include "DNA_mesh_types.h"
@@ -50,6 +48,8 @@
#include "BKE_global.h"
#include "BKE_mesh.h"
+#include "atomic_ops.h"
+
// #define DEBUG_TIME
#ifdef DEBUG_TIME
@@ -57,325 +57,257 @@
# include "PIL_time_utildefines.h"
#endif
-static CLG_LogRef LOG = {"bke.mesh_normals"};
-
/* -------------------------------------------------------------------- */
-/** \name Mesh Normal Calculation
+/** \name Private Utility Functions
* \{ */
-void BKE_mesh_normals_tag_dirty(Mesh *mesh)
-{
- mesh->runtime.cd_dirty_vert |= CD_MASK_NORMAL;
- mesh->runtime.cd_dirty_poly |= CD_MASK_NORMAL;
-}
-
/**
- * Call when there are no polygons.
+ * A thread-safe version of #add_v3_v3 that uses a spin-lock.
+ *
+ * \note Avoid using this when the chance of contention is high.
*/
-static void mesh_calc_normals_vert_fallback(MVert *mverts, int numVerts)
+static void add_v3_v3_atomic(float r[3], const float a[3])
{
- for (int i = 0; i < numVerts; i++) {
- MVert *mv = &mverts[i];
- float no[3];
+#define FLT_EQ_NONAN(_fa, _fb) (*((const uint32_t *)&_fa) == *((const uint32_t *)&_fb))
- normalize_v3_v3(no, mv->co);
- normal_float_to_short_v3(mv->no, no);
+ float virtual_lock = r[0];
+ while (true) {
+ /* This loops until following conditions are met:
+ * - `r[0]` has same value as virtual_lock (i.e. it did not change since last try).
+ * - `r[0]` was not `FLT_MAX`, i.e. it was not locked by another thread. */
+ const float test_lock = atomic_cas_float(&r[0], virtual_lock, FLT_MAX);
+ if (_ATOMIC_LIKELY(FLT_EQ_NONAN(test_lock, virtual_lock) && (test_lock != FLT_MAX))) {
+ break;
+ }
+ virtual_lock = test_lock;
}
-}
+ virtual_lock += a[0];
+ r[1] += a[1];
+ r[2] += a[2];
-/* TODO(Sybren): we can probably rename this to BKE_mesh_calc_normals_mapping(),
- * and remove the function of the same name below, as that one doesn't seem to be
- * called anywhere. */
-void BKE_mesh_calc_normals_mapping_simple(struct Mesh *mesh)
-{
- const bool only_face_normals = CustomData_is_referenced_layer(&mesh->vdata, CD_MVERT);
-
- BKE_mesh_calc_normals_mapping_ex(mesh->mvert,
- mesh->totvert,
- mesh->mloop,
- mesh->mpoly,
- mesh->totloop,
- mesh->totpoly,
- nullptr,
- mesh->mface,
- mesh->totface,
- nullptr,
- nullptr,
- only_face_normals);
-}
+ /* Second atomic operation to 'release'
+ * our lock on that vector and set its first scalar value. */
+ /* Note that we do not need to loop here, since we 'locked' `r[0]`,
+ * nobody should have changed it in the mean time. */
+ virtual_lock = atomic_cas_float(&r[0], FLT_MAX, virtual_lock);
+ BLI_assert(virtual_lock == FLT_MAX);
-/* 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,
- int numVerts,
- const MLoop *mloop,
- const MPoly *mpolys,
- int numLoops,
- int numPolys,
- float (*r_polyNors)[3],
- const MFace *mfaces,
- int numFaces,
- const int *origIndexFace,
- float (*r_faceNors)[3])
-{
- BKE_mesh_calc_normals_mapping_ex(mverts,
- numVerts,
- mloop,
- mpolys,
- numLoops,
- numPolys,
- r_polyNors,
- mfaces,
- numFaces,
- origIndexFace,
- r_faceNors,
- false);
+#undef FLT_EQ_NONAN
}
-/* extended version of 'BKE_mesh_calc_normals_poly' with option not to calc vertex normals */
-void BKE_mesh_calc_normals_mapping_ex(MVert *mverts,
- int numVerts,
- const MLoop *mloop,
- const MPoly *mpolys,
- int numLoops,
- int numPolys,
- float (*r_polyNors)[3],
- const MFace *mfaces,
- int numFaces,
- const int *origIndexFace,
- float (*r_faceNors)[3],
- const bool only_face_normals)
-{
- float(*pnors)[3] = r_polyNors, (*fnors)[3] = r_faceNors;
- if (numPolys == 0) {
- if (only_face_normals == false) {
- mesh_calc_normals_vert_fallback(mverts, numVerts);
- }
- return;
- }
-
- /* if we are not calculating verts and no verts were passes then we have nothing to do */
- if ((only_face_normals == true) && (r_polyNors == nullptr) && (r_faceNors == nullptr)) {
- CLOG_WARN(&LOG, "called with nothing to do");
- return;
- }
-
- if (!pnors) {
- 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"); */
+/** \} */
- if (only_face_normals == false) {
- /* vertex normals are optional, they require some extra calculations,
- * so make them optional */
- BKE_mesh_calc_normals_poly(
- mverts, nullptr, numVerts, mloop, mpolys, numLoops, numPolys, pnors, false);
- }
- else {
- /* only calc poly normals */
- const MPoly *mp = mpolys;
- for (int i = 0; i < numPolys; i++, mp++) {
- BKE_mesh_calc_poly_normal(mp, mloop + mp->loopstart, mverts, pnors[i]);
- }
- }
+/* -------------------------------------------------------------------- */
+/** \name Public Utility Functions
+ *
+ * Related to managing normals but not directly related to calculating normals.
+ * \{ */
- if (origIndexFace &&
- /* fnors == r_faceNors */ /* NO NEED TO ALLOC YET */
- fnors != nullptr &&
- numFaces) {
- const MFace *mf = mfaces;
- for (int i = 0; i < numFaces; i++, mf++, origIndexFace++) {
- if (*origIndexFace < numPolys) {
- copy_v3_v3(fnors[i], pnors[*origIndexFace]);
- }
- else {
- /* eek, we're not corresponding to polys */
- CLOG_ERROR(&LOG, "tessellation face indices are incorrect. normals may look bad.");
- }
- }
- }
+void BKE_mesh_normals_tag_dirty(Mesh *mesh)
+{
+ mesh->runtime.cd_dirty_vert |= CD_MASK_NORMAL;
+ mesh->runtime.cd_dirty_poly |= CD_MASK_NORMAL;
+}
- if (pnors != r_polyNors) {
- MEM_freeN(pnors);
- }
- /* if (fnors != r_faceNors) MEM_freeN(fnors); */ /* NO NEED TO ALLOC YET */
+/** \} */
- fnors = pnors = nullptr;
-}
+/* -------------------------------------------------------------------- */
+/** \name Mesh Normal Calculation (Polygons)
+ * \{ */
-struct MeshCalcNormalsData {
- const MPoly *mpolys;
+struct MeshCalcNormalsData_Poly {
+ const MVert *mvert;
const MLoop *mloop;
- MVert *mverts;
+ const MPoly *mpoly;
+
+ /** Polygon normal output. */
float (*pnors)[3];
- float (*lnors_weighted)[3];
- float (*vnors)[3];
};
-static void mesh_calc_normals_poly_cb(void *__restrict userdata,
+static void mesh_calc_normals_poly_fn(void *__restrict userdata,
const int pidx,
const TaskParallelTLS *__restrict UNUSED(tls))
{
- MeshCalcNormalsData *data = (MeshCalcNormalsData *)userdata;
- const MPoly *mp = &data->mpolys[pidx];
+ const MeshCalcNormalsData_Poly *data = (MeshCalcNormalsData_Poly *)userdata;
+ const MPoly *mp = &data->mpoly[pidx];
+ BKE_mesh_calc_poly_normal(mp, data->mloop + mp->loopstart, data->mvert, data->pnors[pidx]);
+}
+
+void BKE_mesh_calc_normals_poly(const MVert *mvert,
+ int UNUSED(mvert_len),
+ const MLoop *mloop,
+ int UNUSED(mloop_len),
+ const MPoly *mpoly,
+ int mpoly_len,
+ float (*r_poly_normals)[3])
+{
+ TaskParallelSettings settings;
+ BLI_parallel_range_settings_defaults(&settings);
+ settings.min_iter_per_thread = 1024;
- BKE_mesh_calc_poly_normal(mp, data->mloop + mp->loopstart, data->mverts, data->pnors[pidx]);
+ BLI_assert((r_poly_normals != nullptr) || (mpoly_len == 0));
+
+ MeshCalcNormalsData_Poly data = {};
+ data.mpoly = mpoly;
+ data.mloop = mloop;
+ data.mvert = mvert;
+ data.pnors = r_poly_normals;
+
+ BLI_task_parallel_range(0, mpoly_len, &data, mesh_calc_normals_poly_fn, &settings);
}
-static void mesh_calc_normals_poly_prepare_cb(void *__restrict userdata,
- const int pidx,
- const TaskParallelTLS *__restrict UNUSED(tls))
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Mesh Normal Calculation (Polygons & Vertices)
+ *
+ * Implement #BKE_mesh_calc_normals_poly_and_vertex,
+ *
+ * Take care making optimizations to this function as improvements to low-poly
+ * meshes can slow down high-poly meshes. For details on performance, see D11993.
+ * \{ */
+
+struct MeshCalcNormalsData_PolyAndVertex {
+ /** Write into vertex normals #MVert.no. */
+ MVert *mvert;
+ const MLoop *mloop;
+ const MPoly *mpoly;
+
+ /** Polygon normal output. */
+ float (*pnors)[3];
+ /** Vertex normal output (may be freed, copied into #MVert.no). */
+ float (*vnors)[3];
+};
+
+static void mesh_calc_normals_poly_and_vertex_accum_fn(
+ void *__restrict userdata, const int pidx, const TaskParallelTLS *__restrict UNUSED(tls))
{
- MeshCalcNormalsData *data = (MeshCalcNormalsData *)userdata;
- const MPoly *mp = &data->mpolys[pidx];
+ const MeshCalcNormalsData_PolyAndVertex *data = (MeshCalcNormalsData_PolyAndVertex *)userdata;
+ const MPoly *mp = &data->mpoly[pidx];
const MLoop *ml = &data->mloop[mp->loopstart];
- const MVert *mverts = data->mverts;
+ const MVert *mverts = data->mvert;
+ float(*vnors)[3] = data->vnors;
float pnor_temp[3];
float *pnor = data->pnors ? data->pnors[pidx] : pnor_temp;
- float(*lnors_weighted)[3] = data->lnors_weighted;
- const int nverts = mp->totloop;
- float(*edgevecbuf)[3] = (float(*)[3])BLI_array_alloca(edgevecbuf, (size_t)nverts);
+ const int i_end = mp->totloop - 1;
- /* Polygon Normal and edge-vector */
- /* inline version of #BKE_mesh_calc_poly_normal, also does edge-vectors */
+ /* Polygon Normal and edge-vector. */
+ /* Inline version of #BKE_mesh_calc_poly_normal, also does edge-vectors. */
{
- int i_prev = nverts - 1;
- const float *v_prev = mverts[ml[i_prev].v].co;
- const float *v_curr;
-
zero_v3(pnor);
/* Newell's Method */
- for (int i = 0; i < nverts; i++) {
- v_curr = mverts[ml[i].v].co;
- add_newell_cross_v3_v3v3(pnor, v_prev, v_curr);
-
- /* Unrelated to normalize, calculate edge-vector */
- sub_v3_v3v3(edgevecbuf[i_prev], v_prev, v_curr);
- normalize_v3(edgevecbuf[i_prev]);
- i_prev = i;
-
- v_prev = v_curr;
+ const float *v_curr = mverts[ml[i_end].v].co;
+ for (int i_next = 0; i_next <= i_end; i_next++) {
+ const float *v_next = mverts[ml[i_next].v].co;
+ add_newell_cross_v3_v3v3(pnor, v_curr, v_next);
+ v_curr = v_next;
}
if (UNLIKELY(normalize_v3(pnor) == 0.0f)) {
- pnor[2] = 1.0f; /* other axes set to 0.0 */
+ pnor[2] = 1.0f; /* Other axes set to zero. */
}
}
- /* accumulate angle weighted face normal */
- /* inline version of #accumulate_vertex_normals_poly_v3,
- * split between this threaded callback and #mesh_calc_normals_poly_accum_cb. */
+ /* Accumulate angle weighted face normal into the vertex normal. */
+ /* Inline version of #accumulate_vertex_normals_poly_v3. */
{
- const float *prev_edge = edgevecbuf[nverts - 1];
-
- for (int i = 0; i < nverts; i++) {
- const int lidx = mp->loopstart + i;
- const float *cur_edge = edgevecbuf[i];
-
- /* calculate angle between the two poly edges incident on
- * this vertex */
- const float fac = saacos(-dot_v3v3(cur_edge, prev_edge));
+ float edvec_prev[3], edvec_next[3], edvec_end[3];
+ const float *v_curr = mverts[ml[i_end].v].co;
+ sub_v3_v3v3(edvec_prev, mverts[ml[i_end - 1].v].co, v_curr);
+ normalize_v3(edvec_prev);
+ copy_v3_v3(edvec_end, edvec_prev);
+
+ for (int i_next = 0, i_curr = i_end; i_next <= i_end; i_curr = i_next++) {
+ const float *v_next = mverts[ml[i_next].v].co;
+
+ /* Skip an extra normalization by reusing the first calculated edge. */
+ if (i_next != i_end) {
+ sub_v3_v3v3(edvec_next, v_curr, v_next);
+ normalize_v3(edvec_next);
+ }
+ else {
+ copy_v3_v3(edvec_next, edvec_end);
+ }
- /* Store for later accumulation */
- mul_v3_v3fl(lnors_weighted[lidx], pnor, fac);
+ /* Calculate angle between the two poly edges incident on this vertex. */
+ const float fac = saacos(-dot_v3v3(edvec_prev, edvec_next));
+ const float vnor_add[3] = {pnor[0] * fac, pnor[1] * fac, pnor[2] * fac};
- prev_edge = cur_edge;
+ add_v3_v3_atomic(vnors[ml[i_curr].v], vnor_add);
+ v_curr = v_next;
+ copy_v3_v3(edvec_prev, edvec_next);
}
}
}
-static void mesh_calc_normals_poly_finalize_cb(void *__restrict userdata,
- const int vidx,
- const TaskParallelTLS *__restrict UNUSED(tls))
+static void mesh_calc_normals_poly_and_vertex_finalize_fn(
+ void *__restrict userdata, const int vidx, const TaskParallelTLS *__restrict UNUSED(tls))
{
- MeshCalcNormalsData *data = (MeshCalcNormalsData *)userdata;
+ MeshCalcNormalsData_PolyAndVertex *data = (MeshCalcNormalsData_PolyAndVertex *)userdata;
- MVert *mv = &data->mverts[vidx];
+ MVert *mv = &data->mvert[vidx];
float *no = data->vnors[vidx];
if (UNLIKELY(normalize_v3(no) == 0.0f)) {
- /* following Mesh convention; we use vertex coordinate itself for normal in this case */
+ /* Following Mesh convention; we use vertex coordinate itself for normal in this case. */
normalize_v3_v3(no, mv->co);
}
normal_float_to_short_v3(mv->no, no);
}
-void BKE_mesh_calc_normals_poly(MVert *mverts,
- float (*r_vertnors)[3],
- int numVerts,
- const MLoop *mloop,
- const MPoly *mpolys,
- int numLoops,
- int numPolys,
- float (*r_polynors)[3],
- const bool only_face_normals)
+void BKE_mesh_calc_normals_poly_and_vertex(MVert *mvert,
+ const int mvert_len,
+ const MLoop *mloop,
+ const int UNUSED(mloop_len),
+ const MPoly *mpoly,
+ const int mpoly_len,
+ float (*r_poly_normals)[3],
+ float (*r_vert_normals)[3])
{
- float(*pnors)[3] = r_polynors;
-
TaskParallelSettings settings;
BLI_parallel_range_settings_defaults(&settings);
settings.min_iter_per_thread = 1024;
- if (only_face_normals) {
- 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] = (float(*)[3])MEM_malloc_arrayN(
- (size_t)numLoops, sizeof(*lnors_weighted), __func__);
+ float(*vnors)[3] = r_vert_normals;
bool free_vnors = false;
- /* first go through and calculate normals for all the polys */
+ /* First go through and calculate normals for all the polys. */
if (vnors == nullptr) {
- vnors = (float(*)[3])MEM_calloc_arrayN((size_t)numVerts, sizeof(*vnors), __func__);
+ vnors = (float(*)[3])MEM_calloc_arrayN((size_t)mvert_len, sizeof(*vnors), __func__);
free_vnors = true;
}
else {
- memset(vnors, 0, sizeof(*vnors) * (size_t)numVerts);
+ memset(vnors, 0, sizeof(*vnors) * (size_t)mvert_len);
}
- MeshCalcNormalsData data;
- data.mpolys = mpolys;
+ MeshCalcNormalsData_PolyAndVertex data = {};
+ data.mpoly = mpoly;
data.mloop = mloop;
- data.mverts = mverts;
- data.pnors = pnors;
- data.lnors_weighted = lnors_weighted;
+ data.mvert = mvert;
+ data.pnors = r_poly_normals;
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);
+ /* Compute poly normals (`pnors`), accumulating them into vertex normals (`vnors`). */
+ BLI_task_parallel_range(
+ 0, mpoly_len, &data, mesh_calc_normals_poly_and_vertex_accum_fn, &settings);
- /* Actually accumulate weighted loop normals into vertex ones. */
- /* Unfortunately, not possible to thread that
- * (not in a reasonable, totally lock- and barrier-free fashion),
- * since several loops will point to the same vertex... */
- for (int lidx = 0; lidx < numLoops; lidx++) {
- add_v3_v3(vnors[mloop[lidx].v], data.lnors_weighted[lidx]);
- }
-
- /* Normalize and validate computed vertex normals. */
- BLI_task_parallel_range(0, numVerts, &data, mesh_calc_normals_poly_finalize_cb, &settings);
+ /* Normalize and validate computed vertex normals (`vnors`). */
+ BLI_task_parallel_range(
+ 0, mvert_len, &data, mesh_calc_normals_poly_and_vertex_finalize_fn, &settings);
if (free_vnors) {
MEM_freeN(vnors);
}
- MEM_freeN(lnors_weighted);
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Mesh Normal Calculation
+ * \{ */
+
void BKE_mesh_ensure_normals(Mesh *mesh)
{
if (mesh->runtime.cd_dirty_vert & CD_MASK_NORMAL) {
@@ -416,16 +348,26 @@ void BKE_mesh_ensure_normals_for_display(Mesh *mesh)
(size_t)mesh->totpoly, sizeof(*poly_nors), __func__);
}
- /* calculate poly/vert normals */
- BKE_mesh_calc_normals_poly(mesh->mvert,
- nullptr,
- mesh->totvert,
- mesh->mloop,
- mesh->mpoly,
- mesh->totloop,
- mesh->totpoly,
- poly_nors,
- !do_vert_normals);
+ /* Calculate poly/vert normals. */
+ if (do_vert_normals) {
+ BKE_mesh_calc_normals_poly_and_vertex(mesh->mvert,
+ mesh->totvert,
+ mesh->mloop,
+ mesh->totloop,
+ mesh->mpoly,
+ mesh->totpoly,
+ poly_nors,
+ nullptr);
+ }
+ else {
+ BKE_mesh_calc_normals_poly(mesh->mvert,
+ mesh->totvert,
+ mesh->mloop,
+ mesh->totloop,
+ mesh->mpoly,
+ mesh->totpoly,
+ poly_nors);
+ }
if (do_add_poly_nors_cddata) {
CustomData_add_layer(&mesh->pdata, CD_NORMAL, CD_ASSIGN, poly_nors, mesh->totpoly);
@@ -436,22 +378,23 @@ void BKE_mesh_ensure_normals_for_display(Mesh *mesh)
}
}
-/* Note that this does not update the CD_NORMAL layer,
- * but does update the normals in the CD_MVERT layer. */
+/**
+ * NOTE: this does not update the #CD_NORMAL layer,
+ * but does update the normals in the #CD_MVERT layer.
+ */
void BKE_mesh_calc_normals(Mesh *mesh)
{
#ifdef DEBUG_TIME
TIMEIT_START_AVERAGED(BKE_mesh_calc_normals);
#endif
- BKE_mesh_calc_normals_poly(mesh->mvert,
- nullptr,
- mesh->totvert,
- mesh->mloop,
- mesh->mpoly,
- mesh->totloop,
- mesh->totpoly,
- nullptr,
- false);
+ BKE_mesh_calc_normals_poly_and_vertex(mesh->mvert,
+ mesh->totvert,
+ mesh->mloop,
+ mesh->totloop,
+ mesh->mpoly,
+ mesh->totpoly,
+ nullptr,
+ nullptr);
#ifdef DEBUG_TIME
TIMEIT_END_AVERAGED(BKE_mesh_calc_normals);
#endif
@@ -494,7 +437,7 @@ void BKE_mesh_calc_normals_looptri(MVert *mverts,
mverts[vtri[2]].co);
}
- /* following Mesh convention; we use vertex coordinate itself for normal in this case */
+ /* Following Mesh convention; we use vertex coordinate itself for normal in this case. */
for (int i = 0; i < numVerts; i++) {
MVert *mv = &mverts[i];
float *no = tnorms[i];
@@ -634,11 +577,11 @@ void BKE_lnor_space_define(MLoopNorSpace *lnor_space,
BLI_stack_discard(edge_vectors);
nbr++;
}
- /* 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.).
+ /* 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.).
*/
- BLI_assert(nbr >= 2); /* This piece of code shall only be called for more than one loop... */
+ BLI_assert(nbr >= 2); /* This piece of code shall only be called for more than one loop. */
lnor_space->ref_alpha = alpha / (float)nbr;
}
else {
@@ -710,7 +653,7 @@ MINLINE float unit_short_to_float(const short val)
MINLINE short unit_float_to_short(const float val)
{
- /* Rounding... */
+ /* Rounding. */
return (short)floorf(val * (float)SHRT_MAX + 0.5f);
}
@@ -921,7 +864,7 @@ static void mesh_edges_sharp_tag(LoopSplitTaskDataCommon *data,
e2l[1] = INDEX_INVALID;
/* We want to avoid tagging edges as sharp when it is already defined as such by
- * other causes than angle threshold... */
+ * other causes than angle threshold. */
if (do_sharp_edges_tag && is_angle_sharp) {
BLI_BITMAP_SET(sharp_edges, ml_curr->e, true);
}
@@ -935,7 +878,7 @@ static void mesh_edges_sharp_tag(LoopSplitTaskDataCommon *data,
e2l[1] = INDEX_INVALID;
/* We want to avoid tagging edges as sharp when it is already defined as such by
- * other causes than angle threshold... */
+ * other causes than angle threshold. */
if (do_sharp_edges_tag) {
BLI_BITMAP_SET(sharp_edges, ml_curr->e, false);
}
@@ -1017,14 +960,13 @@ void BKE_mesh_loop_manifold_fan_around_vert_next(const MLoop *mloops,
const MLoop *mlfan_next;
const MPoly *mpfan_next;
- /* Warning! This is rather complex!
+ /* WARNING: This is rather complex!
* We have to find our next edge around the vertex (fan mode).
* First we find the next loop, which is either previous or next to mlfan_curr_index, depending
* whether both loops using current edge are in the same direction or not, and whether
* mlfan_curr_index actually uses the vertex we are fanning around!
* mlfan_curr_index is the index of mlfan_next here, and mlfan_next is not the real next one
- * (i.e. not the future mlfan_curr)...
- */
+ * (i.e. not the future `mlfan_curr`). */
*r_mlfan_curr_index = (e2lfan_curr[0] == *r_mlfan_curr_index) ? e2lfan_curr[1] : e2lfan_curr[0];
*r_mpfan_curr_index = loop_to_poly[*r_mlfan_curr_index];
@@ -1049,7 +991,7 @@ void BKE_mesh_loop_manifold_fan_around_vert_next(const MLoop *mloops,
*r_mlfan_vert_index = *r_mlfan_curr_index;
}
*r_mlfan_curr = &mloops[*r_mlfan_curr_index];
- /* And now we are back in sync, mlfan_curr_index is the index of mlfan_curr! Pff! */
+ /* And now we are back in sync, mlfan_curr_index is the index of `mlfan_curr`! Pff! */
}
static void split_loop_nor_single_do(LoopSplitTaskDataCommon *common_data, LoopSplitTaskData *data)
@@ -1104,8 +1046,7 @@ static void split_loop_nor_single_do(LoopSplitTaskDataCommon *common_data, LoopS
normalize_v3(vec_prev);
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... */
+ /* We know there is only one loop in this space, no need to create a link-list in this case. */
BKE_lnor_space_add_loop(lnors_spacearr, lnor_space, ml_curr_index, nullptr, true);
if (clnors_data) {
@@ -1141,24 +1082,24 @@ static void split_loop_nor_fan_do(LoopSplitTaskDataCommon *common_data, LoopSpli
BLI_Stack *edge_vectors = data->edge_vectors;
- /* Gah... We have to fan around current vertex, until we find the other non-smooth edge,
+ /* Sigh! we have to fan around current vertex, until we find the other non-smooth edge,
* and accumulate face normals into the vertex!
* Note in case this vertex has only one sharp edges, this is a waste because the normal is the
* same as the vertex normal, but I do not see any easy way to detect that (would need to count
* number of sharp edges per vertex, I doubt the additional memory usage would be worth it,
- * especially as it should not be a common case in real-life meshes anyway).
- */
+ * especially as it should not be a common case in real-life meshes anyway). */
const uint mv_pivot_index = ml_curr->v; /* The vertex we are "fanning" around! */
const MVert *mv_pivot = &mverts[mv_pivot_index];
- /* ml_curr would be mlfan_prev if we needed that one. */
+ /* `ml_curr` would be mlfan_prev if we needed that one. */
const MEdge *me_org = &medges[ml_curr->e];
const int *e2lfan_curr;
float vec_curr[3], vec_prev[3], vec_org[3];
const MLoop *mlfan_curr;
float lnor[3] = {0.0f, 0.0f, 0.0f};
- /* mlfan_vert_index: the loop of our current edge might not be the loop of our current vertex! */
+ /* `mlfan_vert_index` the loop of our current edge might not be the loop of our current vertex!
+ */
int mlfan_curr_index, mlfan_vert_index, mpfan_curr_index;
/* We validate clnors data on the fly - cheapest way to do! */
@@ -1202,7 +1143,7 @@ static void split_loop_nor_fan_do(LoopSplitTaskDataCommon *common_data, LoopSpli
/* Compute edge vectors.
* NOTE: We could pre-compute those into an array, in the first iteration, instead of computing
* them twice (or more) here. However, time gained is not worth memory and time lost,
- * given the fact that this code should not be called that much in real-life meshes...
+ * given the fact that this code should not be called that much in real-life meshes.
*/
{
const MVert *mv_2 = (me_curr->v1 == mv_pivot_index) ? &mverts[me_curr->v2] :
@@ -1394,12 +1335,13 @@ static bool loop_split_generator_check_cyclic_smooth_fan(const MLoop *mloops,
const uint mv_pivot_index = ml_curr->v; /* The vertex we are "fanning" around! */
const int *e2lfan_curr;
const MLoop *mlfan_curr;
- /* mlfan_vert_index: the loop of our current edge might not be the loop of our current vertex! */
+ /* `mlfan_vert_index` the loop of our current edge might not be the loop of our current vertex!
+ */
int mlfan_curr_index, mlfan_vert_index, mpfan_curr_index;
e2lfan_curr = e2l_prev;
if (IS_EDGE_SHARP(e2lfan_curr)) {
- /* Sharp loop, so not a cyclic smooth fan... */
+ /* Sharp loop, so not a cyclic smooth fan. */
return false;
}
@@ -1430,21 +1372,21 @@ static bool loop_split_generator_check_cyclic_smooth_fan(const MLoop *mloops,
e2lfan_curr = edge_to_loops[mlfan_curr->e];
if (IS_EDGE_SHARP(e2lfan_curr)) {
- /* Sharp loop/edge, so not a cyclic smooth fan... */
+ /* Sharp loop/edge, so not a cyclic smooth fan. */
return false;
}
- /* Smooth loop/edge... */
+ /* Smooth loop/edge. */
if (BLI_BITMAP_TEST(skip_loops, mlfan_vert_index)) {
if (mlfan_vert_index == ml_curr_index) {
/* We walked around a whole cyclic smooth fan without finding any already-processed loop,
- * means we can use initial ml_curr/ml_prev edge as start for this smooth fan. */
+ * means we can use initial `ml_curr` / `ml_prev` edge as start for this smooth fan. */
return true;
}
- /* ... already checked in some previous looping, we can abort. */
+ /* Already checked in some previous looping, we can abort. */
return false;
}
- /* ... we can skip it in future, and keep checking the smooth fan. */
+ /* We can skip it in future, and keep checking the smooth fan. */
BLI_BITMAP_ENABLE(skip_loops, mlfan_vert_index);
}
}
@@ -1506,7 +1448,7 @@ static void loop_split_generator(TaskPool *pool, LoopSplitTaskDataCommon *common
const int *e2l_prev = edge_to_loops[ml_prev->e];
#if 0
- printf("Checking loop %d / edge %u / vert %u (sharp edge: %d, skiploop: %d)...",
+ printf("Checking loop %d / edge %u / vert %u (sharp edge: %d, skiploop: %d)",
ml_curr_index,
ml_curr->e,
ml_curr->v,
@@ -1610,7 +1552,7 @@ static void loop_split_generator(TaskPool *pool, LoopSplitTaskDataCommon *common
}
}
- /* Last block of data... Since it is calloc'ed and we use first nullptr 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, nullptr);
@@ -1657,8 +1599,7 @@ void BKE_mesh_normals_loop_split(const MVert *mverts,
* since we may want to use lnors even when mesh's 'autosmooth' is disabled
* (see e.g. mesh mapping code).
* As usual, we could handle that on case-by-case basis,
- * but simpler to keep it well confined here.
- */
+ * but simpler to keep it well confined here. */
int mp_index;
for (mp_index = 0; mp_index < numPolys; mp_index++) {
@@ -1741,7 +1682,7 @@ void BKE_mesh_normals_loop_split(const MVert *mverts,
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... */
+ /* Not enough loops to be worth the whole threading overhead. */
loop_split_generator(nullptr, &common_data);
}
else {
@@ -1796,13 +1737,12 @@ static void mesh_normals_loop_custom_set(const MVert *mverts,
short (*r_clnors_data)[2],
const bool use_vertices)
{
- /* We *may* make that poor BKE_mesh_normals_loop_split() even more complex by making it handling
+ /* We *may* make that poor #BKE_mesh_normals_loop_split() even more complex by making it handling
* that feature too, would probably be more efficient in absolute.
* However, this function *is not* performance-critical, since it is mostly expected to be called
- * by io addons when importing custom normals, and modifier
+ * by io add-ons when importing custom normals, and modifier
* (and perhaps from some editing tools later?).
- * So better to keep some simplicity here, and just call BKE_mesh_normals_loop_split() twice!
- */
+ * So better to keep some simplicity here, and just call #BKE_mesh_normals_loop_split() twice! */
MLoopNorSpaceArray lnors_spacearr = {nullptr};
BLI_bitmap *done_loops = BLI_BITMAP_NEW((size_t)numLoops, __func__);
float(*lnors)[3] = (float(*)[3])MEM_calloc_arrayN((size_t)numLoops, sizeof(*lnors), __func__);
@@ -1854,15 +1794,13 @@ static void mesh_normals_loop_custom_set(const MVert *mverts,
* This way, next time we run BKE_mesh_normals_loop_split(), we'll get lnor spacearr/smooth fans
* matching given custom lnors.
* Note this code *will never* unsharp edges! And quite obviously,
- * when we set custom normals per vertices, running this is absolutely useless.
- */
+ * when we set custom normals per vertices, running this is absolutely useless. */
if (!use_vertices) {
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 nullptr loopspacearr at this point. :/
- * Maybe we should set those loops' edges as sharp?
- */
+ * Maybe we should set those loops' edges as sharp? */
BLI_BITMAP_ENABLE(done_loops, i);
if (G.debug & G_DEBUG) {
printf("WARNING! Getting invalid nullptr loop space for loop %d!\n", i);
@@ -1872,12 +1810,12 @@ static void mesh_normals_loop_custom_set(const MVert *mverts,
if (!BLI_BITMAP_TEST(done_loops, i)) {
/* Notes:
- * * In case of mono-loop smooth fan, we have nothing to do.
- * * Loops in this linklist are ordered (in reversed order compared to how they were
+ * - In case of mono-loop smooth fan, we have nothing to do.
+ * - Loops in this linklist are ordered (in reversed order compared to how they were
* discovered by BKE_mesh_normals_loop_split(), but this is not a problem).
* Which means if we find a mismatching clnor,
* we know all remaining loops will have to be in a new, different smooth fan/lnor space.
- * * In smooth fan case, we compare each clnor against a ref one,
+ * - In smooth fan case, we compare each clnor against a ref one,
* to avoid small differences adding up into a real big one in the end!
*/
if (lnors_spacearr.lspacearr[i]->flags & MLNOR_SPACE_IS_SINGLE) {
@@ -1902,8 +1840,7 @@ static void mesh_normals_loop_custom_set(const MVert *mverts,
/* Current normal differs too much from org one, we have to tag the edge between
* previous loop's face and current's one as sharp.
* We know those two loops do not point to the same edge,
- * since we do not allow reversed winding in a same smooth fan.
- */
+ * since we do not allow reversed winding in a same smooth fan. */
const MPoly *mp = &mpolys[loop_to_poly[lidx]];
const MLoop *mlp =
&mloops[(lidx == mp->loopstart) ? mp->loopstart + mp->totloop - 1 : lidx - 1];
@@ -1975,8 +1912,7 @@ static void mesh_normals_loop_custom_set(const MVert *mverts,
if (BLI_BITMAP_TEST_BOOL(done_loops, i)) {
/* Note we accumulate and average all custom normals in current smooth fan,
* to avoid getting different clnors data (tiny differences in plain custom normals can
- * give rather huge differences in computed 2D factors).
- */
+ * give rather huge differences in computed 2D factors). */
LinkNode *loops = lnors_spacearr.lspacearr[i]->loops;
if (lnors_spacearr.lspacearr[i]->flags & MLNOR_SPACE_IS_SINGLE) {
BLI_assert(POINTER_AS_INT(loops) == i);
@@ -2092,15 +2028,14 @@ static void mesh_set_custom_normals(Mesh *mesh, float (*r_custom_nors)[3], const
bool free_polynors = false;
if (polynors == nullptr) {
polynors = (float(*)[3])MEM_mallocN(sizeof(float[3]) * (size_t)mesh->totpoly, __func__);
- BKE_mesh_calc_normals_poly(mesh->mvert,
- nullptr,
- mesh->totvert,
- mesh->mloop,
- mesh->mpoly,
- mesh->totloop,
- mesh->totpoly,
- polynors,
- false);
+ BKE_mesh_calc_normals_poly_and_vertex(mesh->mvert,
+ mesh->totvert,
+ mesh->mloop,
+ mesh->totloop,
+ mesh->mpoly,
+ mesh->totpoly,
+ polynors,
+ nullptr);
free_polynors = true;
}
diff --git a/source/blender/blenkernel/intern/mesh_remap.c b/source/blender/blenkernel/intern/mesh_remap.c
index c5e8858ea12..53a31cbbc7a 100644
--- a/source/blender/blenkernel/intern/mesh_remap.c
+++ b/source/blender/blenkernel/intern/mesh_remap.c
@@ -1379,14 +1379,12 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode,
}
if (dirty_nors_dst || do_poly_nors_dst) {
BKE_mesh_calc_normals_poly(verts_dst,
- NULL,
numverts_dst,
loops_dst,
- polys_dst,
numloops_dst,
+ polys_dst,
numpolys_dst,
- poly_nors_dst,
- true);
+ poly_nors_dst);
}
}
if (need_lnors_dst) {
@@ -2231,14 +2229,12 @@ void BKE_mesh_remap_calc_polys_from_mesh(const int mode,
}
if (dirty_nors_dst) {
BKE_mesh_calc_normals_poly(verts_dst,
- NULL,
numverts_dst,
loops_dst,
- polys_dst,
numloops_dst,
+ polys_dst,
numpolys_dst,
- poly_nors_dst,
- true);
+ poly_nors_dst);
}
}
diff --git a/source/blender/blenkernel/intern/multires.c b/source/blender/blenkernel/intern/multires.c
index 54f0da30a2b..eaa11a6683a 100644
--- a/source/blender/blenkernel/intern/multires.c
+++ b/source/blender/blenkernel/intern/multires.c
@@ -468,15 +468,9 @@ void multires_force_sculpt_rebuild(Object *object)
object->sculpt->pbvh = NULL;
}
- if (ss->pmap != NULL) {
- MEM_freeN(ss->pmap);
- ss->pmap = NULL;
- }
+ MEM_SAFE_FREE(ss->pmap);
- if (ss->pmap_mem != NULL) {
- MEM_freeN(ss->pmap_mem);
- ss->pmap_mem = NULL;
- }
+ MEM_SAFE_FREE(ss->pmap_mem);
}
void multires_force_external_reload(Object *object)
diff --git a/source/blender/blenkernel/intern/node.cc b/source/blender/blenkernel/intern/node.cc
index 1c990c409f6..4e58a076419 100644
--- a/source/blender/blenkernel/intern/node.cc
+++ b/source/blender/blenkernel/intern/node.cc
@@ -2364,7 +2364,7 @@ bNodeLink *nodeAddLink(
ntree->update |= NTREE_UPDATE_LINKS;
}
- if (link->tosock->flag & SOCK_MULTI_INPUT) {
+ if (link != nullptr && link->tosock->flag & SOCK_MULTI_INPUT) {
link->multi_input_socket_index = node_count_links(ntree, link->tosock) - 1;
}
@@ -3194,6 +3194,7 @@ void ntreeFreeEmbeddedTree(bNodeTree *ntree)
{
ntreeFreeTree(ntree);
BKE_libblock_free_data(&ntree->id, true);
+ BKE_libblock_free_data_py(&ntree->id);
}
void ntreeFreeLocalTree(bNodeTree *ntree)
@@ -5182,6 +5183,7 @@ static void registerGeometryNodes()
register_node_type_geo_points_to_volume();
register_node_type_geo_raycast();
register_node_type_geo_sample_texture();
+ register_node_type_geo_select_by_handle_type();
register_node_type_geo_select_by_material();
register_node_type_geo_separate_components();
register_node_type_geo_subdivision_surface();
diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c
index f969ca0ff1c..23b9dca8371 100644
--- a/source/blender/blenkernel/intern/object.c
+++ b/source/blender/blenkernel/intern/object.c
@@ -914,7 +914,7 @@ static void object_blend_read_lib(BlendLibReader *reader, ID *id)
if (ob->id.lib) {
BLO_reportf_wrap(reports,
RPT_INFO,
- TIP_("Can't find obdata of %s lib %s\n"),
+ TIP_("Can't find object data of %s lib %s\n"),
ob->id.name + 2,
ob->id.lib->filepath);
}
@@ -4047,10 +4047,7 @@ void BKE_object_empty_draw_type_set(Object *ob, const int value)
}
}
else {
- if (ob->iuser) {
- MEM_freeN(ob->iuser);
- ob->iuser = NULL;
- }
+ MEM_SAFE_FREE(ob->iuser);
}
}
diff --git a/source/blender/blenkernel/intern/object_deform.c b/source/blender/blenkernel/intern/object_deform.c
index c69326a23c6..511f5d4ae66 100644
--- a/source/blender/blenkernel/intern/object_deform.c
+++ b/source/blender/blenkernel/intern/object_deform.c
@@ -307,10 +307,7 @@ static void object_defgroup_remove_common(Object *ob, bDeformGroup *dg, const in
}
else if (ob->type == OB_LATTICE) {
Lattice *lt = object_defgroup_lattice_get((ID *)(ob->data));
- if (lt->dvert) {
- MEM_freeN(lt->dvert);
- lt->dvert = NULL;
- }
+ MEM_SAFE_FREE(lt->dvert);
}
}
else if (BKE_object_defgroup_active_index_get(ob) < 1) {
@@ -465,10 +462,7 @@ void BKE_object_defgroup_remove_all_ex(struct Object *ob, bool only_unlocked)
}
else if (ob->type == OB_LATTICE) {
Lattice *lt = object_defgroup_lattice_get((ID *)(ob->data));
- if (lt->dvert) {
- MEM_freeN(lt->dvert);
- lt->dvert = NULL;
- }
+ MEM_SAFE_FREE(lt->dvert);
}
/* Fix counters/indices */
BKE_object_defgroup_active_index_set(ob, 0);
diff --git a/source/blender/blenkernel/intern/ocean.c b/source/blender/blenkernel/intern/ocean.c
index 4d003ddc900..e9683d3b52c 100644
--- a/source/blender/blenkernel/intern/ocean.c
+++ b/source/blender/blenkernel/intern/ocean.c
@@ -530,7 +530,7 @@ static void ocean_compute_jacobian_jxx(TaskPool *__restrict pool, void *UNUSED(t
for (j = 0; j <= o->_N / 2; j++) {
fftw_complex mul_param;
- /* init_complex(mul_param, -scale, 0); */
+ // init_complex(mul_param, -scale, 0);
init_complex(mul_param, -1, 0);
mul_complex_f(mul_param, mul_param, chop_amount);
@@ -563,7 +563,7 @@ static void ocean_compute_jacobian_jzz(TaskPool *__restrict pool, void *UNUSED(t
for (j = 0; j <= o->_N / 2; j++) {
fftw_complex mul_param;
- /* init_complex(mul_param, -scale, 0); */
+ // init_complex(mul_param, -scale, 0);
init_complex(mul_param, -1, 0);
mul_complex_f(mul_param, mul_param, chop_amount);
@@ -596,7 +596,7 @@ static void ocean_compute_jacobian_jxz(TaskPool *__restrict pool, void *UNUSED(t
for (j = 0; j <= o->_N / 2; j++) {
fftw_complex mul_param;
- /* init_complex(mul_param, -scale, 0); */
+ // init_complex(mul_param, -scale, 0);
init_complex(mul_param, -1, 0);
mul_complex_f(mul_param, mul_param, chop_amount);
@@ -1015,7 +1015,7 @@ bool BKE_ocean_init(struct Ocean *o,
"ocean_fft_in_nz");
o->_N_x = (double *)MEM_mallocN(o->_M * o->_N * sizeof(double), "ocean_N_x");
- /* o->_N_y = (float *) fftwf_malloc(o->_M * o->_N * sizeof(float)); (MEM01) */
+ // o->_N_y = (float *) fftwf_malloc(o->_M * o->_N * sizeof(float)); /* (MEM01) */
o->_N_z = (double *)MEM_mallocN(o->_M * o->_N * sizeof(double), "ocean_N_z");
o->_N_x_plan = fftw_plan_dft_c2r_2d(o->_M, o->_N, o->_fft_in_nx, o->_N_x, FFTW_ESTIMATE);
@@ -1083,7 +1083,7 @@ void BKE_ocean_free_data(struct Ocean *oc)
fftw_destroy_plan(oc->_N_x_plan);
fftw_destroy_plan(oc->_N_z_plan);
MEM_freeN(oc->_N_x);
- /* fftwf_free(oc->_N_y); (MEM01) */
+ // fftwf_free(oc->_N_y); /* (MEM01) */
MEM_freeN(oc->_N_z);
}
diff --git a/source/blender/blenkernel/intern/ocean_spectrum.c b/source/blender/blenkernel/intern/ocean_spectrum.c
index 7ed70234baf..c5504b22b43 100644
--- a/source/blender/blenkernel/intern/ocean_spectrum.c
+++ b/source/blender/blenkernel/intern/ocean_spectrum.c
@@ -77,7 +77,7 @@ static float ocean_spectrum_wind_and_damp(const Ocean *oc,
float newval = val * pow(fabs(k_dot_w), oc->_wind_alignment);
/* Eliminate wavelengths smaller than cutoff. */
- /* val *= exp(-k2 * m_cutoff); */
+ // val *= exp(-k2 * m_cutoff);
/* Reduce reflected waves. */
if (k_dot_w < 0.0f) {
diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c
index f2f3c5d4ca6..cc8a051eceb 100644
--- a/source/blender/blenkernel/intern/particle.c
+++ b/source/blender/blenkernel/intern/particle.c
@@ -928,10 +928,7 @@ void free_hair(Object *object, ParticleSystem *psys, int dynamics)
LOOP_PARTICLES
{
- if (pa->hair) {
- MEM_freeN(pa->hair);
- }
- pa->hair = NULL;
+ MEM_SAFE_FREE(pa->hair);
pa->totkey = 0;
}
@@ -1044,25 +1041,13 @@ void psys_free_particles(ParticleSystem *psys)
void psys_free_pdd(ParticleSystem *psys)
{
if (psys->pdd) {
- if (psys->pdd->cdata) {
- MEM_freeN(psys->pdd->cdata);
- }
- psys->pdd->cdata = NULL;
+ MEM_SAFE_FREE(psys->pdd->cdata);
- if (psys->pdd->vdata) {
- MEM_freeN(psys->pdd->vdata);
- }
- psys->pdd->vdata = NULL;
+ MEM_SAFE_FREE(psys->pdd->vdata);
- if (psys->pdd->ndata) {
- MEM_freeN(psys->pdd->ndata);
- }
- psys->pdd->ndata = NULL;
+ MEM_SAFE_FREE(psys->pdd->ndata);
- if (psys->pdd->vedata) {
- MEM_freeN(psys->pdd->vedata);
- }
- psys->pdd->vedata = NULL;
+ MEM_SAFE_FREE(psys->pdd->vedata);
psys->pdd->totpoint = 0;
psys->pdd->totpart = 0;
diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c
index 9c0c5639777..60edb78f8ba 100644
--- a/source/blender/blenkernel/intern/particle_system.c
+++ b/source/blender/blenkernel/intern/particle_system.c
@@ -169,10 +169,7 @@ void psys_reset(ParticleSystem *psys, int mode)
}
/* reset children */
- if (psys->child) {
- MEM_freeN(psys->child);
- psys->child = NULL;
- }
+ MEM_SAFE_FREE(psys->child);
psys->totchild = 0;
@@ -182,10 +179,7 @@ void psys_reset(ParticleSystem *psys, int mode)
/* reset point cache */
BKE_ptcache_invalidate(psys->pointcache);
- if (psys->fluid_springs) {
- MEM_freeN(psys->fluid_springs);
- psys->fluid_springs = NULL;
- }
+ MEM_SAFE_FREE(psys->fluid_springs);
psys->tot_fluidsprings = psys->alloc_fluidsprings = 0;
}
@@ -4516,10 +4510,7 @@ static void system_step(ParticleSimulationData *sim, float cfra, const bool use_
reset_all_particles(sim, 0.0, cfra, oldtotpart);
free_unexisting_particles(sim);
- if (psys->fluid_springs) {
- MEM_freeN(psys->fluid_springs);
- psys->fluid_springs = NULL;
- }
+ MEM_SAFE_FREE(psys->fluid_springs);
psys->tot_fluidsprings = psys->alloc_fluidsprings = 0;
@@ -4770,6 +4761,7 @@ static void particle_settings_free_local(ParticleSettings *particle_settings)
{
BKE_libblock_free_datablock(&particle_settings->id, 0);
BKE_libblock_free_data(&particle_settings->id, false);
+ BLI_assert(!particle_settings->id.py_instance); /* Or call #BKE_libblock_free_data_py. */
MEM_freeN(particle_settings);
}
diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c
index 9dab276af95..5ecd9b7283e 100644
--- a/source/blender/blenkernel/intern/scene.c
+++ b/source/blender/blenkernel/intern/scene.c
@@ -445,7 +445,8 @@ static void scene_free_data(ID *id)
* for objects directly in the master collection? then other
* collections in the scene need to do it too? */
if (scene->master_collection) {
- BKE_collection_free(scene->master_collection);
+ BKE_collection_free_data(scene->master_collection);
+ BKE_libblock_free_data_py(&scene->master_collection->id);
MEM_freeN(scene->master_collection);
scene->master_collection = NULL;
}
diff --git a/source/blender/blenkernel/intern/softbody.c b/source/blender/blenkernel/intern/softbody.c
index f41251f6ea5..fbc781f5eb9 100644
--- a/source/blender/blenkernel/intern/softbody.c
+++ b/source/blender/blenkernel/intern/softbody.c
@@ -891,11 +891,7 @@ static void free_softbody_baked(SoftBody *sb)
MEM_freeN(key);
}
}
- if (sb->keys) {
- MEM_freeN(sb->keys);
- }
-
- sb->keys = NULL;
+ MEM_SAFE_FREE(sb->keys);
sb->totkey = 0;
}
static void free_scratch(SoftBody *sb)
@@ -2281,7 +2277,7 @@ static void softbody_calc_forces(
float fieldfactor = -1.0f, windfactor = 0.25;
int do_deflector /*, do_selfcollision */, do_springcollision, do_aero;
- /* gravity = sb->grav * sb_grav_force_scale(ob); */ /* UNUSED */
+ // gravity = sb->grav * sb_grav_force_scale(ob); /* UNUSED */
/* check conditions for various options */
do_deflector = query_external_colliders(depsgraph, sb->collision_group);
@@ -2753,7 +2749,7 @@ static void mesh_to_softbody(Object *ob)
build_bps_springlist(ob); /* scan for springs attached to bodypoints ONCE */
/* insert *other second order* springs if desired */
if (sb->secondspring > 0.0000001f) {
- /* exploits the first run of build_bps_springlist(ob); */
+ /* Exploits the first run of `build_bps_springlist(ob)`. */
add_2nd_order_springs(ob, sb->secondspring);
/* yes we need to do it again. */
build_bps_springlist(ob);
diff --git a/source/blender/blenkernel/intern/text_suggestions.c b/source/blender/blenkernel/intern/text_suggestions.c
index d717b88e8ca..e93e969cb33 100644
--- a/source/blender/blenkernel/intern/text_suggestions.c
+++ b/source/blender/blenkernel/intern/text_suggestions.c
@@ -57,10 +57,7 @@ static void txttl_free_suggest(void)
static void txttl_free_docs(void)
{
- if (documentation) {
- MEM_freeN(documentation);
- documentation = NULL;
- }
+ MEM_SAFE_FREE(documentation);
}
/**************************/
@@ -240,10 +237,7 @@ void texttool_docs_show(const char *docs)
len = strlen(docs);
- if (documentation) {
- MEM_freeN(documentation);
- documentation = NULL;
- }
+ MEM_SAFE_FREE(documentation);
/* Ensure documentation ends with a '\n' */
if (docs[len - 1] != '\n') {
diff --git a/source/blender/blenkernel/intern/texture.c b/source/blender/blenkernel/intern/texture.c
index 29c41b88135..beb92495d16 100644
--- a/source/blender/blenkernel/intern/texture.c
+++ b/source/blender/blenkernel/intern/texture.c
@@ -490,9 +490,8 @@ void set_current_linestyle_texture(FreestyleLineStyle *linestyle, Tex *newtex)
linestyle->mtex[act]->tex = newtex;
id_us_plus(&newtex->id);
}
- else if (linestyle->mtex[act]) {
- MEM_freeN(linestyle->mtex[act]);
- linestyle->mtex[act] = NULL;
+ else {
+ MEM_SAFE_FREE(linestyle->mtex[act]);
}
}
@@ -595,9 +594,8 @@ void set_current_particle_texture(ParticleSettings *part, Tex *newtex)
part->mtex[act]->tex = newtex;
id_us_plus(&newtex->id);
}
- else if (part->mtex[act]) {
- MEM_freeN(part->mtex[act]);
- part->mtex[act] = NULL;
+ else {
+ MEM_SAFE_FREE(part->mtex[act]);
}
}
@@ -660,14 +658,8 @@ void BKE_texture_pointdensity_free_data(PointDensity *pd)
BLI_bvhtree_free(pd->point_tree);
pd->point_tree = NULL;
}
- if (pd->point_data) {
- MEM_freeN(pd->point_data);
- pd->point_data = NULL;
- }
- if (pd->coba) {
- MEM_freeN(pd->coba);
- pd->coba = NULL;
- }
+ MEM_SAFE_FREE(pd->point_data);
+ MEM_SAFE_FREE(pd->coba);
BKE_curvemapping_free(pd->falloff_curve); /* can be NULL */
}
diff --git a/source/blender/blenkernel/intern/workspace.c b/source/blender/blenkernel/intern/workspace.c
index 059dc68b1dc..329633c6759 100644
--- a/source/blender/blenkernel/intern/workspace.c
+++ b/source/blender/blenkernel/intern/workspace.c
@@ -58,7 +58,7 @@ static void workspace_init_data(ID *id)
{
WorkSpace *workspace = (WorkSpace *)id;
- BKE_asset_library_reference_init_default(&workspace->asset_library);
+ BKE_asset_library_reference_init_default(&workspace->asset_library_ref);
}
static void workspace_free_data(ID *id)
diff --git a/source/blender/blenlib/BLI_range.h b/source/blender/blenlib/BLI_range.h
index ad4cd6c162e..e55f443769d 100644
--- a/source/blender/blenlib/BLI_range.h
+++ b/source/blender/blenlib/BLI_range.h
@@ -29,6 +29,11 @@ typedef struct Range2f {
float max;
} Range2f;
+BLI_INLINE bool range2f_in_range(const Range2f *range, const float value)
+{
+ return IN_RANGE(value, range->min, range->max);
+}
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/blenlib/intern/math_vector_inline.c b/source/blender/blenlib/intern/math_vector_inline.c
index dddefd60b1b..ddfdaffb706 100644
--- a/source/blender/blenlib/intern/math_vector_inline.c
+++ b/source/blender/blenlib/intern/math_vector_inline.c
@@ -1145,6 +1145,9 @@ MINLINE float len_v3v3(const float a[3], const float b[3])
return len_v3(d);
}
+/**
+ * \note any vectors containing `nan` will be zeroed out.
+ */
MINLINE float normalize_v2_v2_length(float r[2], const float a[2], const float unit_length)
{
float d = dot_v2v2(a, a);
@@ -1154,6 +1157,7 @@ MINLINE float normalize_v2_v2_length(float r[2], const float a[2], const float u
mul_v2_v2fl(r, a, unit_length / d);
}
else {
+ /* Either the vector is small or one of it's values contained `nan`. */
zero_v2(r);
d = 0.0f;
}
@@ -1175,17 +1179,20 @@ MINLINE float normalize_v2_length(float n[2], const float unit_length)
return normalize_v2_v2_length(n, n, unit_length);
}
+/**
+ * \note any vectors containing `nan` will be zeroed out.
+ */
MINLINE float normalize_v3_v3_length(float r[3], const float a[3], const float unit_length)
{
float d = dot_v3v3(a, a);
- /* a larger value causes normalize errors in a
- * scaled down models with camera extreme close */
+ /* A larger value causes normalize errors in a scaled down models with camera extreme close. */
if (d > 1.0e-35f) {
d = sqrtf(d);
mul_v3_v3fl(r, a, unit_length / d);
}
else {
+ /* Either the vector is small or one of it's values contained `nan`. */
zero_v3(r);
d = 0.0f;
}
diff --git a/source/blender/blenloader/BLO_readfile.h b/source/blender/blenloader/BLO_readfile.h
index c3a33115613..dbdb181281a 100644
--- a/source/blender/blenloader/BLO_readfile.h
+++ b/source/blender/blenloader/BLO_readfile.h
@@ -118,6 +118,7 @@ typedef struct BlendFileReadReport {
/* Number of libraries which had overrides that needed to be resynced, and a single linked list
* of those. */
int resynced_lib_overrides_libraries_count;
+ bool do_resynced_lib_overrides_libraries_list;
struct LinkNode *resynced_lib_overrides_libraries;
} BlendFileReadReport;
diff --git a/source/blender/blenloader/intern/versioning_300.c b/source/blender/blenloader/intern/versioning_300.c
index 42af8f4bda2..cac607ed152 100644
--- a/source/blender/blenloader/intern/versioning_300.c
+++ b/source/blender/blenloader/intern/versioning_300.c
@@ -22,6 +22,7 @@
#include "BLI_listbase.h"
#include "BLI_math_vector.h"
+#include "BLI_path_util.h"
#include "BLI_string.h"
#include "BLI_utildefines.h"
@@ -657,12 +658,12 @@ void blo_do_versions_300(FileData *fd, Library *UNUSED(lib), Main *bmain)
if (!DNA_struct_elem_find(
fd->filesdna, "WorkSpace", "AssetLibraryReference", "asset_library")) {
LISTBASE_FOREACH (WorkSpace *, workspace, &bmain->workspaces) {
- BKE_asset_library_reference_init_default(&workspace->asset_library);
+ BKE_asset_library_reference_init_default(&workspace->asset_library_ref);
}
}
if (!DNA_struct_elem_find(
- fd->filesdna, "FileAssetSelectParams", "AssetLibraryReference", "asset_library")) {
+ fd->filesdna, "FileAssetSelectParams", "AssetLibraryReference", "asset_library_ref")) {
LISTBASE_FOREACH (bScreen *, screen, &bmain->screens) {
LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
LISTBASE_FOREACH (SpaceLink *, space, &area->spacedata) {
@@ -671,7 +672,7 @@ void blo_do_versions_300(FileData *fd, Library *UNUSED(lib), Main *bmain)
if (sfile->browse_mode != FILE_BROWSE_MODE_ASSETS) {
continue;
}
- BKE_asset_library_reference_init_default(&sfile->asset_params->asset_library);
+ BKE_asset_library_reference_init_default(&sfile->asset_params->asset_library_ref);
}
}
}
@@ -738,6 +739,43 @@ void blo_do_versions_300(FileData *fd, Library *UNUSED(lib), Main *bmain)
}
}
+ if (!MAIN_VERSION_ATLEAST(bmain, 300, 18)) {
+ if (!DNA_struct_elem_find(
+ fd->filesdna, "WorkSpace", "AssetLibraryReference", "asset_library_ref")) {
+ LISTBASE_FOREACH (WorkSpace *, workspace, &bmain->workspaces) {
+ BKE_asset_library_reference_init_default(&workspace->asset_library_ref);
+ }
+ }
+
+ if (!DNA_struct_elem_find(
+ fd->filesdna, "FileAssetSelectParams", "AssetLibraryReference", "asset_library_ref")) {
+ LISTBASE_FOREACH (bScreen *, screen, &bmain->screens) {
+ LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
+ LISTBASE_FOREACH (SpaceLink *, space, &area->spacedata) {
+ if (space->spacetype != SPACE_FILE) {
+ continue;
+ }
+
+ SpaceFile *sfile = (SpaceFile *)space;
+ if (sfile->browse_mode != FILE_BROWSE_MODE_ASSETS) {
+ continue;
+ }
+ BKE_asset_library_reference_init_default(&sfile->asset_params->asset_library_ref);
+ }
+ }
+ }
+ }
+
+ /* Previously, only text ending with `.py` would run, apply this logic
+ * to existing files so text that happens to have the "Register" enabled
+ * doesn't suddenly start running code on startup that was previously ignored. */
+ LISTBASE_FOREACH (Text *, text, &bmain->texts) {
+ if ((text->flags & TXT_ISSCRIPT) && !BLI_path_extension_check(text->id.name + 2, ".py")) {
+ text->flags &= ~TXT_ISSCRIPT;
+ }
+ }
+ }
+
/**
* Versioning code until next subversion bump goes here.
*
diff --git a/source/blender/blenloader/intern/versioning_userdef.c b/source/blender/blenloader/intern/versioning_userdef.c
index c409f0a71fc..0042ff29dc2 100644
--- a/source/blender/blenloader/intern/versioning_userdef.c
+++ b/source/blender/blenloader/intern/versioning_userdef.c
@@ -873,13 +873,6 @@ void blo_do_versions_userdef(UserDef *userdef)
}
}
- if (!USER_VERSION_ATLEAST(293, 2)) {
- /* Enable asset browser features by default for alpha testing.
- * BLO_sanitize_experimental_features_userpref_blend() will disable it again for non-alpha
- * builds. */
- userdef->experimental.use_asset_browser = true;
- }
-
if (!USER_VERSION_ATLEAST(293, 12)) {
if (userdef->gizmo_size_navigate_v3d == 0) {
userdef->gizmo_size_navigate_v3d = 80;
diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c
index 12839a155e4..225548f3832 100644
--- a/source/blender/blenloader/intern/writefile.c
+++ b/source/blender/blenloader/intern/writefile.c
@@ -757,8 +757,8 @@ static void write_userdef(BlendWriter *writer, const UserDef *userdef)
BLO_write_struct(writer, bPathCompare, path_cmp);
}
- LISTBASE_FOREACH (const bUserAssetLibrary *, asset_library, &userdef->asset_libraries) {
- BLO_write_struct(writer, bUserAssetLibrary, asset_library);
+ LISTBASE_FOREACH (const bUserAssetLibrary *, asset_library_ref, &userdef->asset_libraries) {
+ BLO_write_struct(writer, bUserAssetLibrary, asset_library_ref);
}
LISTBASE_FOREACH (const uiStyle *, style, &userdef->uistyles) {
diff --git a/source/blender/blentranslation/intern/blt_lang.c b/source/blender/blentranslation/intern/blt_lang.c
index 97a1a83792a..91e8a81aec0 100644
--- a/source/blender/blentranslation/intern/blt_lang.c
+++ b/source/blender/blentranslation/intern/blt_lang.c
@@ -74,10 +74,7 @@ static void free_locales(void)
MEM_freeN((void *)locales);
locales = NULL;
}
- if (locales_menu) {
- MEM_freeN(locales_menu);
- locales_menu = NULL;
- }
+ MEM_SAFE_FREE(locales_menu);
num_locales = num_locales_menu = 0;
}
diff --git a/source/blender/bmesh/intern/bmesh_mesh_normals.c b/source/blender/bmesh/intern/bmesh_mesh_normals.c
index 8eda38046a1..a5e41b74ee1 100644
--- a/source/blender/bmesh/intern/bmesh_mesh_normals.c
+++ b/source/blender/bmesh/intern/bmesh_mesh_normals.c
@@ -1116,8 +1116,6 @@ static void bm_mesh_loops_calc_normals__single_threaded(BMesh *bm,
BMIter fiter;
BMFace *f_curr;
const bool has_clnors = clnors_data || (cd_loop_clnors_offset != -1);
- const bool check_angle = (split_angle < (float)M_PI);
- const float split_angle_cos = check_angle ? cosf(split_angle) : -1.0f;
MLoopNorSpaceArray _lnors_spacearr = {NULL};
@@ -1152,16 +1150,13 @@ static void bm_mesh_loops_calc_normals__single_threaded(BMesh *bm,
do {
BM_elem_index_set(l_curr, index_loop++); /* set_inline */
BM_elem_flag_disable(l_curr, BM_ELEM_TAG);
- /* Needed for when #bm_mesh_edges_sharp_tag doesn't run.
- * Mark smooth if there is no smoothing angle. */
- BM_elem_flag_enable(l_curr->e, BM_ELEM_TAG);
} while ((l_curr = l_curr->next) != l_first);
}
bm->elem_index_dirty &= ~(BM_FACE | BM_LOOP);
- if (split_angle_cos != -1.0f) {
- bm_mesh_edges_sharp_tag(bm, fnos, has_clnors ? (float)M_PI : split_angle, false);
- }
+ /* Always tag edges based on winding & sharp edge flag
+ * (even when the auto-smooth angle doesn't need to be calculated). */
+ bm_mesh_edges_sharp_tag(bm, fnos, has_clnors ? (float)M_PI : split_angle, false);
/* We now know edges that can be smoothed (they are tagged),
* and edges that will be hard (they aren't).
diff --git a/source/blender/compositor/COM_defines.h b/source/blender/compositor/COM_defines.h
index 900f29db44c..40a1e0da2a8 100644
--- a/source/blender/compositor/COM_defines.h
+++ b/source/blender/compositor/COM_defines.h
@@ -62,12 +62,18 @@ constexpr int COM_data_type_num_channels(const DataType datatype)
}
}
+constexpr int COM_data_type_bytes_len(DataType data_type)
+{
+ return COM_data_type_num_channels(data_type) * sizeof(float);
+}
+
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_COLOR_TRANSPARENT[4] = {0.0f, 0.0f, 0.0f, 0.0f};
constexpr float COM_VECTOR_ZERO[3] = {0.0f, 0.0f, 0.0f};
+constexpr float COM_COLOR_BLACK[4] = {0.0f, 0.0f, 0.0f, 1.0f};
constexpr float COM_VALUE_ZERO[1] = {0.0f};
constexpr float COM_VALUE_ONE[1] = {1.0f};
diff --git a/source/blender/compositor/intern/COM_BufferOperation.cc b/source/blender/compositor/intern/COM_BufferOperation.cc
index 90c97f2a9c7..cafdff89c8e 100644
--- a/source/blender/compositor/intern/COM_BufferOperation.cc
+++ b/source/blender/compositor/intern/COM_BufferOperation.cc
@@ -32,6 +32,7 @@ BufferOperation::BufferOperation(MemoryBuffer *buffer, DataType data_type)
setResolution(resolution);
addOutputSocket(data_type);
flags.is_constant_operation = buffer_->is_a_single_elem();
+ flags.is_fullframe_operation = false;
}
const float *BufferOperation::get_constant_elem()
@@ -40,20 +41,32 @@ const float *BufferOperation::get_constant_elem()
return buffer_->getBuffer();
}
+void BufferOperation::initExecution()
+{
+ if (buffer_->is_a_single_elem()) {
+ initMutex();
+ }
+}
+
void *BufferOperation::initializeTileData(rcti * /*rect*/)
{
if (buffer_->is_a_single_elem() == false) {
return buffer_;
}
+ lockMutex();
if (!inflated_buffer_) {
inflated_buffer_ = buffer_->inflate();
}
+ unlockMutex();
return inflated_buffer_;
}
void BufferOperation::deinitExecution()
{
+ if (buffer_->is_a_single_elem()) {
+ deinitMutex();
+ }
delete inflated_buffer_;
}
diff --git a/source/blender/compositor/intern/COM_BufferOperation.h b/source/blender/compositor/intern/COM_BufferOperation.h
index 705264c37b7..b4cbc0a56b6 100644
--- a/source/blender/compositor/intern/COM_BufferOperation.h
+++ b/source/blender/compositor/intern/COM_BufferOperation.h
@@ -32,6 +32,7 @@ class BufferOperation : public ConstantOperation {
const float *get_constant_elem() override;
void *initializeTileData(rcti *rect) override;
+ void initExecution() 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_ConstantFolder.cc b/source/blender/compositor/intern/COM_ConstantFolder.cc
index 5b48ff8fc08..445a9ce7433 100644
--- a/source/blender/compositor/intern/COM_ConstantFolder.cc
+++ b/source/blender/compositor/intern/COM_ConstantFolder.cc
@@ -44,7 +44,9 @@ 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) {
+ NodeOperation *input = operation->get_input_operation(i);
+ if (!input->get_flags().is_constant_operation ||
+ !static_cast<ConstantOperation *>(input)->can_get_constant_elem()) {
return false;
}
}
diff --git a/source/blender/compositor/intern/COM_Debug.cc b/source/blender/compositor/intern/COM_Debug.cc
index 5443974cbb0..a0333cf96cf 100644
--- a/source/blender/compositor/intern/COM_Debug.cc
+++ b/source/blender/compositor/intern/COM_Debug.cc
@@ -178,21 +178,27 @@ 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:
- if (typeid(*operation) == typeid(SetValueOperation)) {
- const float value = ((SetValueOperation *)operation)->getValue();
+ case DataType::Value: {
+ ConstantOperation *constant = operation->get_flags().is_constant_operation ?
+ static_cast<ConstantOperation *>(operation) :
+ nullptr;
+ if (constant && constant->can_get_constant_elem()) {
+ const float value = *constant->get_constant_elem();
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:
+ }
+ case DataType::Vector: {
len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "Vector");
break;
- case DataType::Color:
+ }
+ case DataType::Color: {
len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "Color");
break;
+ }
}
}
len += snprintf(str + len, maxlen > len ? maxlen - len : 0, "}");
diff --git a/source/blender/compositor/intern/COM_MemoryBuffer.h b/source/blender/compositor/intern/COM_MemoryBuffer.h
index ae12c444dc1..310e87b6a4b 100644
--- a/source/blender/compositor/intern/COM_MemoryBuffer.h
+++ b/source/blender/compositor/intern/COM_MemoryBuffer.h
@@ -260,6 +260,11 @@ class MemoryBuffer {
return this->m_num_channels;
}
+ uint8_t get_elem_bytes_len() const
+ {
+ return this->m_num_channels * sizeof(float);
+ }
+
/**
* Get all buffer elements as a range with no offsets.
*/
diff --git a/source/blender/compositor/intern/COM_TiledExecutionModel.cc b/source/blender/compositor/intern/COM_TiledExecutionModel.cc
index d025ce53330..a081b80349d 100644
--- a/source/blender/compositor/intern/COM_TiledExecutionModel.cc
+++ b/source/blender/compositor/intern/COM_TiledExecutionModel.cc
@@ -45,7 +45,7 @@ TiledExecutionModel::TiledExecutionModel(CompositorContext &context,
group->determineResolution(resolution);
if (border_.use_render_border) {
- const rctf *render_border = border_.viewer_border;
+ const rctf *render_border = border_.render_border;
group->setRenderBorder(
render_border->xmin, render_border->xmax, render_border->ymin, render_border->ymax);
}
diff --git a/source/blender/compositor/operations/COM_AlphaOverKeyOperation.cc b/source/blender/compositor/operations/COM_AlphaOverKeyOperation.cc
index 0c656753a51..30e7fab4027 100644
--- a/source/blender/compositor/operations/COM_AlphaOverKeyOperation.cc
+++ b/source/blender/compositor/operations/COM_AlphaOverKeyOperation.cc
@@ -20,6 +20,11 @@
namespace blender::compositor {
+AlphaOverKeyOperation::AlphaOverKeyOperation()
+{
+ this->flags.can_be_constant = true;
+}
+
void AlphaOverKeyOperation::executePixelSampled(float output[4],
float x,
float y,
@@ -50,4 +55,29 @@ void AlphaOverKeyOperation::executePixelSampled(float output[4],
}
}
+void AlphaOverKeyOperation::update_memory_buffer_row(PixelCursor &p)
+{
+ for (; p.out < p.row_end; p.next()) {
+ const float *color1 = p.color1;
+ const float *over_color = p.color2;
+ const float value = *p.value;
+
+ if (over_color[3] <= 0.0f) {
+ copy_v4_v4(p.out, color1);
+ }
+ else if (value == 1.0f && over_color[3] >= 1.0f) {
+ copy_v4_v4(p.out, over_color);
+ }
+ else {
+ const float premul = value * over_color[3];
+ const float mul = 1.0f - premul;
+
+ p.out[0] = (mul * color1[0]) + premul * over_color[0];
+ p.out[1] = (mul * color1[1]) + premul * over_color[1];
+ p.out[2] = (mul * color1[2]) + premul * over_color[2];
+ p.out[3] = (mul * color1[3]) + value * over_color[3];
+ }
+ }
+}
+
} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_AlphaOverKeyOperation.h b/source/blender/compositor/operations/COM_AlphaOverKeyOperation.h
index 83713d18971..960fbc98fe9 100644
--- a/source/blender/compositor/operations/COM_AlphaOverKeyOperation.h
+++ b/source/blender/compositor/operations/COM_AlphaOverKeyOperation.h
@@ -28,10 +28,14 @@ namespace blender::compositor {
*/
class AlphaOverKeyOperation : public MixBaseOperation {
public:
+ AlphaOverKeyOperation();
+
/**
* The inner loop of this operation.
*/
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
+
+ void update_memory_buffer_row(PixelCursor &p) override;
};
} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_AlphaOverMixedOperation.cc b/source/blender/compositor/operations/COM_AlphaOverMixedOperation.cc
index c68c79d2263..0cc179ea209 100644
--- a/source/blender/compositor/operations/COM_AlphaOverMixedOperation.cc
+++ b/source/blender/compositor/operations/COM_AlphaOverMixedOperation.cc
@@ -23,6 +23,7 @@ namespace blender::compositor {
AlphaOverMixedOperation::AlphaOverMixedOperation()
{
this->m_x = 0.0f;
+ this->flags.can_be_constant = true;
}
void AlphaOverMixedOperation::executePixelSampled(float output[4],
@@ -56,4 +57,30 @@ void AlphaOverMixedOperation::executePixelSampled(float output[4],
}
}
+void AlphaOverMixedOperation::update_memory_buffer_row(PixelCursor &p)
+{
+ for (; p.out < p.row_end; p.next()) {
+ const float *color1 = p.color1;
+ const float *over_color = p.color2;
+ const float value = *p.value;
+
+ if (over_color[3] <= 0.0f) {
+ copy_v4_v4(p.out, color1);
+ }
+ else if (value == 1.0f && over_color[3] >= 1.0f) {
+ copy_v4_v4(p.out, over_color);
+ }
+ else {
+ const float addfac = 1.0f - this->m_x + over_color[3] * this->m_x;
+ const float premul = value * addfac;
+ const float mul = 1.0f - value * over_color[3];
+
+ p.out[0] = (mul * color1[0]) + premul * over_color[0];
+ p.out[1] = (mul * color1[1]) + premul * over_color[1];
+ p.out[2] = (mul * color1[2]) + premul * over_color[2];
+ p.out[3] = (mul * color1[3]) + value * over_color[3];
+ }
+ }
+}
+
} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_AlphaOverMixedOperation.h b/source/blender/compositor/operations/COM_AlphaOverMixedOperation.h
index e2b3af84162..2b88cd5f421 100644
--- a/source/blender/compositor/operations/COM_AlphaOverMixedOperation.h
+++ b/source/blender/compositor/operations/COM_AlphaOverMixedOperation.h
@@ -45,6 +45,8 @@ class AlphaOverMixedOperation : public MixBaseOperation {
{
this->m_x = x;
}
+
+ void update_memory_buffer_row(PixelCursor &p) override;
};
} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_AlphaOverPremultiplyOperation.cc b/source/blender/compositor/operations/COM_AlphaOverPremultiplyOperation.cc
index 3dd4607e273..a57e8c7f8a3 100644
--- a/source/blender/compositor/operations/COM_AlphaOverPremultiplyOperation.cc
+++ b/source/blender/compositor/operations/COM_AlphaOverPremultiplyOperation.cc
@@ -20,6 +20,11 @@
namespace blender::compositor {
+AlphaOverPremultiplyOperation::AlphaOverPremultiplyOperation()
+{
+ this->flags.can_be_constant = true;
+}
+
void AlphaOverPremultiplyOperation::executePixelSampled(float output[4],
float x,
float y,
@@ -50,4 +55,28 @@ void AlphaOverPremultiplyOperation::executePixelSampled(float output[4],
}
}
+void AlphaOverPremultiplyOperation::update_memory_buffer_row(PixelCursor &p)
+{
+ for (; p.out < p.row_end; p.next()) {
+ const float *color1 = p.color1;
+ const float *over_color = p.color2;
+ const float value = *p.value;
+
+ if (over_color[3] <= 0.0f) {
+ copy_v4_v4(p.out, color1);
+ }
+ else if (value == 1.0f && over_color[3] >= 1.0f) {
+ copy_v4_v4(p.out, over_color);
+ }
+ else {
+ const float mul = 1.0f - value * over_color[3];
+
+ p.out[0] = (mul * color1[0]) + value * over_color[0];
+ p.out[1] = (mul * color1[1]) + value * over_color[1];
+ p.out[2] = (mul * color1[2]) + value * over_color[2];
+ p.out[3] = (mul * color1[3]) + value * over_color[3];
+ }
+ }
+}
+
} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_AlphaOverPremultiplyOperation.h b/source/blender/compositor/operations/COM_AlphaOverPremultiplyOperation.h
index f1d4b668fce..701bc07cc27 100644
--- a/source/blender/compositor/operations/COM_AlphaOverPremultiplyOperation.h
+++ b/source/blender/compositor/operations/COM_AlphaOverPremultiplyOperation.h
@@ -28,10 +28,14 @@ namespace blender::compositor {
*/
class AlphaOverPremultiplyOperation : public MixBaseOperation {
public:
+ AlphaOverPremultiplyOperation();
+
/**
* The inner loop of this operation.
*/
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
+
+ void update_memory_buffer_row(PixelCursor &p) override;
};
} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_BilateralBlurOperation.cc b/source/blender/compositor/operations/COM_BilateralBlurOperation.cc
index 64448e2ae95..0c1bb688d4e 100644
--- a/source/blender/compositor/operations/COM_BilateralBlurOperation.cc
+++ b/source/blender/compositor/operations/COM_BilateralBlurOperation.cc
@@ -38,7 +38,6 @@ void BilateralBlurOperation::initExecution()
{
this->m_inputColorProgram = getInputSocketReader(0);
this->m_inputDeterminatorProgram = getInputSocketReader(1);
- this->m_space = this->m_data->sigma_space + this->m_data->iter;
QualityStepHelper::initExecution(COM_QH_INCREASE);
}
@@ -115,4 +114,89 @@ bool BilateralBlurOperation::determineDependingAreaOfInterest(rcti *input,
return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output);
}
+void BilateralBlurOperation::get_area_of_interest(const int UNUSED(input_idx),
+ const rcti &output_area,
+ rcti &r_input_area)
+{
+ const int add = ceil(this->m_space) + 1;
+
+ r_input_area.xmax = output_area.xmax + (add);
+ r_input_area.xmin = output_area.xmin - (add);
+ r_input_area.ymax = output_area.ymax + (add);
+ r_input_area.ymin = output_area.ymin - (add);
+}
+
+struct PixelCursor {
+ MemoryBuffer *input_determinator;
+ MemoryBuffer *input_color;
+ int step;
+ float sigma_color;
+ const float *determ_reference_color;
+ float temp_color[4];
+ float *out;
+ int min_x, max_x;
+ int min_y, max_y;
+};
+
+static void blur_pixel(PixelCursor &p)
+{
+ float blur_divider = 0.0f;
+ zero_v4(p.out);
+
+ /* TODO(sergey): This isn't really good bilateral filter, it should be
+ * using gaussian bell for weights. Also sigma_color doesn't seem to be
+ * used correct at all.
+ */
+ for (int yi = p.min_y; yi < p.max_y; yi += p.step) {
+ for (int xi = p.min_x; xi < p.max_x; xi += p.step) {
+ p.input_determinator->read(p.temp_color, xi, yi);
+ /* Do not take the alpha channel into account. */
+ const float delta_color = (fabsf(p.determ_reference_color[0] - p.temp_color[0]) +
+ fabsf(p.determ_reference_color[1] - p.temp_color[1]) +
+ fabsf(p.determ_reference_color[2] - p.temp_color[2]));
+ if (delta_color < p.sigma_color) {
+ /* Add this to the blur. */
+ p.input_color->read(p.temp_color, xi, yi);
+ add_v4_v4(p.out, p.temp_color);
+ blur_divider += 1.0f;
+ }
+ }
+ }
+
+ if (blur_divider > 0.0f) {
+ mul_v4_fl(p.out, 1.0f / blur_divider);
+ }
+ else {
+ copy_v4_v4(p.out, COM_COLOR_BLACK);
+ }
+}
+
+void BilateralBlurOperation::update_memory_buffer_partial(MemoryBuffer *output,
+ const rcti &area,
+ Span<MemoryBuffer *> inputs)
+{
+ PixelCursor p = {};
+ p.step = QualityStepHelper::getStep();
+ p.sigma_color = this->m_data->sigma_color;
+ p.input_color = inputs[0];
+ p.input_determinator = inputs[1];
+ const float space = this->m_space;
+ for (int y = area.ymin; y < area.ymax; y++) {
+ p.out = output->get_elem(area.xmin, y);
+ /* This will be used as the reference color for the determinator. */
+ p.determ_reference_color = p.input_determinator->get_elem(area.xmin, y);
+ p.min_y = floor(y - space);
+ p.max_y = ceil(y + space);
+ for (int x = area.xmin; x < area.xmax; x++) {
+ p.min_x = floor(x - space);
+ p.max_x = ceil(x + space);
+
+ blur_pixel(p);
+
+ p.determ_reference_color += p.input_determinator->elem_stride;
+ p.out += output->elem_stride;
+ }
+ }
+}
+
} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_BilateralBlurOperation.h b/source/blender/compositor/operations/COM_BilateralBlurOperation.h
index c56cef35050..517c5292827 100644
--- a/source/blender/compositor/operations/COM_BilateralBlurOperation.h
+++ b/source/blender/compositor/operations/COM_BilateralBlurOperation.h
@@ -18,12 +18,12 @@
#pragma once
-#include "COM_NodeOperation.h"
+#include "COM_MultiThreadedOperation.h"
#include "COM_QualityStepHelper.h"
namespace blender::compositor {
-class BilateralBlurOperation : public NodeOperation, public QualityStepHelper {
+class BilateralBlurOperation : public MultiThreadedOperation, public QualityStepHelper {
private:
SocketReader *m_inputColorProgram;
SocketReader *m_inputDeterminatorProgram;
@@ -55,7 +55,14 @@ class BilateralBlurOperation : public NodeOperation, public QualityStepHelper {
void setData(NodeBilateralBlurData *data)
{
this->m_data = data;
+ this->m_space = data->sigma_space + data->iter;
}
+
+ 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_BokehImageOperation.cc b/source/blender/compositor/operations/COM_BokehImageOperation.cc
index 63f283b6acc..bd5b25b5af8 100644
--- a/source/blender/compositor/operations/COM_BokehImageOperation.cc
+++ b/source/blender/compositor/operations/COM_BokehImageOperation.cc
@@ -110,6 +110,31 @@ void BokehImageOperation::executePixelSampled(float output[4],
output[3] = (insideBokehMax + insideBokehMed + insideBokehMin) / 3.0f;
}
+void BokehImageOperation::update_memory_buffer_partial(MemoryBuffer *output,
+ const rcti &area,
+ Span<MemoryBuffer *> UNUSED(inputs))
+{
+ const float shift = this->m_data->lensshift;
+ const float shift2 = shift / 2.0f;
+ const float distance = this->m_circularDistance;
+ for (BuffersIterator<float> it = output->iterate_with({}, area); !it.is_end(); ++it) {
+ const float insideBokehMax = isInsideBokeh(distance, it.x, it.y);
+ const float insideBokehMed = isInsideBokeh(distance - fabsf(shift2 * distance), it.x, it.y);
+ const float insideBokehMin = isInsideBokeh(distance - fabsf(shift * distance), it.x, it.y);
+ if (shift < 0) {
+ it.out[0] = insideBokehMax;
+ it.out[1] = insideBokehMed;
+ it.out[2] = insideBokehMin;
+ }
+ else {
+ it.out[0] = insideBokehMin;
+ it.out[1] = insideBokehMed;
+ it.out[2] = insideBokehMax;
+ }
+ it.out[3] = (insideBokehMax + insideBokehMed + insideBokehMin) / 3.0f;
+ }
+}
+
void BokehImageOperation::deinitExecution()
{
if (this->m_deleteData) {
diff --git a/source/blender/compositor/operations/COM_BokehImageOperation.h b/source/blender/compositor/operations/COM_BokehImageOperation.h
index 2e0bc8a34dc..2527233fabd 100644
--- a/source/blender/compositor/operations/COM_BokehImageOperation.h
+++ b/source/blender/compositor/operations/COM_BokehImageOperation.h
@@ -18,7 +18,7 @@
#pragma once
-#include "COM_NodeOperation.h"
+#include "COM_MultiThreadedOperation.h"
namespace blender::compositor {
@@ -49,7 +49,7 @@ namespace blender::compositor {
* With a simple compare it can be detected if the evaluated pixel is between the outer and inner
*edge.
*/
-class BokehImageOperation : public NodeOperation {
+class BokehImageOperation : public MultiThreadedOperation {
private:
/**
* \brief Settings of the bokeh image
@@ -151,6 +151,10 @@ class BokehImageOperation : public NodeOperation {
{
this->m_deleteData = true;
}
+
+ 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_ChangeHSVOperation.cc b/source/blender/compositor/operations/COM_ChangeHSVOperation.cc
index eee007ce9e6..1e3e7806968 100644
--- a/source/blender/compositor/operations/COM_ChangeHSVOperation.cc
+++ b/source/blender/compositor/operations/COM_ChangeHSVOperation.cc
@@ -28,6 +28,7 @@ ChangeHSVOperation::ChangeHSVOperation()
this->addInputSocket(DataType::Value);
this->addOutputSocket(DataType::Color);
this->m_inputOperation = nullptr;
+ this->flags.can_be_constant = true;
}
void ChangeHSVOperation::initExecution()
@@ -71,4 +72,26 @@ void ChangeHSVOperation::executePixelSampled(float output[4],
output[3] = inputColor1[3];
}
+void ChangeHSVOperation::update_memory_buffer_partial(MemoryBuffer *output,
+ const rcti &area,
+ Span<MemoryBuffer *> inputs)
+{
+ for (BuffersIterator<float> it = output->iterate_with(inputs, area); !it.is_end(); ++it) {
+ const float *color = it.in(0);
+ const float hue = *it.in(1);
+ it.out[0] = color[0] + (hue - 0.5f);
+ if (it.out[0] > 1.0f) {
+ it.out[0] -= 1.0f;
+ }
+ else if (it.out[0] < 0.0f) {
+ it.out[0] += 1.0f;
+ }
+ const float saturation = *it.in(2);
+ const float value = *it.in(3);
+ it.out[1] = color[1] * saturation;
+ it.out[2] = color[2] * value;
+ it.out[3] = color[3];
+ }
+}
+
} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_ChangeHSVOperation.h b/source/blender/compositor/operations/COM_ChangeHSVOperation.h
index d38b4be3efe..e7bc3274f25 100644
--- a/source/blender/compositor/operations/COM_ChangeHSVOperation.h
+++ b/source/blender/compositor/operations/COM_ChangeHSVOperation.h
@@ -18,7 +18,7 @@
#pragma once
-#include "COM_MixOperation.h"
+#include "COM_MultiThreadedOperation.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 ChangeHSVOperation : public NodeOperation {
+class ChangeHSVOperation : public MultiThreadedOperation {
private:
SocketReader *m_inputOperation;
SocketReader *m_hueOperation;
@@ -46,6 +46,10 @@ class ChangeHSVOperation : public NodeOperation {
* The inner loop of this operation.
*/
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_ColorCurveOperation.cc b/source/blender/compositor/operations/COM_ColorCurveOperation.cc
index cb0565a81a2..1b7ad0ea608 100644
--- a/source/blender/compositor/operations/COM_ColorCurveOperation.cc
+++ b/source/blender/compositor/operations/COM_ColorCurveOperation.cc
@@ -98,6 +98,36 @@ void ColorCurveOperation::deinitExecution()
this->m_inputWhiteProgram = nullptr;
}
+void ColorCurveOperation::update_memory_buffer_partial(MemoryBuffer *output,
+ const rcti &area,
+ Span<MemoryBuffer *> inputs)
+{
+ CurveMapping *cumap = this->m_curveMapping;
+ float bwmul[3];
+ for (BuffersIterator<float> it = output->iterate_with(inputs, area); !it.is_end(); ++it) {
+ /* Local versions of `cumap->black` and `cumap->white`. */
+ const float *black = it.in(2);
+ const float *white = it.in(3);
+ /* Get a local `bwmul` value, it's not threadsafe using `cumap->bwmul` and others. */
+ BKE_curvemapping_set_black_white_ex(black, white, bwmul);
+
+ const float fac = *it.in(0);
+ const float *image = it.in(1);
+ if (fac >= 1.0f) {
+ BKE_curvemapping_evaluate_premulRGBF_ex(cumap, it.out, image, black, bwmul);
+ }
+ else if (fac <= 0.0f) {
+ copy_v3_v3(it.out, image);
+ }
+ else {
+ float col[4];
+ BKE_curvemapping_evaluate_premulRGBF_ex(cumap, col, image, black, bwmul);
+ interp_v3_v3v3(it.out, image, col, fac);
+ }
+ it.out[3] = image[3];
+ }
+}
+
// Constant level curve mapping
ConstantLevelColorCurveOperation::ConstantLevelColorCurveOperation()
@@ -154,4 +184,27 @@ void ConstantLevelColorCurveOperation::deinitExecution()
this->m_inputImageProgram = nullptr;
}
+void ConstantLevelColorCurveOperation::update_memory_buffer_partial(MemoryBuffer *output,
+ const rcti &area,
+ Span<MemoryBuffer *> inputs)
+{
+ CurveMapping *cumap = this->m_curveMapping;
+ for (BuffersIterator<float> it = output->iterate_with(inputs, area); !it.is_end(); ++it) {
+ const float fac = *it.in(0);
+ const float *image = it.in(1);
+ if (fac >= 1.0f) {
+ BKE_curvemapping_evaluate_premulRGBF(cumap, it.out, image);
+ }
+ else if (fac <= 0.0f) {
+ copy_v3_v3(it.out, image);
+ }
+ else {
+ float col[4];
+ BKE_curvemapping_evaluate_premulRGBF(cumap, col, image);
+ interp_v3_v3v3(it.out, image, col, fac);
+ }
+ it.out[3] = image[3];
+ }
+}
+
} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_ColorCurveOperation.h b/source/blender/compositor/operations/COM_ColorCurveOperation.h
index 6fc7759b8d2..d8271e56d1d 100644
--- a/source/blender/compositor/operations/COM_ColorCurveOperation.h
+++ b/source/blender/compositor/operations/COM_ColorCurveOperation.h
@@ -51,6 +51,10 @@ class ColorCurveOperation : public CurveBaseOperation {
* Deinitialize the execution
*/
void deinitExecution() override;
+
+ void update_memory_buffer_partial(MemoryBuffer *output,
+ const rcti &area,
+ Span<MemoryBuffer *> inputs) override;
};
class ConstantLevelColorCurveOperation : public CurveBaseOperation {
@@ -89,6 +93,10 @@ class ConstantLevelColorCurveOperation : public CurveBaseOperation {
{
copy_v3_v3(this->m_white, white);
}
+
+ 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_CompositorOperation.cc b/source/blender/compositor/operations/COM_CompositorOperation.cc
index 94d41b28f5d..8752d764107 100644
--- a/source/blender/compositor/operations/COM_CompositorOperation.cc
+++ b/source/blender/compositor/operations/COM_CompositorOperation.cc
@@ -220,6 +220,22 @@ void CompositorOperation::executeRegion(rcti *rect, unsigned int /*tileNumber*/)
}
}
+void CompositorOperation::update_memory_buffer_partial(MemoryBuffer *UNUSED(output),
+ const rcti &area,
+ Span<MemoryBuffer *> inputs)
+{
+ if (!m_outputBuffer) {
+ return;
+ }
+ MemoryBuffer output_buf(m_outputBuffer, COM_DATA_TYPE_COLOR_CHANNELS, getWidth(), getHeight());
+ output_buf.copy_from(inputs[0], area);
+ if (this->m_useAlphaInput) {
+ output_buf.copy_from(inputs[1], area, 0, COM_DATA_TYPE_VALUE_CHANNELS, 3);
+ }
+ MemoryBuffer depth_buf(m_depthBuffer, COM_DATA_TYPE_VALUE_CHANNELS, getWidth(), getHeight());
+ depth_buf.copy_from(inputs[2], area);
+}
+
void CompositorOperation::determineResolution(unsigned int resolution[2],
unsigned int preferredResolution[2])
{
diff --git a/source/blender/compositor/operations/COM_CompositorOperation.h b/source/blender/compositor/operations/COM_CompositorOperation.h
index 65988c86cc5..66367ec8bae 100644
--- a/source/blender/compositor/operations/COM_CompositorOperation.h
+++ b/source/blender/compositor/operations/COM_CompositorOperation.h
@@ -20,7 +20,7 @@
#include "BLI_rect.h"
#include "BLI_string.h"
-#include "COM_NodeOperation.h"
+#include "COM_MultiThreadedOperation.h"
struct Scene;
@@ -29,7 +29,7 @@ namespace blender::compositor {
/**
* \brief Compositor output operation
*/
-class CompositorOperation : public NodeOperation {
+class CompositorOperation : public MultiThreadedOperation {
private:
const struct Scene *m_scene;
/**
@@ -125,6 +125,10 @@ class CompositorOperation : public NodeOperation {
{
this->m_active = active;
}
+
+ 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_ConstantOperation.cc b/source/blender/compositor/operations/COM_ConstantOperation.cc
index f905edbde76..33d51cca432 100644
--- a/source/blender/compositor/operations/COM_ConstantOperation.cc
+++ b/source/blender/compositor/operations/COM_ConstantOperation.cc
@@ -22,7 +22,24 @@ namespace blender::compositor {
ConstantOperation::ConstantOperation()
{
+ needs_resolution_to_get_constant_ = false;
flags.is_constant_operation = true;
+ flags.is_fullframe_operation = true;
+}
+
+bool ConstantOperation::can_get_constant_elem() const
+{
+ return !needs_resolution_to_get_constant_ || this->flags.is_resolution_set;
+}
+
+void ConstantOperation::update_memory_buffer(MemoryBuffer *output,
+ const rcti &area,
+ Span<MemoryBuffer *> UNUSED(inputs))
+{
+ BLI_assert(output->is_a_single_elem());
+ const float *constant = get_constant_elem();
+ float *out = output->get_elem(area.xmin, area.ymin);
+ memcpy(out, constant, output->get_elem_bytes_len());
}
} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_ConstantOperation.h b/source/blender/compositor/operations/COM_ConstantOperation.h
index 2709efeebd8..31b8d30254b 100644
--- a/source/blender/compositor/operations/COM_ConstantOperation.h
+++ b/source/blender/compositor/operations/COM_ConstantOperation.h
@@ -22,15 +22,27 @@
namespace blender::compositor {
+/* TODO(manzanilla): After removing tiled implementation, implement a default #determineResolution
+ * for all constant operations and make all initialization and deinitilization methods final. */
/**
- * Base class for primitive constant operations (Color/Vector/Value). The rest of operations that
- * can be constant are evaluated into primitives during constant folding.
+ * Base class for operations that are always constant. Operations that can be constant only when
+ * all their inputs are so, are evaluated into primitive constants (Color/Vector/Value) during
+ * constant folding.
*/
class ConstantOperation : public NodeOperation {
+ protected:
+ bool needs_resolution_to_get_constant_;
+
public:
ConstantOperation();
+ /** May require resolution to be already determined. */
virtual const float *get_constant_elem() = 0;
+ bool can_get_constant_elem() const;
+
+ void update_memory_buffer(MemoryBuffer *output,
+ const rcti &area,
+ Span<MemoryBuffer *> inputs) final;
};
} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_CurveBaseOperation.cc b/source/blender/compositor/operations/COM_CurveBaseOperation.cc
index 8f655964570..3c4b27aa4cf 100644
--- a/source/blender/compositor/operations/COM_CurveBaseOperation.cc
+++ b/source/blender/compositor/operations/COM_CurveBaseOperation.cc
@@ -25,6 +25,7 @@ namespace blender::compositor {
CurveBaseOperation::CurveBaseOperation()
{
this->m_curveMapping = nullptr;
+ this->flags.can_be_constant = true;
}
CurveBaseOperation::~CurveBaseOperation()
diff --git a/source/blender/compositor/operations/COM_CurveBaseOperation.h b/source/blender/compositor/operations/COM_CurveBaseOperation.h
index fff0f3168ba..da665e7ea60 100644
--- a/source/blender/compositor/operations/COM_CurveBaseOperation.h
+++ b/source/blender/compositor/operations/COM_CurveBaseOperation.h
@@ -18,12 +18,12 @@
#pragma once
-#include "COM_NodeOperation.h"
+#include "COM_MultiThreadedOperation.h"
#include "DNA_color_types.h"
namespace blender::compositor {
-class CurveBaseOperation : public NodeOperation {
+class CurveBaseOperation : public MultiThreadedOperation {
protected:
/**
* Cached reference to the inputProgram
diff --git a/source/blender/compositor/operations/COM_DilateErodeOperation.cc b/source/blender/compositor/operations/COM_DilateErodeOperation.cc
index c67a35b686c..a27148f967d 100644
--- a/source/blender/compositor/operations/COM_DilateErodeOperation.cc
+++ b/source/blender/compositor/operations/COM_DilateErodeOperation.cc
@@ -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 tile-size 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_HueSaturationValueCorrectOperation.cc b/source/blender/compositor/operations/COM_HueSaturationValueCorrectOperation.cc
index e341a88ff71..5ae868c5964 100644
--- a/source/blender/compositor/operations/COM_HueSaturationValueCorrectOperation.cc
+++ b/source/blender/compositor/operations/COM_HueSaturationValueCorrectOperation.cc
@@ -73,4 +73,31 @@ void HueSaturationValueCorrectOperation::deinitExecution()
this->m_inputProgram = nullptr;
}
+void HueSaturationValueCorrectOperation::update_memory_buffer_partial(MemoryBuffer *output,
+ const rcti &area,
+ Span<MemoryBuffer *> inputs)
+{
+ float hsv[4];
+ for (BuffersIterator<float> it = output->iterate_with(inputs, area); !it.is_end(); ++it) {
+ copy_v4_v4(hsv, it.in(0));
+
+ /* Adjust hue, scaling returned default 0.5 up to 1. */
+ float f = BKE_curvemapping_evaluateF(this->m_curveMapping, 0, hsv[0]);
+ hsv[0] += f - 0.5f;
+
+ /* Adjust saturation, scaling returned default 0.5 up to 1. */
+ f = BKE_curvemapping_evaluateF(this->m_curveMapping, 1, hsv[0]);
+ hsv[1] *= (f * 2.0f);
+
+ /* Adjust value, scaling returned default 0.5 up to 1. */
+ f = BKE_curvemapping_evaluateF(this->m_curveMapping, 2, hsv[0]);
+ hsv[2] *= (f * 2.0f);
+
+ hsv[0] = hsv[0] - floorf(hsv[0]); /* Mod 1.0. */
+ CLAMP(hsv[1], 0.0f, 1.0f);
+
+ copy_v4_v4(it.out, hsv);
+ }
+}
+
} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_HueSaturationValueCorrectOperation.h b/source/blender/compositor/operations/COM_HueSaturationValueCorrectOperation.h
index 703b2894bdb..6c1b66aba1f 100644
--- a/source/blender/compositor/operations/COM_HueSaturationValueCorrectOperation.h
+++ b/source/blender/compositor/operations/COM_HueSaturationValueCorrectOperation.h
@@ -47,6 +47,10 @@ class HueSaturationValueCorrectOperation : public CurveBaseOperation {
* Deinitialize the execution
*/
void deinitExecution() 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_InvertOperation.cc b/source/blender/compositor/operations/COM_InvertOperation.cc
index 339e40a5d1f..4f71a1d0d1d 100644
--- a/source/blender/compositor/operations/COM_InvertOperation.cc
+++ b/source/blender/compositor/operations/COM_InvertOperation.cc
@@ -30,6 +30,7 @@ InvertOperation::InvertOperation()
this->m_color = true;
this->m_alpha = false;
setResolutionInputSocketIndex(1);
+ this->flags.can_be_constant = true;
}
void InvertOperation::initExecution()
{
@@ -70,4 +71,31 @@ void InvertOperation::deinitExecution()
this->m_inputColorProgram = nullptr;
}
+void InvertOperation::update_memory_buffer_partial(MemoryBuffer *output,
+ const rcti &area,
+ Span<MemoryBuffer *> inputs)
+{
+ for (BuffersIterator<float> it = output->iterate_with(inputs, area); !it.is_end(); ++it) {
+ const float value = *it.in(0);
+ const float inverted_value = 1.0f - value;
+ const float *color = it.in(1);
+
+ if (this->m_color) {
+ it.out[0] = (1.0f - color[0]) * value + color[0] * inverted_value;
+ it.out[1] = (1.0f - color[1]) * value + color[1] * inverted_value;
+ it.out[2] = (1.0f - color[2]) * value + color[2] * inverted_value;
+ }
+ else {
+ copy_v3_v3(it.out, color);
+ }
+
+ if (this->m_alpha) {
+ it.out[3] = (1.0f - color[3]) * value + color[3] * inverted_value;
+ }
+ else {
+ it.out[3] = color[3];
+ }
+ }
+}
+
} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_InvertOperation.h b/source/blender/compositor/operations/COM_InvertOperation.h
index 17e5eb95f3e..a084bf5d559 100644
--- a/source/blender/compositor/operations/COM_InvertOperation.h
+++ b/source/blender/compositor/operations/COM_InvertOperation.h
@@ -18,11 +18,11 @@
#pragma once
-#include "COM_NodeOperation.h"
+#include "COM_MultiThreadedOperation.h"
namespace blender::compositor {
-class InvertOperation : public NodeOperation {
+class InvertOperation : public MultiThreadedOperation {
private:
/**
* Cached reference to the inputProgram
@@ -59,6 +59,10 @@ class InvertOperation : public NodeOperation {
{
this->m_alpha = alpha;
}
+
+ 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_MaskOperation.cc b/source/blender/compositor/operations/COM_MaskOperation.cc
index c7763f08e71..84992f23924 100644
--- a/source/blender/compositor/operations/COM_MaskOperation.cc
+++ b/source/blender/compositor/operations/COM_MaskOperation.cc
@@ -161,4 +161,41 @@ void MaskOperation::executePixelSampled(float output[4],
}
}
+void MaskOperation::update_memory_buffer_partial(MemoryBuffer *output,
+ const rcti &area,
+ Span<MemoryBuffer *> UNUSED(inputs))
+{
+ Vector<MaskRasterHandle *> handles = get_non_null_handles();
+ if (handles.size() == 0) {
+ output->fill(area, COM_VALUE_ZERO);
+ return;
+ }
+
+ float xy[2];
+ for (BuffersIterator<float> it = output->iterate_with({}, area); !it.is_end(); ++it) {
+ xy[0] = it.x * m_maskWidthInv + m_mask_px_ofs[0];
+ xy[1] = it.y * m_maskHeightInv + m_mask_px_ofs[1];
+ *it.out = 0.0f;
+ for (MaskRasterHandle *handle : handles) {
+ *it.out += BKE_maskrasterize_handle_sample(handle, xy);
+ }
+
+ /* Until we get better falloff. */
+ *it.out /= m_rasterMaskHandleTot;
+ }
+}
+
+Vector<MaskRasterHandle *> MaskOperation::get_non_null_handles() const
+{
+ Vector<MaskRasterHandle *> handles;
+ for (int i = 0; i < m_rasterMaskHandleTot; i++) {
+ MaskRasterHandle *handle = m_rasterMaskHandles[i];
+ if (handle == nullptr) {
+ continue;
+ }
+ handles.append(handle);
+ }
+ return handles;
+}
+
} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_MaskOperation.h b/source/blender/compositor/operations/COM_MaskOperation.h
index e8cd9c722df..81e344c0451 100644
--- a/source/blender/compositor/operations/COM_MaskOperation.h
+++ b/source/blender/compositor/operations/COM_MaskOperation.h
@@ -19,7 +19,7 @@
#pragma once
#include "BLI_listbase.h"
-#include "COM_NodeOperation.h"
+#include "COM_MultiThreadedOperation.h"
#include "DNA_mask_types.h"
#include "IMB_imbuf_types.h"
@@ -31,7 +31,7 @@ namespace blender::compositor {
/**
* Class with implementation of mask rasterization
*/
-class MaskOperation : public NodeOperation {
+class MaskOperation : public MultiThreadedOperation {
protected:
Mask *m_mask;
@@ -98,6 +98,13 @@ class MaskOperation : public NodeOperation {
}
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;
+
+ private:
+ Vector<MaskRasterHandle *> get_non_null_handles() const;
};
} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_MovieClipAttributeOperation.cc b/source/blender/compositor/operations/COM_MovieClipAttributeOperation.cc
index a9f187258b2..e36e93984fb 100644
--- a/source/blender/compositor/operations/COM_MovieClipAttributeOperation.cc
+++ b/source/blender/compositor/operations/COM_MovieClipAttributeOperation.cc
@@ -29,10 +29,21 @@ MovieClipAttributeOperation::MovieClipAttributeOperation()
this->m_framenumber = 0;
this->m_attribute = MCA_X;
this->m_invert = false;
+ needs_resolution_to_get_constant_ = true;
+ is_value_calculated_ = false;
}
void MovieClipAttributeOperation::initExecution()
{
+ if (!is_value_calculated_) {
+ calc_value();
+ }
+}
+
+void MovieClipAttributeOperation::calc_value()
+{
+ BLI_assert(this->get_flags().is_resolution_set);
+ is_value_calculated_ = true;
if (this->m_clip == nullptr) {
return;
}
@@ -83,4 +94,12 @@ void MovieClipAttributeOperation::determineResolution(unsigned int resolution[2]
resolution[1] = preferredResolution[1];
}
+const float *MovieClipAttributeOperation::get_constant_elem()
+{
+ if (!is_value_calculated_) {
+ calc_value();
+ }
+ return &m_value;
+}
+
} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_MovieClipAttributeOperation.h b/source/blender/compositor/operations/COM_MovieClipAttributeOperation.h
index 8507e98d08f..28c39d4dad3 100644
--- a/source/blender/compositor/operations/COM_MovieClipAttributeOperation.h
+++ b/source/blender/compositor/operations/COM_MovieClipAttributeOperation.h
@@ -18,6 +18,7 @@
#pragma once
+#include "COM_ConstantOperation.h"
#include "COM_NodeOperation.h"
#include "DNA_movieclip_types.h"
@@ -33,13 +34,14 @@ typedef enum MovieClipAttribute {
* this program converts an input color to an output value.
* it assumes we are in sRGB color space.
*/
-class MovieClipAttributeOperation : public NodeOperation {
+class MovieClipAttributeOperation : public ConstantOperation {
private:
MovieClip *m_clip;
float m_value;
int m_framenumber;
bool m_invert;
MovieClipAttribute m_attribute;
+ bool is_value_calculated_;
public:
/**
@@ -56,6 +58,8 @@ class MovieClipAttributeOperation : public NodeOperation {
void determineResolution(unsigned int resolution[2],
unsigned int preferredResolution[2]) override;
+ const float *get_constant_elem() override;
+
void setMovieClip(MovieClip *clip)
{
this->m_clip = clip;
@@ -72,6 +76,9 @@ class MovieClipAttributeOperation : public NodeOperation {
{
this->m_invert = invert;
}
+
+ private:
+ void calc_value();
};
} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_OutputFileOperation.cc b/source/blender/compositor/operations/COM_OutputFileOperation.cc
index 6c5984e3414..402d29893a4 100644
--- a/source/blender/compositor/operations/COM_OutputFileOperation.cc
+++ b/source/blender/compositor/operations/COM_OutputFileOperation.cc
@@ -294,6 +294,22 @@ void OutputSingleLayerOperation::deinitExecution()
this->m_imageInput = nullptr;
}
+void OutputSingleLayerOperation::update_memory_buffer_partial(MemoryBuffer *UNUSED(output),
+ const rcti &area,
+ Span<MemoryBuffer *> inputs)
+{
+ if (!m_outputBuffer) {
+ return;
+ }
+
+ MemoryBuffer output_buf(m_outputBuffer,
+ COM_data_type_num_channels(this->m_datatype),
+ this->getWidth(),
+ this->getHeight());
+ const MemoryBuffer *input_image = inputs[0];
+ output_buf.copy_from(input_image, area);
+}
+
/******************************* MultiLayer *******************************/
OutputOpenExrLayer::OutputOpenExrLayer(const char *name_, DataType datatype_, bool use_layer_)
@@ -444,4 +460,21 @@ void OutputOpenExrMultiLayerOperation::deinitExecution()
}
}
+void OutputOpenExrMultiLayerOperation::update_memory_buffer_partial(MemoryBuffer *UNUSED(output),
+ const rcti &area,
+ Span<MemoryBuffer *> inputs)
+{
+ const MemoryBuffer *input_image = inputs[0];
+ for (int i = 0; i < this->m_layers.size(); i++) {
+ OutputOpenExrLayer &layer = this->m_layers[i];
+ if (layer.outputBuffer) {
+ MemoryBuffer output_buf(layer.outputBuffer,
+ COM_data_type_num_channels(layer.datatype),
+ this->getWidth(),
+ this->getHeight());
+ output_buf.copy_from(input_image, area);
+ }
+ }
+}
+
} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_OutputFileOperation.h b/source/blender/compositor/operations/COM_OutputFileOperation.h
index 64ab4c06e7c..057cee0c43e 100644
--- a/source/blender/compositor/operations/COM_OutputFileOperation.h
+++ b/source/blender/compositor/operations/COM_OutputFileOperation.h
@@ -18,7 +18,7 @@
#pragma once
-#include "COM_NodeOperation.h"
+#include "COM_MultiThreadedOperation.h"
#include "BLI_path_util.h"
#include "BLI_rect.h"
@@ -30,7 +30,7 @@
namespace blender::compositor {
/* Writes the image to a single-layer file. */
-class OutputSingleLayerOperation : public NodeOperation {
+class OutputSingleLayerOperation : public MultiThreadedOperation {
protected:
const RenderData *m_rd;
const bNodeTree *m_tree;
@@ -70,6 +70,10 @@ class OutputSingleLayerOperation : public NodeOperation {
{
return eCompositorPriority::Low;
}
+
+ void update_memory_buffer_partial(MemoryBuffer *output,
+ const rcti &area,
+ Span<MemoryBuffer *> inputs) override;
};
/* extra info for OpenEXR layers */
@@ -86,7 +90,7 @@ struct OutputOpenExrLayer {
};
/* Writes inputs into OpenEXR multilayer channels. */
-class OutputOpenExrMultiLayerOperation : public NodeOperation {
+class OutputOpenExrMultiLayerOperation : public MultiThreadedOperation {
protected:
const Scene *m_scene;
const RenderData *m_rd;
@@ -122,6 +126,10 @@ class OutputOpenExrMultiLayerOperation : public NodeOperation {
{
return eCompositorPriority::Low;
}
+
+ void update_memory_buffer_partial(MemoryBuffer *output,
+ const rcti &area,
+ Span<MemoryBuffer *> inputs) override;
};
void add_exr_channels(void *exrhandle,
diff --git a/source/blender/compositor/operations/COM_SetColorOperation.cc b/source/blender/compositor/operations/COM_SetColorOperation.cc
index bfe735aab15..dbe45fa60db 100644
--- a/source/blender/compositor/operations/COM_SetColorOperation.cc
+++ b/source/blender/compositor/operations/COM_SetColorOperation.cc
@@ -24,7 +24,6 @@ SetColorOperation::SetColorOperation()
{
this->addOutputSocket(DataType::Color);
flags.is_set_operation = true;
- flags.is_fullframe_operation = true;
}
void SetColorOperation::executePixelSampled(float output[4],
@@ -42,13 +41,4 @@ void SetColorOperation::determineResolution(unsigned int resolution[2],
resolution[1] = preferredResolution[1];
}
-void SetColorOperation::update_memory_buffer(MemoryBuffer *output,
- const rcti &area,
- Span<MemoryBuffer *> UNUSED(inputs))
-{
- BLI_assert(output->is_a_single_elem());
- float *out_elem = output->get_elem(area.xmin, area.ymin);
- copy_v4_v4(out_elem, m_color);
-}
-
} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_SetColorOperation.h b/source/blender/compositor/operations/COM_SetColorOperation.h
index f4c0948ee1b..f546d5e7668 100644
--- a/source/blender/compositor/operations/COM_SetColorOperation.h
+++ b/source/blender/compositor/operations/COM_SetColorOperation.h
@@ -85,10 +85,6 @@ class SetColorOperation : public ConstantOperation {
void determineResolution(unsigned int resolution[2],
unsigned int preferredResolution[2]) override;
-
- void update_memory_buffer(MemoryBuffer *output,
- const rcti &area,
- 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 c12fb106afd..ef43cf64653 100644
--- a/source/blender/compositor/operations/COM_SetValueOperation.cc
+++ b/source/blender/compositor/operations/COM_SetValueOperation.cc
@@ -24,7 +24,6 @@ SetValueOperation::SetValueOperation()
{
this->addOutputSocket(DataType::Value);
flags.is_set_operation = true;
- flags.is_fullframe_operation = true;
}
void SetValueOperation::executePixelSampled(float output[4],
@@ -42,13 +41,4 @@ void SetValueOperation::determineResolution(unsigned int resolution[2],
resolution[1] = preferredResolution[1];
}
-void SetValueOperation::update_memory_buffer(MemoryBuffer *output,
- const rcti &area,
- Span<MemoryBuffer *> UNUSED(inputs))
-{
- BLI_assert(output->is_a_single_elem());
- float *out_elem = output->get_elem(area.xmin, area.ymin);
- *out_elem = m_value;
-}
-
} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_SetValueOperation.h b/source/blender/compositor/operations/COM_SetValueOperation.h
index f18d44d9554..726624c1c6a 100644
--- a/source/blender/compositor/operations/COM_SetValueOperation.h
+++ b/source/blender/compositor/operations/COM_SetValueOperation.h
@@ -56,9 +56,6 @@ class SetValueOperation : public ConstantOperation {
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
void determineResolution(unsigned int resolution[2],
unsigned int preferredResolution[2]) override;
- void update_memory_buffer(MemoryBuffer *output,
- const rcti &area,
- Span<MemoryBuffer *> inputs) override;
};
} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_SplitOperation.cc b/source/blender/compositor/operations/COM_SplitOperation.cc
index a4754de370d..d18ed3b8e14 100644
--- a/source/blender/compositor/operations/COM_SplitOperation.cc
+++ b/source/blender/compositor/operations/COM_SplitOperation.cc
@@ -79,4 +79,17 @@ void SplitOperation::determineResolution(unsigned int resolution[2],
NodeOperation::determineResolution(resolution, preferredResolution);
}
+void SplitOperation::update_memory_buffer_partial(MemoryBuffer *output,
+ const rcti &area,
+ Span<MemoryBuffer *> inputs)
+{
+ const int percent = this->m_xSplit ? this->m_splitPercentage * this->getWidth() / 100.0f :
+ this->m_splitPercentage * this->getHeight() / 100.0f;
+ const size_t elem_bytes = COM_data_type_bytes_len(getOutputSocket()->getDataType());
+ for (BuffersIterator<float> it = output->iterate_with(inputs, area); !it.is_end(); ++it) {
+ const bool is_image1 = this->m_xSplit ? it.x > percent : it.y > percent;
+ memcpy(it.out, it.in(is_image1 ? 0 : 1), elem_bytes);
+ }
+}
+
} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_SplitOperation.h b/source/blender/compositor/operations/COM_SplitOperation.h
index 09e48821dd0..2d09d2a07dc 100644
--- a/source/blender/compositor/operations/COM_SplitOperation.h
+++ b/source/blender/compositor/operations/COM_SplitOperation.h
@@ -18,11 +18,11 @@
#pragma once
-#include "COM_NodeOperation.h"
+#include "COM_MultiThreadedOperation.h"
namespace blender::compositor {
-class SplitOperation : public NodeOperation {
+class SplitOperation : public MultiThreadedOperation {
private:
SocketReader *m_image1Input;
SocketReader *m_image2Input;
@@ -45,6 +45,10 @@ class SplitOperation : public NodeOperation {
{
this->m_xSplit = xsplit;
}
+
+ 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_SunBeamsOperation.cc b/source/blender/compositor/operations/COM_SunBeamsOperation.cc
index bd82b6397ad..ad96e3a02ba 100644
--- a/source/blender/compositor/operations/COM_SunBeamsOperation.cc
+++ b/source/blender/compositor/operations/COM_SunBeamsOperation.cc
@@ -30,7 +30,7 @@ SunBeamsOperation::SunBeamsOperation()
this->flags.complex = true;
}
-void SunBeamsOperation::initExecution()
+void SunBeamsOperation::calc_rays_common_data()
{
/* convert to pixels */
this->m_source_px[0] = this->m_data.source[0] * this->getWidth();
@@ -38,6 +38,11 @@ void SunBeamsOperation::initExecution()
this->m_ray_length_px = this->m_data.ray_length * MAX2(this->getWidth(), this->getHeight());
}
+void SunBeamsOperation::initExecution()
+{
+ calc_rays_common_data();
+}
+
/**
* Defines a line accumulator for a specific sector,
* given by the four matrix entries that rotate from buffer space into the sector
@@ -140,7 +145,7 @@ template<int fxu, int fxv, int fyu, int fyv> struct BufferLineAccumulator {
falloff_factor = dist_max > dist_min ? dr / (float)(dist_max - dist_min) : 0.0f;
- float *iter = input->getBuffer() + COM_DATA_TYPE_COLOR_CHANNELS * (x + input->getWidth() * y);
+ float *iter = input->getBuffer() + input->get_coords_offset(x, y);
return iter;
}
@@ -159,7 +164,6 @@ template<int fxu, int fxv, int fyu, int fyv> struct BufferLineAccumulator {
float dist_max)
{
const rcti &rect = input->get_rect();
- int buffer_width = input->getWidth();
int x, y, num;
float v, dv;
float falloff_factor;
@@ -168,9 +172,7 @@ template<int fxu, int fxv, int fyu, int fyv> struct BufferLineAccumulator {
zero_v4(output);
if ((int)(co[0] - source[0]) == 0 && (int)(co[1] - source[1]) == 0) {
- copy_v4_v4(output,
- input->getBuffer() + COM_DATA_TYPE_COLOR_CHANNELS *
- ((int)source[0] + input->getWidth() * (int)source[1]));
+ copy_v4_v4(output, input->get_elem(source[0], source[1]));
return;
}
@@ -210,7 +212,7 @@ template<int fxu, int fxv, int fyu, int fyv> struct BufferLineAccumulator {
/* decrement u */
x -= fxu;
y -= fyu;
- buffer -= (fxu + fyu * buffer_width) * COM_DATA_TYPE_COLOR_CHANNELS;
+ buffer -= fxu * input->elem_stride + fyu * input->row_stride;
/* decrement v (in steps of dv < 1) */
v_local -= dv;
@@ -219,7 +221,7 @@ template<int fxu, int fxv, int fyu, int fyv> struct BufferLineAccumulator {
x -= fxv;
y -= fyv;
- buffer -= (fxv + fyv * buffer_width) * COM_DATA_TYPE_COLOR_CHANNELS;
+ buffer -= fxv * input->elem_stride + fyv * input->row_stride;
}
}
@@ -356,4 +358,39 @@ bool SunBeamsOperation::determineDependingAreaOfInterest(rcti *input,
return NodeOperation::determineDependingAreaOfInterest(&rect, readOperation, output);
}
+void SunBeamsOperation::get_area_of_interest(const int input_idx,
+ const rcti &output_area,
+ rcti &r_input_area)
+{
+ BLI_assert(input_idx == 0);
+ UNUSED_VARS(input_idx);
+ calc_rays_common_data();
+
+ r_input_area = output_area;
+ /* Enlarges the rect by moving each corner toward the source.
+ * This is the maximum distance that pixels can influence each other
+ * and gives a rect that contains all possible accumulated pixels. */
+ calc_ray_shift(&r_input_area, output_area.xmin, output_area.ymin, m_source_px, m_ray_length_px);
+ calc_ray_shift(&r_input_area, output_area.xmin, output_area.ymax, m_source_px, m_ray_length_px);
+ calc_ray_shift(&r_input_area, output_area.xmax, output_area.ymin, m_source_px, m_ray_length_px);
+ calc_ray_shift(&r_input_area, output_area.xmax, output_area.ymax, m_source_px, m_ray_length_px);
+}
+
+void SunBeamsOperation::update_memory_buffer_partial(MemoryBuffer *output,
+ const rcti &area,
+ Span<MemoryBuffer *> inputs)
+{
+ MemoryBuffer *input = inputs[0];
+ float coords[2];
+ for (int y = area.ymin; y < area.ymax; y++) {
+ coords[1] = y;
+ float *out_elem = output->get_elem(area.xmin, y);
+ for (int x = area.xmin; x < area.xmax; x++) {
+ coords[0] = x;
+ accumulate_line(input, out_elem, coords, m_source_px, 0.0f, m_ray_length_px);
+ out_elem += output->elem_stride;
+ }
+ }
+}
+
} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_SunBeamsOperation.h b/source/blender/compositor/operations/COM_SunBeamsOperation.h
index d3725021cde..71fc04453fe 100644
--- a/source/blender/compositor/operations/COM_SunBeamsOperation.h
+++ b/source/blender/compositor/operations/COM_SunBeamsOperation.h
@@ -17,11 +17,11 @@
#pragma once
-#include "COM_NodeOperation.h"
+#include "COM_MultiThreadedOperation.h"
namespace blender::compositor {
-class SunBeamsOperation : public NodeOperation {
+class SunBeamsOperation : public MultiThreadedOperation {
public:
SunBeamsOperation();
@@ -40,6 +40,14 @@ class SunBeamsOperation : public NodeOperation {
m_data = data;
}
+ void update_memory_buffer_partial(MemoryBuffer *output,
+ const rcti &area,
+ Span<MemoryBuffer *> inputs) override;
+ void get_area_of_interest(int input_idx, const rcti &output_area, rcti &r_input_area) override;
+
+ private:
+ void calc_rays_common_data();
+
private:
NodeSunBeams m_data;
diff --git a/source/blender/compositor/operations/COM_TonemapOperation.cc b/source/blender/compositor/operations/COM_TonemapOperation.cc
index 6bfacb0c75d..20da468eeb1 100644
--- a/source/blender/compositor/operations/COM_TonemapOperation.cc
+++ b/source/blender/compositor/operations/COM_TonemapOperation.cc
@@ -17,6 +17,8 @@
*/
#include "COM_TonemapOperation.h"
+#include "COM_ExecutionSystem.h"
+
#include "BLI_math.h"
#include "BLI_utildefines.h"
@@ -153,4 +155,126 @@ void TonemapOperation::deinitializeTileData(rcti * /*rect*/, void * /*data*/)
/* pass */
}
+void TonemapOperation::get_area_of_interest(const int input_idx,
+ const rcti &UNUSED(output_area),
+ rcti &r_input_area)
+{
+ BLI_assert(input_idx == 0);
+ NodeOperation *operation = getInputOperation(input_idx);
+ r_input_area.xmin = 0;
+ r_input_area.ymin = 0;
+ r_input_area.xmax = operation->getWidth();
+ r_input_area.ymax = operation->getHeight();
+}
+
+struct Luminance {
+ float sum;
+ float color_sum[3];
+ float log_sum;
+ float min;
+ float max;
+ int num_pixels;
+};
+
+static Luminance calc_area_luminance(const MemoryBuffer *input, const rcti &area)
+{
+ Luminance lum = {0};
+ for (const float *elem : input->get_buffer_area(area)) {
+ const float lu = IMB_colormanagement_get_luminance(elem);
+ lum.sum += lu;
+ add_v3_v3(lum.color_sum, elem);
+ lum.log_sum += logf(MAX2(lu, 0.0f) + 1e-5f);
+ lum.max = MAX2(lu, lum.max);
+ lum.min = MIN2(lu, lum.min);
+ lum.num_pixels++;
+ }
+ return lum;
+}
+
+void TonemapOperation::update_memory_buffer_started(MemoryBuffer *UNUSED(output),
+ const rcti &UNUSED(area),
+ Span<MemoryBuffer *> inputs)
+{
+ if (this->m_cachedInstance == nullptr) {
+ Luminance lum = {0};
+ const MemoryBuffer *input = inputs[0];
+ exec_system_->execute_work<Luminance>(
+ input->get_rect(),
+ [=](const rcti &split) { return calc_area_luminance(input, split); },
+ lum,
+ [](Luminance &join, const Luminance &chunk) {
+ join.sum += chunk.sum;
+ add_v3_v3(join.color_sum, chunk.color_sum);
+ join.log_sum += chunk.log_sum;
+ join.max = MAX2(join.max, chunk.max);
+ join.min = MIN2(join.min, chunk.min);
+ join.num_pixels += chunk.num_pixels;
+ });
+
+ AvgLogLum *avg = new AvgLogLum();
+ avg->lav = lum.sum / lum.num_pixels;
+ mul_v3_v3fl(avg->cav, lum.color_sum, 1.0f / lum.num_pixels);
+ const float max_log = log((double)lum.max + 1e-5);
+ const float min_log = log((double)lum.min + 1e-5);
+ const float avg_log = lum.log_sum / lum.num_pixels;
+ avg->auto_key = (max_log > min_log) ? ((max_log - avg_log) / (max_log - min_log)) : 1.0f;
+ const float al = exp((double)avg_log);
+ avg->al = (al == 0.0f) ? 0.0f : (this->m_data->key / al);
+ avg->igm = (this->m_data->gamma == 0.0f) ? 1 : (1.0f / this->m_data->gamma);
+ this->m_cachedInstance = avg;
+ }
+}
+
+void TonemapOperation::update_memory_buffer_partial(MemoryBuffer *output,
+ const rcti &area,
+ Span<MemoryBuffer *> inputs)
+{
+ AvgLogLum *avg = m_cachedInstance;
+ const float igm = avg->igm;
+ const float offset = this->m_data->offset;
+ for (BuffersIterator<float> it = output->iterate_with(inputs, area); !it.is_end(); ++it) {
+ copy_v4_v4(it.out, it.in(0));
+ mul_v3_fl(it.out, avg->al);
+ float dr = it.out[0] + offset;
+ float dg = it.out[1] + offset;
+ float db = it.out[2] + offset;
+ it.out[0] /= ((dr == 0.0f) ? 1.0f : dr);
+ it.out[1] /= ((dg == 0.0f) ? 1.0f : dg);
+ it.out[2] /= ((db == 0.0f) ? 1.0f : db);
+ if (igm != 0.0f) {
+ it.out[0] = powf(MAX2(it.out[0], 0.0f), igm);
+ it.out[1] = powf(MAX2(it.out[1], 0.0f), igm);
+ it.out[2] = powf(MAX2(it.out[2], 0.0f), igm);
+ }
+ }
+}
+
+void PhotoreceptorTonemapOperation::update_memory_buffer_partial(MemoryBuffer *output,
+ const rcti &area,
+ Span<MemoryBuffer *> inputs)
+{
+ AvgLogLum *avg = m_cachedInstance;
+ NodeTonemap *ntm = this->m_data;
+ const float f = expf(-this->m_data->f);
+ const float m = (ntm->m > 0.0f) ? ntm->m : (0.3f + 0.7f * powf(avg->auto_key, 1.4f));
+ const float ic = 1.0f - ntm->c;
+ const float ia = 1.0f - ntm->a;
+ for (BuffersIterator<float> it = output->iterate_with(inputs, area); !it.is_end(); ++it) {
+ copy_v4_v4(it.out, it.in(0));
+ const float L = IMB_colormanagement_get_luminance(it.out);
+ float I_l = it.out[0] + ic * (L - it.out[0]);
+ float I_g = avg->cav[0] + ic * (avg->lav - avg->cav[0]);
+ float I_a = I_l + ia * (I_g - I_l);
+ it.out[0] /= (it.out[0] + powf(f * I_a, m));
+ I_l = it.out[1] + ic * (L - it.out[1]);
+ I_g = avg->cav[1] + ic * (avg->lav - avg->cav[1]);
+ I_a = I_l + ia * (I_g - I_l);
+ it.out[1] /= (it.out[1] + powf(f * I_a, m));
+ I_l = it.out[2] + ic * (L - it.out[2]);
+ I_g = avg->cav[2] + ic * (avg->lav - avg->cav[2]);
+ I_a = I_l + ia * (I_g - I_l);
+ it.out[2] /= (it.out[2] + powf(f * I_a, m));
+ }
+}
+
} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_TonemapOperation.h b/source/blender/compositor/operations/COM_TonemapOperation.h
index 7ecb179504d..56b57730ec1 100644
--- a/source/blender/compositor/operations/COM_TonemapOperation.h
+++ b/source/blender/compositor/operations/COM_TonemapOperation.h
@@ -18,7 +18,7 @@
#pragma once
-#include "COM_NodeOperation.h"
+#include "COM_MultiThreadedOperation.h"
#include "DNA_node_types.h"
namespace blender::compositor {
@@ -39,7 +39,7 @@ typedef struct AvgLogLum {
* \brief base class of tonemap, implementing the simple tonemap
* \ingroup operation
*/
-class TonemapOperation : public NodeOperation {
+class TonemapOperation : public MultiThreadedOperation {
protected:
/**
* \brief Cached reference to the reader
@@ -85,6 +85,14 @@ class TonemapOperation : public NodeOperation {
bool determineDependingAreaOfInterest(rcti *input,
ReadBufferOperation *readOperation,
rcti *output) override;
+
+ void get_area_of_interest(int input_idx, const rcti &output_area, rcti &r_input_area) override;
+ void update_memory_buffer_started(MemoryBuffer *output,
+ const rcti &area,
+ Span<MemoryBuffer *> inputs) override;
+ virtual void update_memory_buffer_partial(MemoryBuffer *output,
+ const rcti &area,
+ Span<MemoryBuffer *> inputs) override;
};
/**
@@ -99,6 +107,10 @@ class PhotoreceptorTonemapOperation : public TonemapOperation {
* The inner loop of this operation.
*/
void executePixel(float output[4], int x, int y, void *data) 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_TrackPositionOperation.cc b/source/blender/compositor/operations/COM_TrackPositionOperation.cc
index 993410e3e84..0f4be16a620 100644
--- a/source/blender/compositor/operations/COM_TrackPositionOperation.cc
+++ b/source/blender/compositor/operations/COM_TrackPositionOperation.cc
@@ -42,14 +42,24 @@ TrackPositionOperation::TrackPositionOperation()
this->m_relativeFrame = 0;
this->m_speed_output = false;
flags.is_set_operation = true;
+ is_track_position_calculated_ = false;
}
void TrackPositionOperation::initExecution()
{
+ if (!is_track_position_calculated_) {
+ calc_track_position();
+ }
+}
+
+void TrackPositionOperation::calc_track_position()
+{
+ is_track_position_calculated_ = true;
MovieTracking *tracking = nullptr;
MovieClipUser user = {0};
MovieTrackingObject *object;
+ track_position_ = 0;
zero_v2(this->m_markerPos);
zero_v2(this->m_relativePos);
@@ -114,6 +124,14 @@ void TrackPositionOperation::initExecution()
}
}
}
+
+ track_position_ = this->m_markerPos[this->m_axis] - this->m_relativePos[this->m_axis];
+ if (this->m_axis == 0) {
+ track_position_ *= this->m_width;
+ }
+ else {
+ track_position_ *= this->m_height;
+ }
}
void TrackPositionOperation::executePixelSampled(float output[4],
@@ -131,6 +149,14 @@ void TrackPositionOperation::executePixelSampled(float output[4],
}
}
+const float *TrackPositionOperation::get_constant_elem()
+{
+ if (!is_track_position_calculated_) {
+ calc_track_position();
+ }
+ return &track_position_;
+}
+
void TrackPositionOperation::determineResolution(unsigned int resolution[2],
unsigned int preferredResolution[2])
{
diff --git a/source/blender/compositor/operations/COM_TrackPositionOperation.h b/source/blender/compositor/operations/COM_TrackPositionOperation.h
index b0b0a123bd6..f716bd97737 100644
--- a/source/blender/compositor/operations/COM_TrackPositionOperation.h
+++ b/source/blender/compositor/operations/COM_TrackPositionOperation.h
@@ -20,7 +20,7 @@
#include <string.h>
-#include "COM_NodeOperation.h"
+#include "COM_ConstantOperation.h"
#include "DNA_movieclip_types.h"
#include "DNA_tracking_types.h"
@@ -33,7 +33,7 @@ namespace blender::compositor {
/**
* Class with implementation of green screen gradient rasterization
*/
-class TrackPositionOperation : public NodeOperation {
+class TrackPositionOperation : public ConstantOperation {
protected:
MovieClip *m_movieClip;
int m_framenumber;
@@ -47,6 +47,8 @@ class TrackPositionOperation : public NodeOperation {
int m_width, m_height;
float m_markerPos[2];
float m_relativePos[2];
+ float track_position_;
+ bool is_track_position_calculated_;
/**
* Determine the output resolution. The resolution is retrieved from the Renderer
@@ -93,6 +95,11 @@ class TrackPositionOperation : public NodeOperation {
void initExecution() override;
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
+
+ const float *get_constant_elem() override;
+
+ private:
+ void calc_track_position();
};
} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_VectorCurveOperation.cc b/source/blender/compositor/operations/COM_VectorCurveOperation.cc
index 9d53ed5d8ee..c2087fd071e 100644
--- a/source/blender/compositor/operations/COM_VectorCurveOperation.cc
+++ b/source/blender/compositor/operations/COM_VectorCurveOperation.cc
@@ -53,4 +53,14 @@ void VectorCurveOperation::deinitExecution()
this->m_inputProgram = nullptr;
}
+void VectorCurveOperation::update_memory_buffer_partial(MemoryBuffer *output,
+ const rcti &area,
+ Span<MemoryBuffer *> inputs)
+{
+ CurveMapping *curve_map = this->m_curveMapping;
+ for (BuffersIterator<float> it = output->iterate_with(inputs, area); !it.is_end(); ++it) {
+ BKE_curvemapping_evaluate_premulRGBF(curve_map, it.out, it.in(0));
+ }
+}
+
} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_VectorCurveOperation.h b/source/blender/compositor/operations/COM_VectorCurveOperation.h
index 8cbb80e27c7..27b3ad69e17 100644
--- a/source/blender/compositor/operations/COM_VectorCurveOperation.h
+++ b/source/blender/compositor/operations/COM_VectorCurveOperation.h
@@ -47,6 +47,10 @@ class VectorCurveOperation : public CurveBaseOperation {
* Deinitialize the execution
*/
void deinitExecution() 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_ZCombineOperation.cc b/source/blender/compositor/operations/COM_ZCombineOperation.cc
index 9d3ca7e736e..7050c3b2d83 100644
--- a/source/blender/compositor/operations/COM_ZCombineOperation.cc
+++ b/source/blender/compositor/operations/COM_ZCombineOperation.cc
@@ -33,6 +33,7 @@ ZCombineOperation::ZCombineOperation()
this->m_depth1Reader = nullptr;
this->m_image2Reader = nullptr;
this->m_depth2Reader = nullptr;
+ this->flags.can_be_constant = true;
}
void ZCombineOperation::initExecution()
@@ -60,6 +61,19 @@ void ZCombineOperation::executePixelSampled(float output[4],
this->m_image2Reader->readSampled(output, x, y, sampler);
}
}
+
+void ZCombineOperation::update_memory_buffer_partial(MemoryBuffer *output,
+ const rcti &area,
+ Span<MemoryBuffer *> inputs)
+{
+ for (BuffersIterator<float> it = output->iterate_with(inputs, area); !it.is_end(); ++it) {
+ const float depth1 = *it.in(1);
+ const float depth2 = *it.in(3);
+ const float *color = (depth1 < depth2) ? it.in(0) : it.in(2);
+ copy_v4_v4(it.out, color);
+ }
+}
+
void ZCombineAlphaOperation::executePixelSampled(float output[4],
float x,
float y,
@@ -88,6 +102,32 @@ void ZCombineAlphaOperation::executePixelSampled(float output[4],
output[3] = MAX2(color1[3], color2[3]);
}
+void ZCombineAlphaOperation::update_memory_buffer_partial(MemoryBuffer *output,
+ const rcti &area,
+ Span<MemoryBuffer *> inputs)
+{
+ for (BuffersIterator<float> it = output->iterate_with(inputs, area); !it.is_end(); ++it) {
+ const float depth1 = *it.in(1);
+ const float depth2 = *it.in(3);
+ const float *color1;
+ const float *color2;
+ if (depth1 <= depth2) {
+ color1 = it.in(0);
+ color2 = it.in(2);
+ }
+ else {
+ color1 = it.in(2);
+ color2 = it.in(0);
+ }
+ const float fac = color1[3];
+ const float ifac = 1.0f - fac;
+ it.out[0] = fac * color1[0] + ifac * color2[0];
+ it.out[1] = fac * color1[1] + ifac * color2[1];
+ it.out[2] = fac * color1[2] + ifac * color2[2];
+ it.out[3] = MAX2(color1[3], color2[3]);
+ }
+}
+
void ZCombineOperation::deinitExecution()
{
this->m_image1Reader = nullptr;
@@ -132,6 +172,18 @@ void ZCombineMaskOperation::executePixelSampled(float output[4],
interp_v4_v4v4(output, color1, color2, 1.0f - mask[0]);
}
+void ZCombineMaskOperation::update_memory_buffer_partial(MemoryBuffer *output,
+ const rcti &area,
+ Span<MemoryBuffer *> inputs)
+{
+ for (BuffersIterator<float> it = output->iterate_with(inputs, area); !it.is_end(); ++it) {
+ const float mask = *it.in(0);
+ const float *color1 = it.in(1);
+ const float *color2 = it.in(2);
+ interp_v4_v4v4(it.out, color1, color2, 1.0f - mask);
+ }
+}
+
void ZCombineMaskAlphaOperation::executePixelSampled(float output[4],
float x,
float y,
@@ -154,6 +206,24 @@ void ZCombineMaskAlphaOperation::executePixelSampled(float output[4],
output[3] = MAX2(color1[3], color2[3]);
}
+void ZCombineMaskAlphaOperation::update_memory_buffer_partial(MemoryBuffer *output,
+ const rcti &area,
+ Span<MemoryBuffer *> inputs)
+{
+ for (BuffersIterator<float> it = output->iterate_with(inputs, area); !it.is_end(); ++it) {
+ const float mask = *it.in(0);
+ const float *color1 = it.in(1);
+ const float *color2 = it.in(2);
+ const float fac = (1.0f - mask) * (1.0f - color1[3]) + mask * color2[3];
+ const float mfac = 1.0f - fac;
+
+ it.out[0] = color1[0] * mfac + color2[0] * fac;
+ it.out[1] = color1[1] * mfac + color2[1] * fac;
+ it.out[2] = color1[2] * mfac + color2[2] * fac;
+ it.out[3] = MAX2(color1[3], color2[3]);
+ }
+}
+
void ZCombineMaskOperation::deinitExecution()
{
this->m_image1Reader = nullptr;
diff --git a/source/blender/compositor/operations/COM_ZCombineOperation.h b/source/blender/compositor/operations/COM_ZCombineOperation.h
index d0b1aee7310..acd60b6c866 100644
--- a/source/blender/compositor/operations/COM_ZCombineOperation.h
+++ b/source/blender/compositor/operations/COM_ZCombineOperation.h
@@ -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 ZCombineOperation : public NodeOperation {
+class ZCombineOperation : public MultiThreadedOperation {
protected:
SocketReader *m_image1Reader;
SocketReader *m_depth1Reader;
@@ -46,13 +46,21 @@ class ZCombineOperation : public NodeOperation {
* The inner loop of this operation.
*/
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 ZCombineAlphaOperation : public ZCombineOperation {
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 ZCombineMaskOperation : public NodeOperation {
+class ZCombineMaskOperation : public MultiThreadedOperation {
protected:
SocketReader *m_maskReader;
SocketReader *m_image1Reader;
@@ -64,9 +72,17 @@ class ZCombineMaskOperation : public NodeOperation {
void initExecution() override;
void deinitExecution() override;
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 ZCombineMaskAlphaOperation : public ZCombineMaskOperation {
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/datatoc/datatoc.c b/source/blender/datatoc/datatoc.c
index 62b4cee4af0..816353be9de 100644
--- a/source/blender/datatoc/datatoc.c
+++ b/source/blender/datatoc/datatoc.c
@@ -100,15 +100,14 @@ int main(int argc, char **argv)
fprintf(fpout, "const int datatoc_%s_size = %d;\n", argv[1], (int)size);
fprintf(fpout, "const char datatoc_%s[] = {\n", argv[1]);
while (size--) {
- /* if we want to open in an editor
- * this is nicer to avoid very long lines */
-#ifdef VERBOSE
+ /* Even though this file is generated and doesn't need new-lines,
+ * these files may be loaded by developers when looking up symbols.
+ * Avoid a very long single line that may lock-up some editors. */
if (size % 32 == 31) {
fprintf(fpout, "\n");
}
-#endif
- /* fprintf (fpout, "\\x%02x", getc(fpin)); */
+ // fprintf(fpout, "\\x%02x", getc(fpin));
fprintf(fpout, "%3d,", getc(fpin));
}
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc
index c7c6fafa512..7da3d2e25f0 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc
@@ -2224,6 +2224,11 @@ void DepsgraphRelationBuilder::build_object_data_geometry_datablock(ID *obdata)
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_eval_key, obdata_geom_done_key, "ObData Geom Eval Done");
+
+ /* Link object data evaluation to parameter evaluation. */
+ ComponentKey parameters_key(obdata, NodeType::PARAMETERS);
+ add_relation(parameters_key, obdata_geom_eval_key, "ObData Geom Params");
+
/* Type-specific links. */
const ID_Type id_type = GS(obdata->name);
switch (id_type) {
diff --git a/source/blender/depsgraph/intern/depsgraph_tag.cc b/source/blender/depsgraph/intern/depsgraph_tag.cc
index ab93464d09a..dd96c5a3b2b 100644
--- a/source/blender/depsgraph/intern/depsgraph_tag.cc
+++ b/source/blender/depsgraph/intern/depsgraph_tag.cc
@@ -646,8 +646,8 @@ void graph_id_tag_update(
{
const int debug_flags = (graph != nullptr) ? DEG_debug_flags_get((::Depsgraph *)graph) : G.debug;
if (graph != nullptr && graph->is_evaluating) {
- if (debug_flags & G_DEBUG_DEPSGRAPH) {
- printf("ID tagged for update during dependency graph evaluation.");
+ if (debug_flags & G_DEBUG_DEPSGRAPH_TAG) {
+ printf("ID tagged for update during dependency graph evaluation.\n");
}
return;
}
diff --git a/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.h b/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.h
index 255ea840088..d0bb841caab 100644
--- a/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.h
+++ b/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.h
@@ -68,11 +68,11 @@ ID *deg_expand_copy_on_write_datablock(const struct Depsgraph *depsgraph,
ID *deg_update_copy_on_write_datablock(const struct Depsgraph *depsgraph, const IDNode *id_node);
ID *deg_update_copy_on_write_datablock(const struct Depsgraph *depsgraph, struct ID *id_orig);
-/* Helper function which frees memory used by copy-on-written databnlock. */
+/* Helper function which frees memory used by copy-on-written data-block. */
void deg_free_copy_on_write_datablock(struct ID *id_cow);
/* Callback function for depsgraph operation node which ensures copy-on-write
- * datablock is ready for use by further evaluation routines.
+ * data-block is ready for use by further evaluation routines.
*/
void deg_evaluate_copy_on_write(struct ::Depsgraph *depsgraph, const struct IDNode *id_node);
@@ -80,16 +80,16 @@ void deg_evaluate_copy_on_write(struct ::Depsgraph *depsgraph, const struct IDNo
* copies inside. */
bool deg_validate_copy_on_write_datablock(ID *id_cow);
-/* Tag given ID block as being copy-on-wtritten. */
+/* Tag given ID block as being copy-on-written. */
void deg_tag_copy_on_write_id(struct ID *id_cow, const struct ID *id_orig);
-/* Check whether ID datablock is expanded.
+/* Check whether ID data-block is expanded.
*
* TODO(sergey): Make it an inline function or a macro.
*/
bool deg_copy_on_write_is_expanded(const struct ID *id_cow);
-/* Check whether copy-on-write datablock is needed for given ID.
+/* Check whether copy-on-write data-block is needed for given ID.
*
* There are some exceptions on data-blocks which are covered by dependency graph
* but which we don't want to start duplicating.
diff --git a/source/blender/draw/engines/overlay/overlay_extra.c b/source/blender/draw/engines/overlay/overlay_extra.c
index f5be9c846d1..2a9080eb217 100644
--- a/source/blender/draw/engines/overlay/overlay_extra.c
+++ b/source/blender/draw/engines/overlay/overlay_extra.c
@@ -1357,7 +1357,8 @@ static void OVERLAY_relationship_lines(OVERLAY_ExtraCallBuffers *cb,
}
}
}
- BKE_constraints_clear_evalob(cob);
+ /* NOTE: Don't use BKE_constraints_clear_evalob here as that will reset ob->constinv. */
+ MEM_freeN(cob);
}
}
diff --git a/source/blender/draw/engines/select/select_debug_engine.c b/source/blender/draw/engines/select/select_debug_engine.c
index ded96be23f3..e9437c5ab92 100644
--- a/source/blender/draw/engines/select/select_debug_engine.c
+++ b/source/blender/draw/engines/select/select_debug_engine.c
@@ -19,7 +19,7 @@
/** \file
* \ingroup draw_engine
*
- * Engine for debuging the selection map drawing.
+ * Engine for debugging the selection map drawing.
*/
#include "DNA_ID.h"
diff --git a/source/blender/draw/intern/draw_cache_impl_gpencil.c b/source/blender/draw/intern/draw_cache_impl_gpencil.c
index 2a476ab41bb..6ed4148a7fe 100644
--- a/source/blender/draw/intern/draw_cache_impl_gpencil.c
+++ b/source/blender/draw/intern/draw_cache_impl_gpencil.c
@@ -553,7 +553,7 @@ bGPDstroke *DRW_cache_gpencil_sbuffer_stroke_data_get(Object *ob)
gps->runtime.stroke_start = 1; /* Add one for the adjacency index. */
copy_v4_v4(gps->vert_color_fill, gpd->runtime.vert_color_fill);
/* Caps. */
- gps->caps[0] = gps->caps[1] = brush->gpencil_settings->caps_type;
+ gps->caps[0] = gps->caps[1] = (short)brush->gpencil_settings->caps_type;
gpd->runtime.sbuffer_gps = gps;
}
diff --git a/source/blender/draw/intern/draw_cache_impl_mesh.c b/source/blender/draw/intern/draw_cache_impl_mesh.c
index 359788545e4..86c14330409 100644
--- a/source/blender/draw/intern/draw_cache_impl_mesh.c
+++ b/source/blender/draw/intern/draw_cache_impl_mesh.c
@@ -95,7 +95,7 @@
#define MDEPS_CREATE(buff_name, ...) [_BUFFER_INDEX(buff_name)] = VA_NARGS_CALL_OVERLOAD(_MDEPS_CREATE, __VA_ARGS__)
-#define _MDEPS_CREATE_MAP1(a) g_buffer_desps[_BUFFER_INDEX(a)]
+#define _MDEPS_CREATE_MAP1(a) g_buffer_deps[_BUFFER_INDEX(a)]
#define _MDEPS_CREATE_MAP2(a, b) _MDEPS_CREATE_MAP1(a) | _MDEPS_CREATE_MAP1(b)
#define _MDEPS_CREATE_MAP3(a, b, c) _MDEPS_CREATE_MAP2(a, b) | _MDEPS_CREATE_MAP1(c)
#define _MDEPS_CREATE_MAP4(a, b, c, d) _MDEPS_CREATE_MAP3(a, b, c) | _MDEPS_CREATE_MAP1(d)
@@ -110,8 +110,8 @@
#ifndef NDEBUG
# define _MDEPS_ASSERT2(b, name) \
- g_buffer_desps_d[_BUFFER_INDEX(name)] |= _MDEPS_CREATE1(b); \
- BLI_assert(g_buffer_desps[_BUFFER_INDEX(name)] & _MDEPS_CREATE1(b))
+ g_buffer_deps_d[_BUFFER_INDEX(name)] |= _MDEPS_CREATE1(b); \
+ BLI_assert(g_buffer_deps[_BUFFER_INDEX(name)] & _MDEPS_CREATE1(b))
# define _MDEPS_ASSERT3(b, n1, n2) _MDEPS_ASSERT2(b, n1); _MDEPS_ASSERT2(b, n2)
# define _MDEPS_ASSERT4(b, n1, n2, n3) _MDEPS_ASSERT3(b, n1, n2); _MDEPS_ASSERT2(b, n3)
# define _MDEPS_ASSERT5(b, n1, n2, n3, n4) _MDEPS_ASSERT4(b, n1, n2, n3); _MDEPS_ASSERT2(b, n4)
@@ -120,7 +120,7 @@
# define _MDEPS_ASSERT8(b, n1, n2, n3, n4, n5, n6, n7) _MDEPS_ASSERT7(b, n1, n2, n3, n4, n5, n6); _MDEPS_ASSERT2(b, n7)
# define MDEPS_ASSERT(...) VA_NARGS_CALL_OVERLOAD(_MDEPS_ASSERT, __VA_ARGS__)
-# define MDEPS_ASSERT_MAP(name) BLI_assert(g_buffer_desps_d[_BUFFER_INDEX(name)] == g_buffer_desps[_BUFFER_INDEX(name)])
+# define MDEPS_ASSERT_MAP(name) BLI_assert(g_buffer_deps_d[_BUFFER_INDEX(name)] == g_buffer_deps[_BUFFER_INDEX(name)])
#else
# define MDEPS_ASSERT(...)
# define MDEPS_ASSERT_MAP(name)
@@ -128,7 +128,7 @@
/* clang-format on */
-static const DRWBatchFlag g_buffer_desps[] = {
+static const DRWBatchFlag g_buffer_deps[] = {
MDEPS_CREATE(vbo.pos_nor,
batch.surface,
batch.surface_weights,
@@ -215,7 +215,7 @@ static const DRWBatchFlag g_buffer_desps[] = {
};
#ifndef NDEBUG
-static DRWBatchFlag g_buffer_desps_d[sizeof(g_buffer_desps)] = {0};
+static DRWBatchFlag g_buffer_deps_d[sizeof(g_buffer_deps)] = {0};
#endif
static void mesh_batch_cache_discard_surface_batches(MeshBatchCache *cache);
diff --git a/source/blender/draw/intern/draw_manager_texture.c b/source/blender/draw/intern/draw_manager_texture.c
index 73afdd6e1e3..99e8ba968a2 100644
--- a/source/blender/draw/intern/draw_manager_texture.c
+++ b/source/blender/draw/intern/draw_manager_texture.c
@@ -83,8 +83,8 @@ GPUTexture *DRW_texture_create_1d(int w,
DRWTextureFlag flags,
const float *fpixels)
{
- int mips = (flags & DRW_TEX_MIPMAP) ? 9999 : 1;
- GPUTexture *tex = GPU_texture_create_1d(__func__, w, mips, format, fpixels);
+ int mip_len = (flags & DRW_TEX_MIPMAP) ? 9999 : 1;
+ GPUTexture *tex = GPU_texture_create_1d(__func__, w, mip_len, format, fpixels);
drw_texture_set_parameters(tex, flags);
return tex;
@@ -93,8 +93,8 @@ GPUTexture *DRW_texture_create_1d(int w,
GPUTexture *DRW_texture_create_2d(
int w, int h, eGPUTextureFormat format, DRWTextureFlag flags, const float *fpixels)
{
- int mips = (flags & DRW_TEX_MIPMAP) ? 9999 : 1;
- GPUTexture *tex = GPU_texture_create_2d(__func__, w, h, mips, format, fpixels);
+ int mip_len = (flags & DRW_TEX_MIPMAP) ? 9999 : 1;
+ GPUTexture *tex = GPU_texture_create_2d(__func__, w, h, mip_len, format, fpixels);
drw_texture_set_parameters(tex, flags);
return tex;
@@ -103,8 +103,8 @@ GPUTexture *DRW_texture_create_2d(
GPUTexture *DRW_texture_create_2d_array(
int w, int h, int d, eGPUTextureFormat format, DRWTextureFlag flags, const float *fpixels)
{
- int mips = (flags & DRW_TEX_MIPMAP) ? 9999 : 1;
- GPUTexture *tex = GPU_texture_create_2d_array(__func__, w, h, d, mips, format, fpixels);
+ int mip_len = (flags & DRW_TEX_MIPMAP) ? 9999 : 1;
+ GPUTexture *tex = GPU_texture_create_2d_array(__func__, w, h, d, mip_len, format, fpixels);
drw_texture_set_parameters(tex, flags);
return tex;
@@ -113,9 +113,9 @@ GPUTexture *DRW_texture_create_2d_array(
GPUTexture *DRW_texture_create_3d(
int w, int h, int d, eGPUTextureFormat format, DRWTextureFlag flags, const float *fpixels)
{
- int mips = (flags & DRW_TEX_MIPMAP) ? 9999 : 1;
+ int mip_len = (flags & DRW_TEX_MIPMAP) ? 9999 : 1;
GPUTexture *tex = GPU_texture_create_3d(
- __func__, w, h, d, mips, format, GPU_DATA_FLOAT, fpixels);
+ __func__, w, h, d, mip_len, format, GPU_DATA_FLOAT, fpixels);
drw_texture_set_parameters(tex, flags);
return tex;
@@ -126,8 +126,8 @@ GPUTexture *DRW_texture_create_cube(int w,
DRWTextureFlag flags,
const float *fpixels)
{
- int mips = (flags & DRW_TEX_MIPMAP) ? 9999 : 1;
- GPUTexture *tex = GPU_texture_create_cube(__func__, w, mips, format, fpixels);
+ int mip_len = (flags & DRW_TEX_MIPMAP) ? 9999 : 1;
+ GPUTexture *tex = GPU_texture_create_cube(__func__, w, mip_len, format, fpixels);
drw_texture_set_parameters(tex, flags);
return tex;
}
@@ -135,8 +135,8 @@ GPUTexture *DRW_texture_create_cube(int w,
GPUTexture *DRW_texture_create_cube_array(
int w, int d, eGPUTextureFormat format, DRWTextureFlag flags, const float *fpixels)
{
- int mips = (flags & DRW_TEX_MIPMAP) ? 9999 : 1;
- GPUTexture *tex = GPU_texture_create_cube_array(__func__, w, d, mips, format, fpixels);
+ int mip_len = (flags & DRW_TEX_MIPMAP) ? 9999 : 1;
+ GPUTexture *tex = GPU_texture_create_cube_array(__func__, w, d, mip_len, format, fpixels);
drw_texture_set_parameters(tex, flags);
return tex;
}
diff --git a/source/blender/draw/intern/draw_view.c b/source/blender/draw/intern/draw_view.c
index ae2c66881ff..90bb3762473 100644
--- a/source/blender/draw/intern/draw_view.c
+++ b/source/blender/draw/intern/draw_view.c
@@ -211,8 +211,17 @@ static bool is_cursor_visible_2d(const DRWContextState *draw_ctx)
return false;
}
SpaceImage *sima = (SpaceImage *)space_data;
- if (sima->mode != SI_MODE_UV) {
- return false;
+ switch (sima->mode) {
+ case SI_MODE_VIEW:
+ return false;
+ break;
+ case SI_MODE_PAINT:
+ return false;
+ break;
+ case SI_MODE_MASK:
+ break;
+ case SI_MODE_UV:
+ break;
}
return (sima->overlay.flag & SI_OVERLAY_SHOW_OVERLAYS) != 0;
}
diff --git a/source/blender/editors/animation/CMakeLists.txt b/source/blender/editors/animation/CMakeLists.txt
index 7a53b54b5a4..d9f52d90766 100644
--- a/source/blender/editors/animation/CMakeLists.txt
+++ b/source/blender/editors/animation/CMakeLists.txt
@@ -47,7 +47,7 @@ set(SRC
keyframes_draw.c
keyframes_edit.c
keyframes_general.c
- keyframes_keylist.c
+ keyframes_keylist.cc
keyframing.c
keyingsets.c
time_scrub_ui.c
diff --git a/source/blender/editors/animation/anim_draw.c b/source/blender/editors/animation/anim_draw.c
index 735f3b86924..6d272bfc180 100644
--- a/source/blender/editors/animation/anim_draw.c
+++ b/source/blender/editors/animation/anim_draw.c
@@ -495,7 +495,7 @@ static bool find_prev_next_keyframes(struct bContext *C, int *r_nextfra, int *r_
Mask *mask = CTX_data_edit_mask(C);
bDopeSheet ads = {NULL};
struct AnimKeylist *keylist = ED_keylist_create();
- ActKeyColumn *aknext, *akprev;
+ const ActKeyColumn *aknext, *akprev;
float cfranext, cfraprev;
bool donenext = false, doneprev = false;
int nextcount = 0, prevcount = 0;
diff --git a/source/blender/editors/animation/anim_ipo_utils.c b/source/blender/editors/animation/anim_ipo_utils.c
index 5992545bdbe..eda87cf1897 100644
--- a/source/blender/editors/animation/anim_ipo_utils.c
+++ b/source/blender/editors/animation/anim_ipo_utils.c
@@ -134,6 +134,28 @@ int getname_anim_fcurve(char *name, ID *id, FCurve *fcu)
else {
structname = RNA_struct_ui_name(ptr.type);
}
+
+ /* For the VSE, a strip's 'Transform' or 'Crop' is a nested (under Sequence) struct, but
+ * displaying the struct name alone is no meaningful information (and also cannot be
+ * filtered well), same for modifiers. So display strip name alongside as well. */
+ if (GS(ptr.owner_id->name) == ID_SCE) {
+ if (BLI_str_startswith(fcu->rna_path, "sequence_editor.sequences_all[\"")) {
+ if (strstr(fcu->rna_path, ".transform.") || strstr(fcu->rna_path, ".crop.") ||
+ strstr(fcu->rna_path, ".modifiers[")) {
+ char *stripname = BLI_str_quoted_substrN(fcu->rna_path, "sequences_all[");
+ const char *structname_all = BLI_sprintfN(
+ "%s : %s", stripname ? stripname : "", structname);
+ if (free_structname) {
+ MEM_freeN((void *)structname);
+ }
+ if (stripname) {
+ MEM_freeN(stripname);
+ }
+ structname = structname_all;
+ free_structname = 1;
+ }
+ }
+ }
}
/* Property Name is straightforward */
diff --git a/source/blender/editors/animation/fmodifier_ui.c b/source/blender/editors/animation/fmodifier_ui.c
index 31552330071..40871fba2be 100644
--- a/source/blender/editors/animation/fmodifier_ui.c
+++ b/source/blender/editors/animation/fmodifier_ui.c
@@ -672,10 +672,7 @@ static void fmod_envelope_deletepoint_cb(bContext *UNUSED(C), void *fcm_dv, void
}
else {
/* just free array, since the only vert was deleted */
- if (env->data) {
- MEM_freeN(env->data);
- env->data = NULL;
- }
+ MEM_SAFE_FREE(env->data);
env->totvert = 0;
}
}
diff --git a/source/blender/editors/animation/keyframes_draw.c b/source/blender/editors/animation/keyframes_draw.c
index deed79942ac..61918871b90 100644
--- a/source/blender/editors/animation/keyframes_draw.c
+++ b/source/blender/editors/animation/keyframes_draw.c
@@ -25,6 +25,8 @@
#include <float.h>
+#include "MEM_guardedalloc.h"
+
#include "BLI_dlrbTree.h"
#include "BLI_listbase.h"
#include "BLI_rect.h"
@@ -55,11 +57,7 @@ void draw_keyframe_shape(float x,
short key_type,
short mode,
float alpha,
- uint pos_id,
- uint size_id,
- uint color_id,
- uint outline_color_id,
- uint flags_id,
+ const KeyframeShaderBindings *sh_bindings,
short handle_type,
short extreme_type)
{
@@ -176,334 +174,563 @@ void draw_keyframe_shape(float x,
}
}
- immAttr1f(size_id, size);
- immAttr4ubv(color_id, fill_col);
- immAttr4ubv(outline_color_id, outline_col);
- immAttr1u(flags_id, flags);
- immVertex2f(pos_id, x, y);
+ immAttr1f(sh_bindings->size_id, size);
+ immAttr4ubv(sh_bindings->color_id, fill_col);
+ immAttr4ubv(sh_bindings->outline_color_id, outline_col);
+ immAttr1u(sh_bindings->flags_id, flags);
+ immVertex2f(sh_bindings->pos_id, x, y);
}
-static void draw_keylist(View2D *v2d,
- const struct AnimKeylist *keylist,
- float ypos,
- float yscale_fac,
- bool channelLocked,
- int saction_flag)
-{
- const float icon_sz = U.widget_unit * 0.5f * yscale_fac;
- const float half_icon_sz = 0.5f * icon_sz;
- const float smaller_sz = 0.35f * icon_sz;
- const float ipo_sz = 0.1f * icon_sz;
- const float gpencil_sz = smaller_sz * 0.8f;
- const float screenspace_margin = (0.35f * (float)UI_UNIT_X) / UI_view2d_scale_get_x(v2d);
+/* Common attributes shared between the draw calls. */
+typedef struct DrawKeylistUIData {
+ float alpha;
+ float icon_sz;
+ float half_icon_sz;
+ float smaller_sz;
+ float ipo_sz;
+ float gpencil_sz;
+ float screenspace_margin;
+ float sel_color[4];
+ float unsel_color[4];
+ float sel_mhcol[4];
+ float unsel_mhcol[4];
+ float ipo_color[4];
+ float ipo_color_mix[4];
+ /* Show interpolation and handle type? */
+ bool show_ipo;
+} DrawKeylistUIData;
+
+static void draw_keylist_ui_data_init(DrawKeylistUIData *ctx,
+ View2D *v2d,
+ float yscale_fac,
+ bool channel_locked,
+ eSAction_Flag saction_flag)
+{
/* locked channels are less strongly shown, as feedback for locked channels in DopeSheet */
/* TODO: allow this opacity factor to be themed? */
- float alpha = channelLocked ? 0.25f : 1.0f;
+ ctx->alpha = channel_locked ? 0.25f : 1.0f;
+
+ ctx->icon_sz = U.widget_unit * 0.5f * yscale_fac;
+ ctx->half_icon_sz = 0.5f * ctx->icon_sz;
+ ctx->smaller_sz = 0.35f * ctx->icon_sz;
+ ctx->ipo_sz = 0.1f * ctx->icon_sz;
+ ctx->gpencil_sz = ctx->smaller_sz * 0.8f;
+ ctx->screenspace_margin = (0.35f * (float)UI_UNIT_X) / UI_view2d_scale_get_x(v2d);
+
+ ctx->show_ipo = (saction_flag & SACTION_SHOW_INTERPOLATION) != 0;
+
+ UI_GetThemeColor4fv(TH_STRIP_SELECT, ctx->sel_color);
+ UI_GetThemeColor4fv(TH_STRIP, ctx->unsel_color);
+ UI_GetThemeColor4fv(TH_DOPESHEET_IPOLINE, ctx->ipo_color);
+
+ ctx->sel_color[3] *= ctx->alpha;
+ ctx->unsel_color[3] *= ctx->alpha;
+ ctx->ipo_color[3] *= ctx->alpha;
+
+ copy_v4_v4(ctx->sel_mhcol, ctx->sel_color);
+ ctx->sel_mhcol[3] *= 0.8f;
+ copy_v4_v4(ctx->unsel_mhcol, ctx->unsel_color);
+ ctx->unsel_mhcol[3] *= 0.8f;
+ copy_v4_v4(ctx->ipo_color_mix, ctx->ipo_color);
+ ctx->ipo_color_mix[3] *= 0.5f;
+}
- /* Show interpolation and handle type? */
- bool show_ipo = (saction_flag & SACTION_SHOW_INTERPOLATION) != 0;
- /* draw keyblocks */
- float sel_color[4], unsel_color[4];
- float sel_mhcol[4], unsel_mhcol[4];
- float ipo_color[4], ipo_color_mix[4];
-
- /* cache colors first */
- UI_GetThemeColor4fv(TH_STRIP_SELECT, sel_color);
- UI_GetThemeColor4fv(TH_STRIP, unsel_color);
- UI_GetThemeColor4fv(TH_DOPESHEET_IPOLINE, ipo_color);
-
- sel_color[3] *= alpha;
- unsel_color[3] *= alpha;
- ipo_color[3] *= alpha;
-
- copy_v4_v4(sel_mhcol, sel_color);
- sel_mhcol[3] *= 0.8f;
- copy_v4_v4(unsel_mhcol, unsel_color);
- unsel_mhcol[3] *= 0.8f;
- copy_v4_v4(ipo_color_mix, ipo_color);
- ipo_color_mix[3] *= 0.5f;
-
- const ListBase *keys = ED_keylist_listbase(keylist);
-
- LISTBASE_FOREACH (ActKeyColumn *, ab, keys) {
- /* Draw grease pencil bars between keyframes. */
- if ((ab->next != NULL) && (ab->block.flag & ACTKEYBLOCK_FLAG_GPENCIL)) {
- UI_draw_roundbox_corner_set(UI_CNR_TOP_RIGHT | UI_CNR_BOTTOM_RIGHT);
- float size = 1.0f;
- switch (ab->next->key_type) {
- case BEZT_KEYTYPE_BREAKDOWN:
- case BEZT_KEYTYPE_MOVEHOLD:
- case BEZT_KEYTYPE_JITTER:
- size *= 0.5f;
- break;
- case BEZT_KEYTYPE_KEYFRAME:
- size *= 0.8f;
- break;
- default:
- break;
- }
- UI_draw_roundbox_4fv(
- &(const rctf){
- .xmin = ab->cfra,
- .xmax = min_ff(ab->next->cfra - (screenspace_margin * size), ab->next->cfra),
- .ymin = ypos - gpencil_sz,
- .ymax = ypos + gpencil_sz,
- },
- true,
- 0.25f * (float)UI_UNIT_X,
- (ab->block.sel) ? sel_mhcol : unsel_mhcol);
- }
- else {
- /* Draw other types. */
- UI_draw_roundbox_corner_set(UI_CNR_NONE);
-
- int valid_hold = actkeyblock_get_valid_hold(ab);
- if (valid_hold != 0) {
- if ((valid_hold & ACTKEYBLOCK_FLAG_STATIC_HOLD) == 0) {
- /* draw "moving hold" long-keyframe block - slightly smaller */
- UI_draw_roundbox_4fv(
- &(const rctf){
- .xmin = ab->cfra,
- .xmax = ab->next->cfra,
- .ymin = ypos - smaller_sz,
- .ymax = ypos + smaller_sz,
- },
- true,
- 3.0f,
- (ab->block.sel) ? sel_mhcol : unsel_mhcol);
- }
- else {
- /* draw standard long-keyframe block */
- UI_draw_roundbox_4fv(
- &(const rctf){
- .xmin = ab->cfra,
- .xmax = ab->next->cfra,
- .ymin = ypos - half_icon_sz,
- .ymax = ypos + half_icon_sz,
- },
- true,
- 3.0f,
- (ab->block.sel) ? sel_color : unsel_color);
- }
- }
- if (show_ipo && actkeyblock_is_valid(ab) && (ab->block.flag & ACTKEYBLOCK_FLAG_NON_BEZIER)) {
- /* draw an interpolation line */
- UI_draw_roundbox_4fv(
- &(const rctf){
- .xmin = ab->cfra,
- .xmax = ab->next->cfra,
- .ymin = ypos - ipo_sz,
- .ymax = ypos + ipo_sz,
- },
- true,
- 3.0f,
- (ab->block.conflict & ACTKEYBLOCK_FLAG_NON_BEZIER) ? ipo_color_mix : ipo_color);
- }
- }
+static void draw_keylist_block_gpencil(const DrawKeylistUIData *ctx,
+ const ActKeyColumn *ab,
+ float ypos)
+{
+ UI_draw_roundbox_corner_set(UI_CNR_TOP_RIGHT | UI_CNR_BOTTOM_RIGHT);
+ float size = 1.0f;
+ switch (ab->next->key_type) {
+ case BEZT_KEYTYPE_BREAKDOWN:
+ case BEZT_KEYTYPE_MOVEHOLD:
+ case BEZT_KEYTYPE_JITTER:
+ size *= 0.5f;
+ break;
+ case BEZT_KEYTYPE_KEYFRAME:
+ size *= 0.8f;
+ break;
+ default:
+ break;
}
+ UI_draw_roundbox_4fv(
+ &(const rctf){
+ .xmin = ab->cfra,
+ .xmax = min_ff(ab->next->cfra - (ctx->screenspace_margin * size), ab->next->cfra),
+ .ymin = ypos - ctx->gpencil_sz,
+ .ymax = ypos + ctx->gpencil_sz,
+ },
+ true,
+ 0.25f * (float)UI_UNIT_X,
+ (ab->block.sel) ? ctx->sel_mhcol : ctx->unsel_mhcol);
+}
- GPU_blend(GPU_BLEND_ALPHA);
+static void draw_keylist_block_moving_hold(const DrawKeylistUIData *ctx,
+ const ActKeyColumn *ab,
+ float ypos)
+{
- /* count keys */
- uint key_len = 0;
- LISTBASE_FOREACH (ActKeyColumn *, ak, keys) {
- /* Optimization: if keyframe doesn't appear within 5 units (screenspace)
- * in visible area, don't draw.
- * This might give some improvements,
- * since we current have to flip between view/region matrices.
- */
- if (IN_RANGE_INCL(ak->cfra, v2d->cur.xmin, v2d->cur.xmax)) {
- key_len++;
- }
- }
+ UI_draw_roundbox_4fv(
+ &(const rctf){
+ .xmin = ab->cfra,
+ .xmax = ab->next->cfra,
+ .ymin = ypos - ctx->smaller_sz,
+ .ymax = ypos + ctx->smaller_sz,
+ },
+ true,
+ 3.0f,
+ (ab->block.sel) ? ctx->sel_mhcol : ctx->unsel_mhcol);
+}
+
+static void draw_keylist_block_standard(const DrawKeylistUIData *ctx,
+ const ActKeyColumn *ab,
+ float ypos)
+{
+ UI_draw_roundbox_4fv(
+ &(const rctf){
+ .xmin = ab->cfra,
+ .xmax = ab->next->cfra,
+ .ymin = ypos - ctx->half_icon_sz,
+ .ymax = ypos + ctx->half_icon_sz,
+ },
+ true,
+ 3.0f,
+ (ab->block.sel) ? ctx->sel_color : ctx->unsel_color);
+}
+
+static void draw_keylist_block_interpolation_line(const DrawKeylistUIData *ctx,
+ const ActKeyColumn *ab,
+ float ypos)
+{
+ UI_draw_roundbox_4fv(
+ &(const rctf){
+ .xmin = ab->cfra,
+ .xmax = ab->next->cfra,
+ .ymin = ypos - ctx->ipo_sz,
+ .ymax = ypos + ctx->ipo_sz,
+ },
+ true,
+ 3.0f,
+ (ab->block.conflict & ACTKEYBLOCK_FLAG_NON_BEZIER) ? ctx->ipo_color_mix : ctx->ipo_color);
+}
+
+static void draw_keylist_block(const DrawKeylistUIData *ctx, const ActKeyColumn *ab, float ypos)
+{
- if (key_len > 0) {
- /* draw keys */
- GPUVertFormat *format = immVertexFormat();
- uint pos_id = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- uint size_id = GPU_vertformat_attr_add(format, "size", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
- uint color_id = GPU_vertformat_attr_add(
- format, "color", GPU_COMP_U8, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
- uint outline_color_id = GPU_vertformat_attr_add(
- format, "outlineColor", GPU_COMP_U8, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
- uint flags_id = GPU_vertformat_attr_add(format, "flags", GPU_COMP_U32, 1, GPU_FETCH_INT);
-
- GPU_program_point_size(true);
- immBindBuiltinProgram(GPU_SHADER_KEYFRAME_DIAMOND);
- immUniform1f("outline_scale", 1.0f);
- immUniform2f("ViewportSize", BLI_rcti_size_x(&v2d->mask) + 1, BLI_rcti_size_y(&v2d->mask) + 1);
- immBegin(GPU_PRIM_POINTS, key_len);
-
- short handle_type = KEYFRAME_HANDLE_NONE, extreme_type = KEYFRAME_EXTREME_NONE;
-
- LISTBASE_FOREACH (ActKeyColumn *, ak, keys) {
- if (IN_RANGE_INCL(ak->cfra, v2d->cur.xmin, v2d->cur.xmax)) {
- if (show_ipo) {
- handle_type = ak->handle_type;
- }
- if (saction_flag & SACTION_SHOW_EXTREMES) {
- extreme_type = ak->extreme_type;
- }
-
- draw_keyframe_shape(ak->cfra,
- ypos,
- icon_sz,
- (ak->sel & SELECT),
- ak->key_type,
- KEYFRAME_SHAPE_BOTH,
- alpha,
- pos_id,
- size_id,
- color_id,
- outline_color_id,
- flags_id,
- handle_type,
- extreme_type);
+ /* Draw grease pencil bars between keyframes. */
+ if ((ab->next != NULL) && (ab->block.flag & ACTKEYBLOCK_FLAG_GPENCIL)) {
+ draw_keylist_block_gpencil(ctx, ab, ypos);
+ }
+ else {
+ /* Draw other types. */
+ UI_draw_roundbox_corner_set(UI_CNR_NONE);
+
+ int valid_hold = actkeyblock_get_valid_hold(ab);
+ if (valid_hold != 0) {
+ if ((valid_hold & ACTKEYBLOCK_FLAG_STATIC_HOLD) == 0) {
+ /* draw "moving hold" long-keyframe block - slightly smaller */
+ draw_keylist_block_moving_hold(ctx, ab, ypos);
+ }
+ else {
+ /* draw standard long-keyframe block */
+ draw_keylist_block_standard(ctx, ab, ypos);
}
}
-
- immEnd();
- GPU_program_point_size(false);
- immUnbindProgram();
+ if (ctx->show_ipo && actkeyblock_is_valid(ab) &&
+ (ab->block.flag & ACTKEYBLOCK_FLAG_NON_BEZIER)) {
+ /* draw an interpolation line */
+ draw_keylist_block_interpolation_line(ctx, ab, ypos);
+ }
}
-
- GPU_blend(GPU_BLEND_NONE);
}
-/* *************************** Channel Drawing Funcs *************************** */
+static void draw_keylist_blocks(const DrawKeylistUIData *ctx,
+ const ListBase * /*ActKeyColumn*/ columns,
+ float ypos)
+{
+ LISTBASE_FOREACH (ActKeyColumn *, ab, columns) {
+ draw_keylist_block(ctx, ab, ypos);
+ }
+}
-void draw_summary_channel(
- View2D *v2d, bAnimContext *ac, float ypos, float yscale_fac, int saction_flag)
+static bool draw_keylist_is_visible_key(const View2D *v2d, const ActKeyColumn *ak)
{
- struct AnimKeylist *keylist = ED_keylist_create();
+ return IN_RANGE_INCL(ak->cfra, v2d->cur.xmin, v2d->cur.xmax);
+}
- saction_flag &= ~SACTION_SHOW_EXTREMES;
+static void draw_keylist_keys(const DrawKeylistUIData *ctx,
+ View2D *v2d,
+ const KeyframeShaderBindings *sh_bindings,
+ const ListBase * /*ActKeyColumn*/ keys,
+ float ypos,
+ eSAction_Flag saction_flag)
+{
+ short handle_type = KEYFRAME_HANDLE_NONE, extreme_type = KEYFRAME_EXTREME_NONE;
- summary_to_keylist(ac, keylist, saction_flag);
+ LISTBASE_FOREACH (ActKeyColumn *, ak, keys) {
+ if (draw_keylist_is_visible_key(v2d, ak)) {
+ if (ctx->show_ipo) {
+ handle_type = ak->handle_type;
+ }
+ if (saction_flag & SACTION_SHOW_EXTREMES) {
+ extreme_type = ak->extreme_type;
+ }
- draw_keylist(v2d, keylist, ypos, yscale_fac, false, saction_flag);
+ draw_keyframe_shape(ak->cfra,
+ ypos,
+ ctx->icon_sz,
+ (ak->sel & SELECT),
+ ak->key_type,
+ KEYFRAME_SHAPE_BOTH,
+ ctx->alpha,
+ sh_bindings,
+ handle_type,
+ extreme_type);
+ }
+ }
+}
- ED_keylist_free(keylist);
+/* *************************** Drawing Stack *************************** */
+typedef enum eAnimKeylistDrawListElemType {
+ ANIM_KEYLIST_SUMMARY,
+ ANIM_KEYLIST_SCENE,
+ ANIM_KEYLIST_OBJECT,
+ ANIM_KEYLIST_FCURVE,
+ ANIM_KEYLIST_ACTION,
+ ANIM_KEYLIST_AGROUP,
+ ANIM_KEYLIST_GP_LAYER,
+ ANIM_KEYLIST_MASK_LAYER,
+} eAnimKeylistDrawListElemType;
+
+typedef struct AnimKeylistDrawListElem {
+ struct AnimKeylistDrawListElem *next, *prev;
+ struct AnimKeylist *keylist;
+ eAnimKeylistDrawListElemType type;
+
+ float yscale_fac;
+ float ypos;
+ eSAction_Flag saction_flag;
+ bool channel_locked;
+
+ bAnimContext *ac;
+ bDopeSheet *ads;
+ Scene *sce;
+ Object *ob;
+ AnimData *adt;
+ FCurve *fcu;
+ bAction *act;
+ bActionGroup *agrp;
+ bGPDlayer *gpl;
+ MaskLayer *masklay;
+
+} AnimKeylistDrawListElem;
+
+static void ED_keylist_draw_list_elem_build_keylist(AnimKeylistDrawListElem *elem)
+{
+ switch (elem->type) {
+ case ANIM_KEYLIST_SUMMARY: {
+ summary_to_keylist(elem->ac, elem->keylist, elem->saction_flag);
+ break;
+ }
+ case ANIM_KEYLIST_SCENE: {
+ scene_to_keylist(elem->ads, elem->sce, elem->keylist, elem->saction_flag);
+ break;
+ }
+ case ANIM_KEYLIST_OBJECT: {
+ ob_to_keylist(elem->ads, elem->ob, elem->keylist, elem->saction_flag);
+ break;
+ }
+ case ANIM_KEYLIST_FCURVE: {
+ fcurve_to_keylist(elem->adt, elem->fcu, elem->keylist, elem->saction_flag);
+ break;
+ }
+ case ANIM_KEYLIST_ACTION: {
+ action_to_keylist(elem->adt, elem->act, elem->keylist, elem->saction_flag);
+ break;
+ }
+ case ANIM_KEYLIST_AGROUP: {
+ agroup_to_keylist(elem->adt, elem->agrp, elem->keylist, elem->saction_flag);
+ break;
+ }
+ case ANIM_KEYLIST_GP_LAYER: {
+ gpl_to_keylist(elem->ads, elem->gpl, elem->keylist);
+ break;
+ }
+ case ANIM_KEYLIST_MASK_LAYER: {
+ mask_to_keylist(elem->ads, elem->masklay, elem->keylist);
+ break;
+ }
+ }
}
-void draw_scene_channel(
- View2D *v2d, bDopeSheet *ads, Scene *sce, float ypos, float yscale_fac, int saction_flag)
+static void ED_keylist_draw_list_elem_draw_blocks(AnimKeylistDrawListElem *elem, View2D *v2d)
{
- struct AnimKeylist *keylist = ED_keylist_create();
+ DrawKeylistUIData ctx;
+ draw_keylist_ui_data_init(&ctx, v2d, elem->yscale_fac, elem->channel_locked, elem->saction_flag);
- saction_flag &= ~SACTION_SHOW_EXTREMES;
+ const ListBase *keys = ED_keylist_listbase(elem->keylist);
+ draw_keylist_blocks(&ctx, keys, elem->ypos);
+}
- scene_to_keylist(ads, sce, keylist, saction_flag);
+static void ED_keylist_draw_list_elem_draw_keys(AnimKeylistDrawListElem *elem,
+ View2D *v2d,
+ const KeyframeShaderBindings *sh_bindings)
+{
+ DrawKeylistUIData ctx;
+ draw_keylist_ui_data_init(&ctx, v2d, elem->yscale_fac, elem->channel_locked, elem->saction_flag);
+ const ListBase *keys = ED_keylist_listbase(elem->keylist);
+ draw_keylist_keys(&ctx, v2d, sh_bindings, keys, elem->ypos, elem->saction_flag);
+}
- draw_keylist(v2d, keylist, ypos, yscale_fac, false, saction_flag);
+typedef struct AnimKeylistDrawList {
+ ListBase /* AnimKeylistDrawListElem*/ channels;
+} AnimKeylistDrawList;
- ED_keylist_free(keylist);
+AnimKeylistDrawList *ED_keylist_draw_list_create(void)
+{
+ return MEM_callocN(sizeof(AnimKeylistDrawList), __func__);
}
-void draw_object_channel(
- View2D *v2d, bDopeSheet *ads, Object *ob, float ypos, float yscale_fac, int saction_flag)
+static void ED_keylist_draw_list_build_keylists(AnimKeylistDrawList *draw_list)
{
- struct AnimKeylist *keylist = ED_keylist_create();
+ LISTBASE_FOREACH (AnimKeylistDrawListElem *, elem, &draw_list->channels) {
+ ED_keylist_draw_list_elem_build_keylist(elem);
+ }
+}
- saction_flag &= ~SACTION_SHOW_EXTREMES;
+static void ED_keylist_draw_list_draw_blocks(AnimKeylistDrawList *draw_list, View2D *v2d)
+{
+ LISTBASE_FOREACH (AnimKeylistDrawListElem *, elem, &draw_list->channels) {
+ ED_keylist_draw_list_elem_draw_blocks(elem, v2d);
+ }
+}
- ob_to_keylist(ads, ob, keylist, saction_flag);
+static int ED_keylist_draw_keylist_visible_key_len(const View2D *v2d,
+ const ListBase * /*ActKeyColumn*/ keys)
+{
+ /* count keys */
+ uint len = 0;
- draw_keylist(v2d, keylist, ypos, yscale_fac, false, saction_flag);
+ LISTBASE_FOREACH (ActKeyColumn *, ak, keys) {
+ /* Optimization: if keyframe doesn't appear within 5 units (screenspace)
+ * in visible area, don't draw.
+ * This might give some improvements,
+ * since we current have to flip between view/region matrices.
+ */
+ if (draw_keylist_is_visible_key(v2d, ak)) {
+ len++;
+ }
+ }
+ return len;
+}
- ED_keylist_free(keylist);
+static int ED_keylist_draw_list_visible_key_len(const AnimKeylistDrawList *draw_list,
+ const View2D *v2d)
+{
+ uint len = 0;
+ LISTBASE_FOREACH (AnimKeylistDrawListElem *, elem, &draw_list->channels) {
+ const ListBase *keys = ED_keylist_listbase(elem->keylist);
+ len += ED_keylist_draw_keylist_visible_key_len(v2d, keys);
+ }
+ return len;
}
-void draw_fcurve_channel(
- View2D *v2d, AnimData *adt, FCurve *fcu, float ypos, float yscale_fac, int saction_flag)
+static void ED_keylist_draw_list_draw_keys(AnimKeylistDrawList *draw_list, View2D *v2d)
{
- struct AnimKeylist *keylist = ED_keylist_create();
+ const int visible_key_len = ED_keylist_draw_list_visible_key_len(draw_list, v2d);
+ if (visible_key_len == 0) {
+ return;
+ }
- bool locked = (fcu->flag & FCURVE_PROTECTED) ||
- ((fcu->grp) && (fcu->grp->flag & AGRP_PROTECTED)) ||
- ((adt && adt->action) && ID_IS_LINKED(adt->action));
+ GPU_blend(GPU_BLEND_ALPHA);
- fcurve_to_keylist(adt, fcu, keylist, saction_flag);
+ GPUVertFormat *format = immVertexFormat();
+ KeyframeShaderBindings sh_bindings;
+
+ sh_bindings.pos_id = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ sh_bindings.size_id = GPU_vertformat_attr_add(format, "size", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
+ sh_bindings.color_id = GPU_vertformat_attr_add(
+ format, "color", GPU_COMP_U8, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
+ sh_bindings.outline_color_id = GPU_vertformat_attr_add(
+ format, "outlineColor", GPU_COMP_U8, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
+ sh_bindings.flags_id = GPU_vertformat_attr_add(format, "flags", GPU_COMP_U32, 1, GPU_FETCH_INT);
+
+ GPU_program_point_size(true);
+ immBindBuiltinProgram(GPU_SHADER_KEYFRAME_DIAMOND);
+ immUniform1f("outline_scale", 1.0f);
+ immUniform2f("ViewportSize", BLI_rcti_size_x(&v2d->mask) + 1, BLI_rcti_size_y(&v2d->mask) + 1);
+ immBegin(GPU_PRIM_POINTS, visible_key_len);
+
+ LISTBASE_FOREACH (AnimKeylistDrawListElem *, elem, &draw_list->channels) {
+ ED_keylist_draw_list_elem_draw_keys(elem, v2d, &sh_bindings);
+ }
- draw_keylist(v2d, keylist, ypos, yscale_fac, locked, saction_flag);
+ immEnd();
+ GPU_program_point_size(false);
+ immUnbindProgram();
- ED_keylist_free(keylist);
+ GPU_blend(GPU_BLEND_NONE);
}
-void draw_agroup_channel(
- View2D *v2d, AnimData *adt, bActionGroup *agrp, float ypos, float yscale_fac, int saction_flag)
+static void ED_keylist_draw_list_draw(AnimKeylistDrawList *draw_list, View2D *v2d)
{
- struct AnimKeylist *keylist = ED_keylist_create();
-
- bool locked = (agrp->flag & AGRP_PROTECTED) ||
- ((adt && adt->action) && ID_IS_LINKED(adt->action));
-
- agroup_to_keylist(adt, agrp, keylist, saction_flag);
+ ED_keylist_draw_list_draw_blocks(draw_list, v2d);
+ ED_keylist_draw_list_draw_keys(draw_list, v2d);
+}
- draw_keylist(v2d, keylist, ypos, yscale_fac, locked, saction_flag);
+void ED_keylist_draw_list_flush(AnimKeylistDrawList *draw_list, View2D *v2d)
+{
+ ED_keylist_draw_list_build_keylists(draw_list);
+ ED_keylist_draw_list_draw(draw_list, v2d);
+}
- ED_keylist_free(keylist);
+void ED_keylist_draw_list_free(AnimKeylistDrawList *draw_list)
+{
+ LISTBASE_FOREACH (AnimKeylistDrawListElem *, elem, &draw_list->channels) {
+ ED_keylist_free(elem->keylist);
+ }
+ BLI_freelistN(&draw_list->channels);
+ MEM_freeN(draw_list);
}
-void draw_action_channel(
- View2D *v2d, AnimData *adt, bAction *act, float ypos, float yscale_fac, int saction_flag)
+static AnimKeylistDrawListElem *ed_keylist_draw_list_add_elem(
+ AnimKeylistDrawList *draw_list,
+ eAnimKeylistDrawListElemType elem_type,
+ float ypos,
+ float yscale_fac,
+ eSAction_Flag saction_flag)
{
- struct AnimKeylist *keylist = ED_keylist_create();
+ AnimKeylistDrawListElem *draw_elem = MEM_callocN(sizeof(AnimKeylistDrawListElem), __func__);
+ BLI_addtail(&draw_list->channels, draw_elem);
+ draw_elem->type = elem_type;
+ draw_elem->keylist = ED_keylist_create();
+ draw_elem->ypos = ypos;
+ draw_elem->yscale_fac = yscale_fac;
+ draw_elem->saction_flag = saction_flag;
+ return draw_elem;
+}
- bool locked = (act && ID_IS_LINKED(act));
+/* *************************** Channel Drawing Funcs *************************** */
+void draw_summary_channel(struct AnimKeylistDrawList *draw_list,
+ bAnimContext *ac,
+ float ypos,
+ float yscale_fac,
+ int saction_flag)
+{
saction_flag &= ~SACTION_SHOW_EXTREMES;
-
- action_to_keylist(adt, act, keylist, saction_flag);
-
- draw_keylist(v2d, keylist, ypos, yscale_fac, locked, saction_flag);
-
- ED_keylist_free(keylist);
+ AnimKeylistDrawListElem *draw_elem = ed_keylist_draw_list_add_elem(
+ draw_list, ANIM_KEYLIST_SUMMARY, ypos, yscale_fac, saction_flag);
+ draw_elem->ac = ac;
}
-void draw_gpencil_channel(
- View2D *v2d, bDopeSheet *ads, bGPdata *gpd, float ypos, float yscale_fac, int saction_flag)
+void draw_scene_channel(AnimKeylistDrawList *draw_list,
+ bDopeSheet *ads,
+ Scene *sce,
+ float ypos,
+ float yscale_fac,
+ int saction_flag)
{
- struct AnimKeylist *keylist = ED_keylist_create();
-
saction_flag &= ~SACTION_SHOW_EXTREMES;
+ AnimKeylistDrawListElem *draw_elem = ed_keylist_draw_list_add_elem(
+ draw_list, ANIM_KEYLIST_SCENE, ypos, yscale_fac, saction_flag);
+ draw_elem->ads = ads;
+ draw_elem->sce = sce;
+}
- gpencil_to_keylist(ads, gpd, keylist, false);
-
- draw_keylist(v2d, keylist, ypos, yscale_fac, false, saction_flag);
+void draw_object_channel(AnimKeylistDrawList *draw_list,
+ bDopeSheet *ads,
+ Object *ob,
+ float ypos,
+ float yscale_fac,
+ int saction_flag)
+{
+ saction_flag &= ~SACTION_SHOW_EXTREMES;
+ AnimKeylistDrawListElem *draw_elem = ed_keylist_draw_list_add_elem(
+ draw_list, ANIM_KEYLIST_OBJECT, ypos, yscale_fac, saction_flag);
+ draw_elem->ads = ads;
+ draw_elem->ob = ob;
+}
- ED_keylist_free(keylist);
+void draw_fcurve_channel(AnimKeylistDrawList *draw_list,
+ AnimData *adt,
+ FCurve *fcu,
+ float ypos,
+ float yscale_fac,
+ int saction_flag)
+{
+ const bool locked = (fcu->flag & FCURVE_PROTECTED) ||
+ ((fcu->grp) && (fcu->grp->flag & AGRP_PROTECTED)) ||
+ ((adt && adt->action) && ID_IS_LINKED(adt->action));
+
+ AnimKeylistDrawListElem *draw_elem = ed_keylist_draw_list_add_elem(
+ draw_list, ANIM_KEYLIST_FCURVE, ypos, yscale_fac, saction_flag);
+ draw_elem->adt = adt;
+ draw_elem->fcu = fcu;
+ draw_elem->channel_locked = locked;
}
-void draw_gpl_channel(
- View2D *v2d, bDopeSheet *ads, bGPDlayer *gpl, float ypos, float yscale_fac, int saction_flag)
+void draw_agroup_channel(AnimKeylistDrawList *draw_list,
+ AnimData *adt,
+ bActionGroup *agrp,
+ float ypos,
+ float yscale_fac,
+ int saction_flag)
{
- struct AnimKeylist *keylist = ED_keylist_create();
+ bool locked = (agrp->flag & AGRP_PROTECTED) ||
+ ((adt && adt->action) && ID_IS_LINKED(adt->action));
- bool locked = (gpl->flag & GP_LAYER_LOCKED) != 0;
+ AnimKeylistDrawListElem *draw_elem = ed_keylist_draw_list_add_elem(
+ draw_list, ANIM_KEYLIST_AGROUP, ypos, yscale_fac, saction_flag);
+ draw_elem->adt = adt;
+ draw_elem->agrp = agrp;
+ draw_elem->channel_locked = locked;
+}
- gpl_to_keylist(ads, gpl, keylist);
+void draw_action_channel(AnimKeylistDrawList *draw_list,
+ AnimData *adt,
+ bAction *act,
+ float ypos,
+ float yscale_fac,
+ int saction_flag)
+{
+ const bool locked = (act && ID_IS_LINKED(act));
+ saction_flag &= ~SACTION_SHOW_EXTREMES;
- draw_keylist(v2d, keylist, ypos, yscale_fac, locked, saction_flag);
+ AnimKeylistDrawListElem *draw_elem = ed_keylist_draw_list_add_elem(
+ draw_list, ANIM_KEYLIST_ACTION, ypos, yscale_fac, saction_flag);
+ draw_elem->adt = adt;
+ draw_elem->act = act;
+ draw_elem->channel_locked = locked;
+}
- ED_keylist_free(keylist);
+void draw_gpl_channel(AnimKeylistDrawList *draw_list,
+ bDopeSheet *ads,
+ bGPDlayer *gpl,
+ float ypos,
+ float yscale_fac,
+ int saction_flag)
+{
+ bool locked = (gpl->flag & GP_LAYER_LOCKED) != 0;
+ AnimKeylistDrawListElem *draw_elem = ed_keylist_draw_list_add_elem(
+ draw_list, ANIM_KEYLIST_GP_LAYER, ypos, yscale_fac, saction_flag);
+ draw_elem->ads = ads;
+ draw_elem->gpl = gpl;
+ draw_elem->channel_locked = locked;
}
-void draw_masklay_channel(View2D *v2d,
+void draw_masklay_channel(AnimKeylistDrawList *draw_list,
bDopeSheet *ads,
MaskLayer *masklay,
float ypos,
float yscale_fac,
int saction_flag)
{
- struct AnimKeylist *keylist = ED_keylist_create();
-
bool locked = (masklay->flag & MASK_LAYERFLAG_LOCKED) != 0;
-
- mask_to_keylist(ads, masklay, keylist);
-
- draw_keylist(v2d, keylist, ypos, yscale_fac, locked, saction_flag);
-
- ED_keylist_free(keylist);
+ AnimKeylistDrawListElem *draw_elem = ed_keylist_draw_list_add_elem(
+ draw_list, ANIM_KEYLIST_MASK_LAYER, ypos, yscale_fac, saction_flag);
+ draw_elem->ads = ads;
+ draw_elem->masklay = masklay;
+ draw_elem->channel_locked = locked;
}
diff --git a/source/blender/editors/animation/keyframes_general.c b/source/blender/editors/animation/keyframes_general.c
index eb91afa5c84..75ce62d5e27 100644
--- a/source/blender/editors/animation/keyframes_general.c
+++ b/source/blender/editors/animation/keyframes_general.c
@@ -92,10 +92,7 @@ void delete_fcurve_key(FCurve *fcu, int index, bool do_recalc)
fcu->totvert--;
if (fcu->totvert == 0) {
- if (fcu->bezt) {
- MEM_freeN(fcu->bezt);
- }
- fcu->bezt = NULL;
+ MEM_SAFE_FREE(fcu->bezt);
}
/* recalc handles - only if it won't cause problems */
@@ -136,10 +133,7 @@ bool delete_fcurve_keys(FCurve *fcu)
void clear_fcurve_keys(FCurve *fcu)
{
- if (fcu->bezt) {
- MEM_freeN(fcu->bezt);
- }
- fcu->bezt = NULL;
+ MEM_SAFE_FREE(fcu->bezt);
fcu->totvert = 0;
}
diff --git a/source/blender/editors/animation/keyframes_keylist.c b/source/blender/editors/animation/keyframes_keylist.cc
index 8f0f6d753be..f6ade11a517 100644
--- a/source/blender/editors/animation/keyframes_keylist.c
+++ b/source/blender/editors/animation/keyframes_keylist.cc
@@ -23,10 +23,10 @@
/* System includes ----------------------------------------------------- */
-#include <float.h>
-#include <math.h>
-#include <stdlib.h>
-#include <string.h>
+#include <cfloat>
+#include <cmath>
+#include <cstdlib>
+#include <cstring>
#include "MEM_guardedalloc.h"
@@ -47,11 +47,12 @@
#include "ED_anim_api.h"
#include "ED_keyframes_keylist.h"
+extern "C" {
/* *************************** Keyframe Processing *************************** */
-typedef struct AnimKeylist {
+struct AnimKeylist {
DLRBT_Tree keys;
-} AnimKeylist;
+};
static void ED_keylist_init(AnimKeylist *keylist)
{
@@ -60,7 +61,7 @@ static void ED_keylist_init(AnimKeylist *keylist)
AnimKeylist *ED_keylist_create(void)
{
- AnimKeylist *keylist = MEM_callocN(sizeof(AnimKeylist), __func__);
+ AnimKeylist *keylist = static_cast<AnimKeylist *>(MEM_callocN(sizeof(AnimKeylist), __func__));
ED_keylist_init(keylist);
return keylist;
}
@@ -72,37 +73,40 @@ void ED_keylist_free(AnimKeylist *keylist)
MEM_freeN(keylist);
}
-ActKeyColumn *ED_keylist_find_exact(const AnimKeylist *keylist, float cfra)
+const ActKeyColumn *ED_keylist_find_exact(const AnimKeylist *keylist, float cfra)
{
- return (ActKeyColumn *)BLI_dlrbTree_search_exact(&keylist->keys, compare_ak_cfraPtr, &cfra);
+ return (const ActKeyColumn *)BLI_dlrbTree_search_exact(
+ &keylist->keys, compare_ak_cfraPtr, &cfra);
}
-ActKeyColumn *ED_keylist_find_next(const AnimKeylist *keylist, float cfra)
+const ActKeyColumn *ED_keylist_find_next(const AnimKeylist *keylist, float cfra)
{
- return (ActKeyColumn *)BLI_dlrbTree_search_next(&keylist->keys, compare_ak_cfraPtr, &cfra);
+ return (const ActKeyColumn *)BLI_dlrbTree_search_next(&keylist->keys, compare_ak_cfraPtr, &cfra);
}
-ActKeyColumn *ED_keylist_find_prev(const AnimKeylist *keylist, float cfra)
+const ActKeyColumn *ED_keylist_find_prev(const AnimKeylist *keylist, float cfra)
{
- return (ActKeyColumn *)BLI_dlrbTree_search_prev(&keylist->keys, compare_ak_cfraPtr, &cfra);
+ return (const ActKeyColumn *)BLI_dlrbTree_search_prev(&keylist->keys, compare_ak_cfraPtr, &cfra);
}
/* TODO(jbakker): Should we change this to use `ED_keylist_find_next(keys, min_fra)` and only check
* boundary of `max_fra`. */
-ActKeyColumn *ED_keylist_find_any_between(const AnimKeylist *keylist, float min_fra, float max_fra)
+const ActKeyColumn *ED_keylist_find_any_between(const AnimKeylist *keylist,
+ const Range2f frame_range)
{
- for (ActKeyColumn *ak = keylist->keys.root; ak;
- ak = (ak->cfra < min_fra) ? ak->right : ak->left) {
- if (IN_RANGE(ak->cfra, min_fra, max_fra)) {
+ for (const ActKeyColumn *ak = static_cast<const ActKeyColumn *>(keylist->keys.root); ak;
+ ak = static_cast<const ActKeyColumn *>((ak->cfra < frame_range.min) ? ak->right :
+ ak->left)) {
+ if (range2f_in_range(&frame_range, ak->cfra)) {
return ak;
}
}
- return NULL;
+ return nullptr;
}
bool ED_keylist_is_empty(const struct AnimKeylist *keylist)
{
- return keylist->keys.root == NULL;
+ return keylist->keys.root == nullptr;
}
const struct ListBase *ED_keylist_listbase(const AnimKeylist *keylist)
@@ -128,12 +132,12 @@ bool ED_keylist_frame_range(const struct AnimKeylist *keylist, Range2f *r_frame_
}
/* ActKeyColumns (Keyframe Columns) ------------------------------------------ */
-BLI_INLINE bool is_cfra_eq(float a, float b)
+BLI_INLINE bool is_cfra_eq(const float a, const float b)
{
return IS_EQT(a, b, BEZT_BINARYSEARCH_THRESH);
}
-BLI_INLINE bool is_cfra_lt(float a, float b)
+BLI_INLINE bool is_cfra_lt(const float a, const float b)
{
return (b - a) > BEZT_BINARYSEARCH_THRESH;
}
@@ -143,8 +147,8 @@ BLI_INLINE bool is_cfra_lt(float a, float b)
short compare_ak_cfraPtr(void *node, void *data)
{
ActKeyColumn *ak = (ActKeyColumn *)node;
- const float *cframe = data;
- float val = *cframe;
+ const float *cframe = static_cast<const float *>(data);
+ const float val = *cframe;
if (is_cfra_eq(val, ak->cfra)) {
return 0;
@@ -159,16 +163,16 @@ short compare_ak_cfraPtr(void *node, void *data)
/* --------------- */
/* Set of references to three logically adjacent keys. */
-typedef struct BezTripleChain {
+struct BezTripleChain {
/* Current keyframe. */
BezTriple *cur;
- /* Logical neighbors. May be NULL. */
+ /* Logical neighbors. May be nullptr. */
BezTriple *prev, *next;
-} BezTripleChain;
+};
/* Categorize the interpolation & handle type of the keyframe. */
-static eKeyframeHandleDrawOpts bezt_handle_type(BezTriple *bezt)
+static eKeyframeHandleDrawOpts bezt_handle_type(const BezTriple *bezt)
{
if (bezt->h1 == HD_AUTO_ANIM && bezt->h2 == HD_AUTO_ANIM) {
return KEYFRAME_HANDLE_AUTO_CLAMP;
@@ -188,14 +192,14 @@ static eKeyframeHandleDrawOpts bezt_handle_type(BezTriple *bezt)
/* Determine if the keyframe is an extreme by comparing with neighbors.
* Ends of fixed-value sections and of the whole curve are also marked.
*/
-static eKeyframeExtremeDrawOpts bezt_extreme_type(BezTripleChain *chain)
+static eKeyframeExtremeDrawOpts bezt_extreme_type(const BezTripleChain *chain)
{
- if (chain->prev == NULL && chain->next == NULL) {
+ if (chain->prev == nullptr && chain->next == nullptr) {
return KEYFRAME_EXTREME_NONE;
}
/* Keyframe values for the current one and neighbors. */
- float cur_y = chain->cur->vec[1][1];
+ const float cur_y = chain->cur->vec[1][1];
float prev_y = cur_y, next_y = cur_y;
if (chain->prev && !IS_EQF(cur_y, chain->prev->vec[1][1])) {
@@ -216,22 +220,24 @@ static eKeyframeExtremeDrawOpts bezt_extreme_type(BezTripleChain *chain)
}
/* Bezier handle values for the overshoot check. */
- bool l_bezier = chain->prev && chain->prev->ipo == BEZT_IPO_BEZ;
- bool r_bezier = chain->next && chain->cur->ipo == BEZT_IPO_BEZ;
- float handle_l = l_bezier ? chain->cur->vec[0][1] : cur_y;
- float handle_r = r_bezier ? chain->cur->vec[2][1] : cur_y;
+ const bool l_bezier = chain->prev && chain->prev->ipo == BEZT_IPO_BEZ;
+ const bool r_bezier = chain->next && chain->cur->ipo == BEZT_IPO_BEZ;
+ const float handle_l = l_bezier ? chain->cur->vec[0][1] : cur_y;
+ const float handle_r = r_bezier ? chain->cur->vec[2][1] : cur_y;
/* Detect extremes. One of the neighbors is allowed to be equal to current. */
if (prev_y < cur_y || next_y < cur_y) {
- bool is_overshoot = (handle_l > cur_y || handle_r > cur_y);
+ const bool is_overshoot = (handle_l > cur_y || handle_r > cur_y);
- return KEYFRAME_EXTREME_MAX | (is_overshoot ? KEYFRAME_EXTREME_MIXED : 0);
+ return static_cast<eKeyframeExtremeDrawOpts>(KEYFRAME_EXTREME_MAX |
+ (is_overshoot ? KEYFRAME_EXTREME_MIXED : 0));
}
if (prev_y > cur_y || next_y > cur_y) {
- bool is_overshoot = (handle_l < cur_y || handle_r < cur_y);
+ const bool is_overshoot = (handle_l < cur_y || handle_r < cur_y);
- return KEYFRAME_EXTREME_MIN | (is_overshoot ? KEYFRAME_EXTREME_MIXED : 0);
+ return static_cast<eKeyframeExtremeDrawOpts>(KEYFRAME_EXTREME_MIN |
+ (is_overshoot ? KEYFRAME_EXTREME_MIXED : 0));
}
return KEYFRAME_EXTREME_NONE;
@@ -240,7 +246,7 @@ static eKeyframeExtremeDrawOpts bezt_extreme_type(BezTripleChain *chain)
/* Comparator callback used for ActKeyColumns and BezTripleChain */
static short compare_ak_bezt(void *node, void *data)
{
- BezTripleChain *chain = data;
+ BezTripleChain *chain = static_cast<BezTripleChain *>(data);
return compare_ak_cfraPtr(node, &chain->cur->vec[1][0]);
}
@@ -248,9 +254,10 @@ static short compare_ak_bezt(void *node, void *data)
/* New node callback used for building ActKeyColumns from BezTripleChain */
static DLRBT_Node *nalloc_ak_bezt(void *data)
{
- ActKeyColumn *ak = MEM_callocN(sizeof(ActKeyColumn), "ActKeyColumn");
- BezTripleChain *chain = data;
- BezTriple *bezt = chain->cur;
+ ActKeyColumn *ak = static_cast<ActKeyColumn *>(
+ MEM_callocN(sizeof(ActKeyColumn), "ActKeyColumn"));
+ const BezTripleChain *chain = static_cast<const BezTripleChain *>(data);
+ const BezTriple *bezt = chain->cur;
/* store settings based on state of BezTriple */
ak->cfra = bezt->vec[1][0];
@@ -268,9 +275,9 @@ static DLRBT_Node *nalloc_ak_bezt(void *data)
/* Node updater callback used for building ActKeyColumns from BezTripleChain */
static void nupdate_ak_bezt(void *node, void *data)
{
- ActKeyColumn *ak = node;
- BezTripleChain *chain = data;
- BezTriple *bezt = chain->cur;
+ ActKeyColumn *ak = static_cast<ActKeyColumn *>(node);
+ const BezTripleChain *chain = static_cast<const BezTripleChain *>(data);
+ const BezTriple *bezt = chain->cur;
/* set selection status and 'touched' status */
if (BEZT_ISSEL_ANY(bezt)) {
@@ -287,10 +294,10 @@ static void nupdate_ak_bezt(void *node, void *data)
}
/* For interpolation type, select the highest value (enum is sorted). */
- ak->handle_type = MAX2(ak->handle_type, bezt_handle_type(bezt));
+ ak->handle_type = MAX2((eKeyframeHandleDrawOpts)ak->handle_type, bezt_handle_type(bezt));
/* For extremes, detect when combining different states. */
- char new_extreme = bezt_extreme_type(chain);
+ const char new_extreme = bezt_extreme_type(chain);
if (new_extreme != ak->extreme_type) {
/* Replace the flat status without adding mixed. */
@@ -308,7 +315,7 @@ static void nupdate_ak_bezt(void *node, void *data)
/* Comparator callback used for ActKeyColumns and GPencil frame */
static short compare_ak_gpframe(void *node, void *data)
{
- bGPDframe *gpf = (bGPDframe *)data;
+ const bGPDframe *gpf = (bGPDframe *)data;
float frame = gpf->framenum;
return compare_ak_cfraPtr(node, &frame);
@@ -317,8 +324,9 @@ static short compare_ak_gpframe(void *node, void *data)
/* New node callback used for building ActKeyColumns from GPencil frames */
static DLRBT_Node *nalloc_ak_gpframe(void *data)
{
- ActKeyColumn *ak = MEM_callocN(sizeof(ActKeyColumn), "ActKeyColumnGPF");
- bGPDframe *gpf = (bGPDframe *)data;
+ ActKeyColumn *ak = static_cast<ActKeyColumn *>(
+ MEM_callocN(sizeof(ActKeyColumn), "ActKeyColumnGPF"));
+ const bGPDframe *gpf = (bGPDframe *)data;
/* store settings based on state of BezTriple */
ak->cfra = gpf->framenum;
@@ -339,7 +347,7 @@ static DLRBT_Node *nalloc_ak_gpframe(void *data)
static void nupdate_ak_gpframe(void *node, void *data)
{
ActKeyColumn *ak = (ActKeyColumn *)node;
- bGPDframe *gpf = (bGPDframe *)data;
+ const bGPDframe *gpf = (bGPDframe *)data;
/* set selection status and 'touched' status */
if (gpf->flag & GP_FRAME_SELECT) {
@@ -361,7 +369,7 @@ static void nupdate_ak_gpframe(void *node, void *data)
/* Comparator callback used for ActKeyColumns and GPencil frame */
static short compare_ak_masklayshape(void *node, void *data)
{
- MaskLayerShape *masklay_shape = (MaskLayerShape *)data;
+ const MaskLayerShape *masklay_shape = (const MaskLayerShape *)data;
float frame = masklay_shape->frame;
return compare_ak_cfraPtr(node, &frame);
@@ -370,8 +378,9 @@ static short compare_ak_masklayshape(void *node, void *data)
/* New node callback used for building ActKeyColumns from GPencil frames */
static DLRBT_Node *nalloc_ak_masklayshape(void *data)
{
- ActKeyColumn *ak = MEM_callocN(sizeof(ActKeyColumn), "ActKeyColumnGPF");
- MaskLayerShape *masklay_shape = (MaskLayerShape *)data;
+ ActKeyColumn *ak = static_cast<ActKeyColumn *>(
+ MEM_callocN(sizeof(ActKeyColumn), "ActKeyColumnGPF"));
+ const MaskLayerShape *masklay_shape = (const MaskLayerShape *)data;
/* store settings based on state of BezTriple */
ak->cfra = masklay_shape->frame;
@@ -387,7 +396,7 @@ static DLRBT_Node *nalloc_ak_masklayshape(void *data)
static void nupdate_ak_masklayshape(void *node, void *data)
{
ActKeyColumn *ak = (ActKeyColumn *)node;
- MaskLayerShape *masklay_shape = (MaskLayerShape *)data;
+ const MaskLayerShape *masklay_shape = (const MaskLayerShape *)data;
/* set selection status and 'touched' status */
if (masklay_shape->flag & MASK_SHAPE_SELECT) {
@@ -403,7 +412,7 @@ static void nupdate_ak_masklayshape(void *node, void *data)
/* Add the given BezTriple to the given 'list' of Keyframes */
static void add_bezt_to_keycolumns_list(AnimKeylist *keylist, BezTripleChain *bezt)
{
- if (ELEM(NULL, keylist, bezt)) {
+ if (ELEM(nullptr, keylist, bezt)) {
return;
}
@@ -413,7 +422,7 @@ static void add_bezt_to_keycolumns_list(AnimKeylist *keylist, BezTripleChain *be
/* Add the given GPencil Frame to the given 'list' of Keyframes */
static void add_gpframe_to_keycolumns_list(AnimKeylist *keylist, bGPDframe *gpf)
{
- if (ELEM(NULL, keylist, gpf)) {
+ if (ELEM(nullptr, keylist, gpf)) {
return;
}
@@ -423,7 +432,7 @@ static void add_gpframe_to_keycolumns_list(AnimKeylist *keylist, bGPDframe *gpf)
/* Add the given MaskLayerShape Frame to the given 'list' of Keyframes */
static void add_masklay_to_keycolumns_list(AnimKeylist *keylist, MaskLayerShape *masklay_shape)
{
- if (ELEM(NULL, keylist, masklay_shape)) {
+ if (ELEM(nullptr, keylist, masklay_shape)) {
return;
}
@@ -438,7 +447,9 @@ static void add_masklay_to_keycolumns_list(AnimKeylist *keylist, MaskLayerShape
static const ActKeyBlockInfo dummy_keyblock = {0};
-static void compute_keyblock_data(ActKeyBlockInfo *info, BezTriple *prev, BezTriple *beztn)
+static void compute_keyblock_data(ActKeyBlockInfo *info,
+ const BezTriple *prev,
+ const BezTriple *beztn)
{
memset(info, 0, sizeof(ActKeyBlockInfo));
@@ -501,22 +512,22 @@ static void add_keyblock_info(ActKeyColumn *col, const ActKeyBlockInfo *block)
}
}
-static void add_bezt_to_keyblocks_list(AnimKeylist *keylist, BezTriple *bezt, int bezt_len)
+static void add_bezt_to_keyblocks_list(AnimKeylist *keylist, BezTriple *bezt, const int bezt_len)
{
- ActKeyColumn *col = keylist->keys.first;
+ ActKeyColumn *col = static_cast<ActKeyColumn *>(keylist->keys.first);
if (bezt && bezt_len >= 2) {
ActKeyBlockInfo block;
/* Find the first key column while inserting dummy blocks. */
- for (; col != NULL && is_cfra_lt(col->cfra, bezt[0].vec[1][0]); col = col->next) {
+ for (; col != nullptr && is_cfra_lt(col->cfra, bezt[0].vec[1][0]); col = col->next) {
add_keyblock_info(col, &dummy_keyblock);
}
- BLI_assert(col != NULL);
+ BLI_assert(col != nullptr);
/* Insert real blocks. */
- for (int v = 1; col != NULL && v < bezt_len; v++, bezt++) {
+ for (int v = 1; col != nullptr && v < bezt_len; v++, bezt++) {
/* Wrong order of bezier keys: resync position. */
if (is_cfra_lt(bezt[1].vec[1][0], bezt[0].vec[1][0])) {
/* Backtrack to find the right location. */
@@ -524,11 +535,11 @@ static void add_bezt_to_keyblocks_list(AnimKeylist *keylist, BezTriple *bezt, in
ActKeyColumn *newcol = (ActKeyColumn *)BLI_dlrbTree_search_exact(
&keylist->keys, compare_ak_cfraPtr, &bezt[1].vec[1][0]);
- if (newcol != NULL) {
+ if (newcol != nullptr) {
col = newcol;
/* The previous keyblock is garbage too. */
- if (col->prev != NULL) {
+ if (col->prev != nullptr) {
add_keyblock_info(col->prev, &dummy_keyblock);
}
}
@@ -545,16 +556,16 @@ static void add_bezt_to_keyblocks_list(AnimKeylist *keylist, BezTriple *bezt, in
compute_keyblock_data(&block, bezt, bezt + 1);
- for (; col != NULL && is_cfra_lt(col->cfra, bezt[1].vec[1][0]); col = col->next) {
+ for (; col != nullptr && is_cfra_lt(col->cfra, bezt[1].vec[1][0]); col = col->next) {
add_keyblock_info(col, &block);
}
- BLI_assert(col != NULL);
+ BLI_assert(col != nullptr);
}
}
/* Insert dummy blocks at the end. */
- for (; col != NULL; col = col->next) {
+ for (; col != nullptr; col = col->next) {
add_keyblock_info(col, &dummy_keyblock);
}
}
@@ -564,7 +575,7 @@ static void add_bezt_to_keyblocks_list(AnimKeylist *keylist, BezTriple *bezt, in
* This must be called even by animation sources that don't generate
* keyblocks to keep the data structure consistent after adding columns.
*/
-static void update_keyblocks(AnimKeylist *keylist, BezTriple *bezt, int bezt_len)
+static void update_keyblocks(AnimKeylist *keylist, BezTriple *bezt, const int bezt_len)
{
/* Recompute the prev/next linked list. */
BLI_dlrbTree_linkedlist_sync(&keylist->keys);
@@ -577,7 +588,7 @@ static void update_keyblocks(AnimKeylist *keylist, BezTriple *bezt, int bezt_len
}
/* Propagate blocks to inserted keys */
- ActKeyColumn *prev_ready = NULL;
+ ActKeyColumn *prev_ready = nullptr;
LISTBASE_FOREACH (ActKeyColumn *, col, &keylist->keys) {
/* Pre-existing column. */
@@ -585,7 +596,7 @@ static void update_keyblocks(AnimKeylist *keylist, BezTriple *bezt, int bezt_len
prev_ready = col;
}
/* Newly inserted column, so copy block data from previous. */
- else if (prev_ready != NULL) {
+ else if (prev_ready != nullptr) {
col->totblock = prev_ready->totblock;
memcpy(&col->block, &prev_ready->block, sizeof(ActKeyBlockInfo));
}
@@ -599,13 +610,13 @@ static void update_keyblocks(AnimKeylist *keylist, BezTriple *bezt, int bezt_len
/* --------- */
-bool actkeyblock_is_valid(ActKeyColumn *ac)
+bool actkeyblock_is_valid(const ActKeyColumn *ac)
{
- return ac != NULL && ac->next != NULL && ac->totblock > 0;
+ return ac != nullptr && ac->next != nullptr && ac->totblock > 0;
}
/* Checks if ActKeyBlock should exist... */
-int actkeyblock_get_valid_hold(ActKeyColumn *ac)
+int actkeyblock_get_valid_hold(const ActKeyColumn *ac)
{
/* check that block is valid */
if (!actkeyblock_is_valid(ac)) {
@@ -618,34 +629,32 @@ int actkeyblock_get_valid_hold(ActKeyColumn *ac)
/* *************************** Keyframe List Conversions *************************** */
-void summary_to_keylist(bAnimContext *ac, AnimKeylist *keylist, int saction_flag)
+void summary_to_keylist(bAnimContext *ac, AnimKeylist *keylist, const int saction_flag)
{
if (ac) {
- ListBase anim_data = {NULL, NULL};
- bAnimListElem *ale;
- int filter;
+ ListBase anim_data = {nullptr, nullptr};
/* get F-Curves to take keyframes from */
- filter = ANIMFILTER_DATA_VISIBLE;
- ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+ const eAnimFilter_Flags filter = ANIMFILTER_DATA_VISIBLE;
+ ANIM_animdata_filter(
+ ac, &anim_data, filter, ac->data, static_cast<eAnimCont_Types>(ac->datatype));
/* loop through each F-Curve, grabbing the keyframes */
- for (ale = anim_data.first; ale; ale = ale->next) {
+ LISTBASE_FOREACH (const bAnimListElem *, ale, &anim_data) {
/* Why not use all #eAnim_KeyType here?
* All of the other key types are actually "summaries" themselves,
* and will just end up duplicating stuff that comes up through
* standard filtering of just F-Curves. Given the way that these work,
* there isn't really any benefit at all from including them. - Aligorith */
-
switch (ale->datatype) {
case ALE_FCURVE:
- fcurve_to_keylist(ale->adt, ale->data, keylist, saction_flag);
+ fcurve_to_keylist(ale->adt, static_cast<FCurve *>(ale->data), keylist, saction_flag);
break;
case ALE_MASKLAY:
- mask_to_keylist(ac->ads, ale->data, keylist);
+ mask_to_keylist(ac->ads, static_cast<MaskLayer *>(ale->data), keylist);
break;
case ALE_GPFRAME:
- gpl_to_keylist(ac->ads, ale->data, keylist);
+ gpl_to_keylist(ac->ads, static_cast<bGPDlayer *>(ale->data), keylist);
break;
default:
// printf("%s: datatype %d unhandled\n", __func__, ale->datatype);
@@ -657,16 +666,14 @@ void summary_to_keylist(bAnimContext *ac, AnimKeylist *keylist, int saction_flag
}
}
-void scene_to_keylist(bDopeSheet *ads, Scene *sce, AnimKeylist *keylist, int saction_flag)
+void scene_to_keylist(bDopeSheet *ads, Scene *sce, AnimKeylist *keylist, const int saction_flag)
{
- bAnimContext ac = {NULL};
- ListBase anim_data = {NULL, NULL};
- bAnimListElem *ale;
- int filter;
+ bAnimContext ac = {nullptr};
+ ListBase anim_data = {nullptr, nullptr};
- bAnimListElem dummychan = {NULL};
+ bAnimListElem dummychan = {nullptr};
- if (sce == NULL) {
+ if (sce == nullptr) {
return;
}
@@ -681,28 +688,27 @@ void scene_to_keylist(bDopeSheet *ads, Scene *sce, AnimKeylist *keylist, int sac
ac.datatype = ANIMCONT_CHANNEL;
/* get F-Curves to take keyframes from */
- filter = ANIMFILTER_DATA_VISIBLE; /* curves only */
- ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
+ const eAnimFilter_Flags filter = ANIMFILTER_DATA_VISIBLE; /* curves only */
+ ANIM_animdata_filter(
+ &ac, &anim_data, filter, ac.data, static_cast<eAnimCont_Types>(ac.datatype));
/* loop through each F-Curve, grabbing the keyframes */
- for (ale = anim_data.first; ale; ale = ale->next) {
- fcurve_to_keylist(ale->adt, ale->data, keylist, saction_flag);
+ LISTBASE_FOREACH (const bAnimListElem *, ale, &anim_data) {
+ fcurve_to_keylist(ale->adt, static_cast<FCurve *>(ale->data), keylist, saction_flag);
}
ANIM_animdata_freelist(&anim_data);
}
-void ob_to_keylist(bDopeSheet *ads, Object *ob, AnimKeylist *keylist, int saction_flag)
+void ob_to_keylist(bDopeSheet *ads, Object *ob, AnimKeylist *keylist, const int saction_flag)
{
- bAnimContext ac = {NULL};
- ListBase anim_data = {NULL, NULL};
- bAnimListElem *ale;
- int filter;
+ bAnimContext ac = {nullptr};
+ ListBase anim_data = {nullptr, nullptr};
- bAnimListElem dummychan = {NULL};
- Base dummybase = {NULL};
+ bAnimListElem dummychan = {nullptr};
+ Base dummybase = {nullptr};
- if (ob == NULL) {
+ if (ob == nullptr) {
return;
}
@@ -719,12 +725,13 @@ void ob_to_keylist(bDopeSheet *ads, Object *ob, AnimKeylist *keylist, int sactio
ac.datatype = ANIMCONT_CHANNEL;
/* get F-Curves to take keyframes from */
- filter = ANIMFILTER_DATA_VISIBLE; /* curves only */
- ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
+ const eAnimFilter_Flags filter = ANIMFILTER_DATA_VISIBLE; /* curves only */
+ ANIM_animdata_filter(
+ &ac, &anim_data, filter, ac.data, static_cast<eAnimCont_Types>(ac.datatype));
/* loop through each F-Curve, grabbing the keyframes */
- for (ale = anim_data.first; ale; ale = ale->next) {
- fcurve_to_keylist(ale->adt, ale->data, keylist, saction_flag);
+ LISTBASE_FOREACH (const bAnimListElem *, ale, &anim_data) {
+ fcurve_to_keylist(ale->adt, static_cast<FCurve *>(ale->data), keylist, saction_flag);
}
ANIM_animdata_freelist(&anim_data);
@@ -733,43 +740,44 @@ void ob_to_keylist(bDopeSheet *ads, Object *ob, AnimKeylist *keylist, int sactio
void cachefile_to_keylist(bDopeSheet *ads,
CacheFile *cache_file,
AnimKeylist *keylist,
- int saction_flag)
+ const int saction_flag)
{
- if (cache_file == NULL) {
+ if (cache_file == nullptr) {
return;
}
/* create a dummy wrapper data to work with */
- bAnimListElem dummychan = {NULL};
+ bAnimListElem dummychan = {nullptr};
dummychan.type = ANIMTYPE_DSCACHEFILE;
dummychan.data = cache_file;
dummychan.id = &cache_file->id;
dummychan.adt = cache_file->adt;
- bAnimContext ac = {NULL};
+ bAnimContext ac = {nullptr};
ac.ads = ads;
ac.data = &dummychan;
ac.datatype = ANIMCONT_CHANNEL;
/* get F-Curves to take keyframes from */
- ListBase anim_data = {NULL, NULL};
- int filter = ANIMFILTER_DATA_VISIBLE; /* curves only */
- ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
+ ListBase anim_data = {nullptr, nullptr};
+ const eAnimFilter_Flags filter = ANIMFILTER_DATA_VISIBLE; /* curves only */
+ ANIM_animdata_filter(
+ &ac, &anim_data, filter, ac.data, static_cast<eAnimCont_Types>(ac.datatype));
/* loop through each F-Curve, grabbing the keyframes */
- LISTBASE_FOREACH (bAnimListElem *, ale, &anim_data) {
- fcurve_to_keylist(ale->adt, ale->data, keylist, saction_flag);
+ LISTBASE_FOREACH (const bAnimListElem *, ale, &anim_data) {
+ fcurve_to_keylist(ale->adt, static_cast<FCurve *>(ale->data), keylist, saction_flag);
}
ANIM_animdata_freelist(&anim_data);
}
-void fcurve_to_keylist(AnimData *adt, FCurve *fcu, AnimKeylist *keylist, int saction_flag)
+void fcurve_to_keylist(AnimData *adt, FCurve *fcu, AnimKeylist *keylist, const int saction_flag)
{
if (fcu && fcu->totvert && fcu->bezt) {
/* apply NLA-mapping (if applicable) */
if (adt) {
- ANIM_nla_mapping_apply_fcurve(adt, fcu, 0, 0);
+ ANIM_nla_mapping_apply_fcurve(adt, fcu, false, false);
}
/* Check if the curve is cyclic. */
@@ -777,15 +785,19 @@ void fcurve_to_keylist(AnimData *adt, FCurve *fcu, AnimKeylist *keylist, int sac
bool do_extremes = (saction_flag & SACTION_SHOW_EXTREMES) != 0;
/* loop through beztriples, making ActKeysColumns */
- BezTripleChain chain = {0};
+ BezTripleChain chain = {nullptr};
for (int v = 0; v < fcu->totvert; v++) {
chain.cur = &fcu->bezt[v];
/* Neighbor keys, accounting for being cyclic. */
if (do_extremes) {
- chain.prev = (v > 0) ? &fcu->bezt[v - 1] : is_cyclic ? &fcu->bezt[fcu->totvert - 2] : NULL;
- chain.next = (v + 1 < fcu->totvert) ? &fcu->bezt[v + 1] : is_cyclic ? &fcu->bezt[1] : NULL;
+ chain.prev = (v > 0) ? &fcu->bezt[v - 1] :
+ is_cyclic ? &fcu->bezt[fcu->totvert - 2] :
+ nullptr;
+ chain.next = (v + 1 < fcu->totvert) ? &fcu->bezt[v + 1] :
+ is_cyclic ? &fcu->bezt[1] :
+ nullptr;
}
add_bezt_to_keycolumns_list(keylist, &chain);
@@ -796,30 +808,32 @@ void fcurve_to_keylist(AnimData *adt, FCurve *fcu, AnimKeylist *keylist, int sac
/* unapply NLA-mapping if applicable */
if (adt) {
- ANIM_nla_mapping_apply_fcurve(adt, fcu, 1, 0);
+ ANIM_nla_mapping_apply_fcurve(adt, fcu, true, false);
}
}
}
-void agroup_to_keylist(AnimData *adt, bActionGroup *agrp, AnimKeylist *keylist, int saction_flag)
+void agroup_to_keylist(AnimData *adt,
+ bActionGroup *agrp,
+ AnimKeylist *keylist,
+ const int saction_flag)
{
- FCurve *fcu;
-
if (agrp) {
/* loop through F-Curves */
- for (fcu = agrp->channels.first; fcu && fcu->grp == agrp; fcu = fcu->next) {
+ LISTBASE_FOREACH (FCurve *, fcu, &agrp->channels) {
+ if (fcu->grp != agrp) {
+ break;
+ }
fcurve_to_keylist(adt, fcu, keylist, saction_flag);
}
}
}
-void action_to_keylist(AnimData *adt, bAction *act, AnimKeylist *keylist, int saction_flag)
+void action_to_keylist(AnimData *adt, bAction *act, AnimKeylist *keylist, const int saction_flag)
{
- FCurve *fcu;
-
if (act) {
/* loop through F-Curves */
- for (fcu = act->curves.first; fcu; fcu = fcu->next) {
+ LISTBASE_FOREACH (FCurve *, fcu, &act->curves) {
fcurve_to_keylist(adt, fcu, keylist, saction_flag);
}
}
@@ -827,11 +841,9 @@ void action_to_keylist(AnimData *adt, bAction *act, AnimKeylist *keylist, int sa
void gpencil_to_keylist(bDopeSheet *ads, bGPdata *gpd, AnimKeylist *keylist, const bool active)
{
- bGPDlayer *gpl;
-
if (gpd && keylist) {
/* for now, just aggregate out all the frames, but only for visible layers */
- for (gpl = gpd->layers.last; gpl; gpl = gpl->prev) {
+ LISTBASE_FOREACH_BACKWARD (bGPDlayer *, gpl, &gpd->layers) {
if ((gpl->flag & GP_LAYER_HIDE) == 0) {
if ((!active) || ((active) && (gpl->flag & GP_LAYER_SELECT))) {
gpl_to_keylist(ads, gpl, keylist);
@@ -843,29 +855,25 @@ void gpencil_to_keylist(bDopeSheet *ads, bGPdata *gpd, AnimKeylist *keylist, con
void gpl_to_keylist(bDopeSheet *UNUSED(ads), bGPDlayer *gpl, AnimKeylist *keylist)
{
- bGPDframe *gpf;
-
if (gpl && keylist) {
/* Although the frames should already be in an ordered list,
* they are not suitable for displaying yet. */
- for (gpf = gpl->frames.first; gpf; gpf = gpf->next) {
+ LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
add_gpframe_to_keycolumns_list(keylist, gpf);
}
- update_keyblocks(keylist, NULL, 0);
+ update_keyblocks(keylist, nullptr, 0);
}
}
void mask_to_keylist(bDopeSheet *UNUSED(ads), MaskLayer *masklay, AnimKeylist *keylist)
{
- MaskLayerShape *masklay_shape;
-
if (masklay && keylist) {
- for (masklay_shape = masklay->splines_shapes.first; masklay_shape;
- masklay_shape = masklay_shape->next) {
+ LISTBASE_FOREACH (MaskLayerShape *, masklay_shape, &masklay->splines_shapes) {
add_masklay_to_keycolumns_list(keylist, masklay_shape);
}
- update_keyblocks(keylist, NULL, 0);
+ update_keyblocks(keylist, nullptr, 0);
}
}
+}
diff --git a/source/blender/editors/armature/meshlaplacian.c b/source/blender/editors/armature/meshlaplacian.c
index e362a2e2f40..990e7589d9d 100644
--- a/source/blender/editors/armature/meshlaplacian.c
+++ b/source/blender/editors/armature/meshlaplacian.c
@@ -307,10 +307,7 @@ static void laplacian_system_construct_end(LaplacianSystem *sys)
MEM_freeN(sys->faces);
sys->faces = NULL;
- if (sys->varea) {
- MEM_freeN(sys->varea);
- sys->varea = NULL;
- }
+ MEM_SAFE_FREE(sys->varea);
BLI_edgehash_free(sys->edgehash, NULL);
sys->edgehash = NULL;
diff --git a/source/blender/editors/armature/pose_lib_2.c b/source/blender/editors/armature/pose_lib_2.c
index 32440f941ba..91a5dc67a21 100644
--- a/source/blender/editors/armature/pose_lib_2.c
+++ b/source/blender/editors/armature/pose_lib_2.c
@@ -299,16 +299,16 @@ static void poselib_tempload_exit(PoseBlendData *pbd)
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 AssetLibraryReference *asset_library_ref = CTX_wm_asset_library_ref(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);
+ BLI_assert((asset_library_ref != 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);
+ pbd->temp_id_consumer, C, asset_library_ref, ID_AC, CTX_data_main(C), op->reports);
}
static bAction *flip_pose(bContext *C, Object *ob, bAction *action)
@@ -423,7 +423,7 @@ static void poselib_blend_cleanup(bContext *C, wmOperator *op)
case POSE_BLEND_ORIGINAL:
/* Cleanup should not be called directly from these states. */
BLI_assert_msg(0, "poselib_blend_cleanup: unexpected pose blend state");
- BKE_report(op->reports, RPT_ERROR, "Internal pose library error, cancelling operator");
+ BKE_report(op->reports, RPT_ERROR, "Internal pose library error, canceling operator");
ATTR_FALLTHROUGH;
case POSE_BLEND_CANCEL:
ED_pose_backup_restore(pbd->pose_backup);
@@ -540,10 +540,10 @@ 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);
+ const AssetLibraryReference *asset_library_ref = CTX_wm_asset_library_ref(C);
AssetHandle asset_handle = CTX_wm_asset_handle(C, &asset_handle_valid);
- return (asset_library != NULL) && asset_handle_valid &&
+ return (asset_library_ref != NULL) && asset_handle_valid &&
(ED_asset_handle_get_id_type(&asset_handle) == ID_AC);
}
diff --git a/source/blender/editors/armature/pose_slide.c b/source/blender/editors/armature/pose_slide.c
index 238799650a0..bc5cbd92deb 100644
--- a/source/blender/editors/armature/pose_slide.c
+++ b/source/blender/editors/armature/pose_slide.c
@@ -1716,7 +1716,7 @@ static float pose_propagate_get_boneHoldEndFrame(tPChanFCurveLink *pfl, float st
/* Find the long keyframe (i.e. hold), and hence obtain the endFrame value
* - the best case would be one that starts on the frame itself
*/
- ActKeyColumn *ab = ED_keylist_find_exact(keylist, startFrame);
+ const ActKeyColumn *ab = ED_keylist_find_exact(keylist, startFrame);
/* There are only two cases for no-exact match:
* 1) the current frame is just before another key but not on a key itself
@@ -1746,7 +1746,7 @@ static float pose_propagate_get_boneHoldEndFrame(tPChanFCurveLink *pfl, float st
if (ab) {
/* Go to next if it is also valid and meets "extension" criteria. */
while (ab->next) {
- ActKeyColumn *abn = ab->next;
+ const ActKeyColumn *abn = ab->next;
/* Must be valid. */
if ((actkeyblock_get_valid_hold(abn) & ACTKEYBLOCK_FLAG_STATIC_HOLD) == 0) {
diff --git a/source/blender/editors/asset/ED_asset_handle.h b/source/blender/editors/asset/ED_asset_handle.h
index c51ce422c25..efb99410d3d 100644
--- a/source/blender/editors/asset/ED_asset_handle.h
+++ b/source/blender/editors/asset/ED_asset_handle.h
@@ -36,7 +36,7 @@ struct ID *ED_asset_handle_get_local_id(const struct AssetHandle *asset);
ID_Type ED_asset_handle_get_id_type(const struct AssetHandle *asset);
int ED_asset_handle_get_preview_icon_id(const struct AssetHandle *asset);
void ED_asset_handle_get_full_library_path(const struct bContext *C,
- const struct AssetLibraryReference *asset_library,
+ const struct AssetLibraryReference *asset_library_ref,
const struct AssetHandle *asset,
char r_full_lib_path[]);
diff --git a/source/blender/editors/asset/ED_asset_temp_id_consumer.h b/source/blender/editors/asset/ED_asset_temp_id_consumer.h
index 9af08c5c52b..7c10d88262e 100644
--- a/source/blender/editors/asset/ED_asset_temp_id_consumer.h
+++ b/source/blender/editors/asset/ED_asset_temp_id_consumer.h
@@ -39,7 +39,7 @@ 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 struct AssetLibraryReference *asset_library,
+ const struct AssetLibraryReference *asset_library_ref,
ID_Type id_type,
struct Main *bmain,
struct ReportList *reports);
diff --git a/source/blender/editors/asset/intern/asset_handle.cc b/source/blender/editors/asset/intern/asset_handle.cc
index aae85e61372..5c8d0b1349c 100644
--- a/source/blender/editors/asset/intern/asset_handle.cc
+++ b/source/blender/editors/asset/intern/asset_handle.cc
@@ -60,13 +60,13 @@ int ED_asset_handle_get_preview_icon_id(const AssetHandle *asset)
}
void ED_asset_handle_get_full_library_path(const bContext *C,
- const AssetLibraryReference *asset_library,
+ const AssetLibraryReference *asset_library_ref,
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);
+ std::string asset_path = ED_assetlist_asset_filepath_get(C, *asset_library_ref, *asset);
if (asset_path.empty()) {
return;
}
diff --git a/source/blender/editors/asset/intern/asset_ops.cc b/source/blender/editors/asset/intern/asset_ops.cc
index 579803f7ff7..d69a2cae94d 100644
--- a/source/blender/editors/asset/intern/asset_ops.cc
+++ b/source/blender/editors/asset/intern/asset_ops.cc
@@ -36,7 +36,7 @@ using PointerRNAVec = blender::Vector<PointerRNA>;
static bool asset_operation_poll(bContext * /*C*/)
{
- return U.experimental.use_asset_browser;
+ return U.experimental.use_extended_asset_browser;
}
/**
@@ -266,7 +266,7 @@ static void ASSET_OT_clear(wmOperatorType *ot)
static bool asset_list_refresh_poll(bContext *C)
{
- const AssetLibraryReference *library = CTX_wm_asset_library(C);
+ const AssetLibraryReference *library = CTX_wm_asset_library_ref(C);
if (!library) {
return false;
}
@@ -276,7 +276,7 @@ static bool asset_list_refresh_poll(bContext *C)
static int asset_list_refresh_exec(bContext *C, wmOperator *UNUSED(unused))
{
- const AssetLibraryReference *library = CTX_wm_asset_library(C);
+ const AssetLibraryReference *library = CTX_wm_asset_library_ref(C);
ED_assetlist_clear(library, C);
return OPERATOR_FINISHED;
}
diff --git a/source/blender/editors/asset/intern/asset_temp_id_consumer.cc b/source/blender/editors/asset/intern/asset_temp_id_consumer.cc
index bed35fdeeb5..f664eab5cbb 100644
--- a/source/blender/editors/asset/intern/asset_temp_id_consumer.cc
+++ b/source/blender/editors/asset/intern/asset_temp_id_consumer.cc
@@ -60,14 +60,14 @@ class AssetTemporaryIDConsumer : NonCopyable, NonMovable {
}
ID *import_id(const bContext *C,
- const AssetLibraryReference &asset_library,
+ const AssetLibraryReference &asset_library_ref,
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);
+ ED_asset_handle_get_full_library_path(C, &asset_library_ref, &handle_, blend_file_path);
temp_lib_context_ = BLO_library_temp_load_id(
&bmain, blend_file_path, id_type, asset_name, &reports);
@@ -99,12 +99,12 @@ void ED_asset_temp_id_consumer_free(AssetTempIDConsumer **consumer)
ID *ED_asset_temp_id_consumer_ensure_local_id(AssetTempIDConsumer *consumer_,
const bContext *C,
- const AssetLibraryReference *asset_library,
+ const AssetLibraryReference *asset_library_ref,
ID_Type id_type,
Main *bmain,
ReportList *reports)
{
- if (!(consumer_ && asset_library && bmain && reports)) {
+ if (!(consumer_ && asset_library_ref && bmain && reports)) {
return nullptr;
}
AssetTemporaryIDConsumer *consumer = reinterpret_cast<AssetTemporaryIDConsumer *>(consumer_);
@@ -112,5 +112,5 @@ ID *ED_asset_temp_id_consumer_ensure_local_id(AssetTempIDConsumer *consumer_,
if (ID *local_id = consumer->get_local_id()) {
return local_id;
}
- return consumer->import_id(C, *asset_library, id_type, *bmain, *reports);
+ return consumer->import_id(C, *asset_library_ref, id_type, *bmain, *reports);
}
diff --git a/source/blender/editors/curve/editcurve.c b/source/blender/editors/curve/editcurve.c
index e7d97ce343c..c399abfa52d 100644
--- a/source/blender/editors/curve/editcurve.c
+++ b/source/blender/editors/curve/editcurve.c
@@ -1848,10 +1848,7 @@ static void ed_surf_delete_selected(Object *obedit)
nu->pntsv = 1;
SWAP(short, nu->orderu, nu->orderv);
BKE_nurb_order_clamp_u(nu);
- if (nu->knotsv) {
- MEM_freeN(nu->knotsv);
- }
- nu->knotsv = NULL;
+ MEM_SAFE_FREE(nu->knotsv);
}
else {
nu->pntsu = newu;
@@ -4650,10 +4647,7 @@ static int make_segment_exec(bContext *C, wmOperator *op)
/* now join the knots */
if (nu1->type == CU_NURBS) {
- if (nu1->knotsu != NULL) {
- MEM_freeN(nu1->knotsu);
- nu1->knotsu = NULL;
- }
+ MEM_SAFE_FREE(nu1->knotsu);
BKE_nurb_knot_calc_u(nu1);
}
diff --git a/source/blender/editors/curve/editfont.c b/source/blender/editors/curve/editfont.c
index e43e4194c51..39fb2882e4b 100644
--- a/source/blender/editors/curve/editfont.c
+++ b/source/blender/editors/curve/editfont.c
@@ -439,37 +439,27 @@ static void text_update_edited(bContext *C, Object *obedit, int mode)
WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
}
-static int kill_selection(Object *obedit, int ins) /* 1 == new character */
+static int kill_selection(Object *obedit, int ins) /* ins == new character len */
{
Curve *cu = obedit->data;
EditFont *ef = cu->editfont;
int selend, selstart, direction;
- int offset = 0;
int getfrom;
direction = BKE_vfont_select_get(obedit, &selstart, &selend);
if (direction) {
int size;
- if (ins) {
- offset = 1;
- }
if (ef->pos >= selstart) {
- ef->pos = selstart + offset;
+ ef->pos = selstart + ins;
}
if ((direction == -1) && ins) {
- selstart++;
- selend++;
- }
- getfrom = selend + offset;
- if (ins == 0) {
- getfrom++;
- }
- size = (ef->len * sizeof(*ef->textbuf)) - (selstart * sizeof(*ef->textbuf)) +
- (offset * sizeof(*ef->textbuf));
- memmove(ef->textbuf + selstart, ef->textbuf + getfrom, size);
- memmove(ef->textbufinfo + selstart,
- ef->textbufinfo + getfrom,
- ((ef->len - selstart) + offset) * sizeof(CharInfo));
+ selstart += ins;
+ selend += ins;
+ }
+ getfrom = selend + 1;
+ size = ef->len - selend; /* This is equivalent to: `(ef->len - getfrom) + 1(null)`. */
+ memmove(ef->textbuf + selstart, ef->textbuf + getfrom, sizeof(*ef->textbuf) * size);
+ memmove(ef->textbufinfo + selstart, ef->textbufinfo + getfrom, sizeof(CharInfo) * size);
ef->len -= ((selend - selstart) + 1);
ef->selstart = ef->selend = 0;
}
@@ -1650,7 +1640,7 @@ static int insert_text_exec(bContext *C, wmOperator *op)
MEM_freeN(inserted_text);
MEM_freeN(inserted_utf8);
- kill_selection(obedit, 1);
+ kill_selection(obedit, len);
text_update_edited(C, obedit, FO_EDIT);
return OPERATOR_FINISHED;
diff --git a/source/blender/editors/gpencil/gpencil_convert.c b/source/blender/editors/gpencil/gpencil_convert.c
index ee3536c2f3f..a0a58abc02f 100644
--- a/source/blender/editors/gpencil/gpencil_convert.c
+++ b/source/blender/editors/gpencil/gpencil_convert.c
@@ -1588,14 +1588,8 @@ static int gpencil_convert_layer_exec(bContext *C, wmOperator *op)
C, op->reports, gpd, gpl, mode, norm_weights, rad_fac, link_strokes, &gtd);
/* free temp memory */
- if (gtd.dists) {
- MEM_freeN(gtd.dists);
- gtd.dists = NULL;
- }
- if (gtd.times) {
- MEM_freeN(gtd.times);
- gtd.times = NULL;
- }
+ MEM_SAFE_FREE(gtd.dists);
+ MEM_SAFE_FREE(gtd.times);
/* notifiers */
DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
diff --git a/source/blender/editors/gpencil/gpencil_intern.h b/source/blender/editors/gpencil/gpencil_intern.h
index d1a1e417d9e..b6730cb123b 100644
--- a/source/blender/editors/gpencil/gpencil_intern.h
+++ b/source/blender/editors/gpencil/gpencil_intern.h
@@ -375,6 +375,7 @@ void GPENCIL_OT_select_less(struct wmOperatorType *ot);
void GPENCIL_OT_select_first(struct wmOperatorType *ot);
void GPENCIL_OT_select_last(struct wmOperatorType *ot);
void GPENCIL_OT_select_alternate(struct wmOperatorType *ot);
+void GPENCIL_OT_select_random(struct wmOperatorType *ot);
void GPENCIL_OT_select_vertex_color(struct wmOperatorType *ot);
void GPENCIL_OT_duplicate(struct wmOperatorType *ot);
diff --git a/source/blender/editors/gpencil/gpencil_ops.c b/source/blender/editors/gpencil/gpencil_ops.c
index 35640cf3b66..8c78a402e81 100644
--- a/source/blender/editors/gpencil/gpencil_ops.c
+++ b/source/blender/editors/gpencil/gpencil_ops.c
@@ -555,6 +555,7 @@ void ED_operatortypes_gpencil(void)
WM_operatortype_append(GPENCIL_OT_select_first);
WM_operatortype_append(GPENCIL_OT_select_last);
WM_operatortype_append(GPENCIL_OT_select_alternate);
+ WM_operatortype_append(GPENCIL_OT_select_random);
WM_operatortype_append(GPENCIL_OT_select_vertex_color);
WM_operatortype_append(GPENCIL_OT_duplicate);
diff --git a/source/blender/editors/gpencil/gpencil_paint.c b/source/blender/editors/gpencil/gpencil_paint.c
index aaea1c0ddaf..9e96c40b2db 100644
--- a/source/blender/editors/gpencil/gpencil_paint.c
+++ b/source/blender/editors/gpencil/gpencil_paint.c
@@ -997,7 +997,7 @@ static void gpencil_stroke_newfrombuffer(tGPsdata *p)
gps->uv_scale = 1.0f;
/* Set stroke caps. */
- gps->caps[0] = gps->caps[1] = brush->gpencil_settings->caps_type;
+ gps->caps[0] = gps->caps[1] = (short)brush->gpencil_settings->caps_type;
/* allocate enough memory for a continuous array for storage points */
const int subdivide = brush->gpencil_settings->draw_subdivide;
diff --git a/source/blender/editors/gpencil/gpencil_primitive.c b/source/blender/editors/gpencil/gpencil_primitive.c
index 27374f21b66..7e6ff53de14 100644
--- a/source/blender/editors/gpencil/gpencil_primitive.c
+++ b/source/blender/editors/gpencil/gpencil_primitive.c
@@ -336,7 +336,7 @@ static void gpencil_primitive_set_initdata(bContext *C, tGPDprimitive *tgpi)
gps->inittime = 0.0f;
/* Set stroke caps. */
- gps->caps[0] = gps->caps[1] = brush->gpencil_settings->caps_type;
+ gps->caps[0] = gps->caps[1] = (short)brush->gpencil_settings->caps_type;
/* Apply the vertex color to fill. */
ED_gpencil_fill_vertex_color_set(ts, brush, gps);
diff --git a/source/blender/editors/gpencil/gpencil_sculpt_paint.c b/source/blender/editors/gpencil/gpencil_sculpt_paint.c
index 14caf0c08a7..869254cef3b 100644
--- a/source/blender/editors/gpencil/gpencil_sculpt_paint.c
+++ b/source/blender/editors/gpencil/gpencil_sculpt_paint.c
@@ -968,10 +968,7 @@ static void gpencil_brush_clone_free(tGP_BrushEditData *gso)
tGPSB_CloneBrushData *data = gso->customdata;
/* free strokes array */
- if (data->new_strokes) {
- MEM_freeN(data->new_strokes);
- data->new_strokes = NULL;
- }
+ MEM_SAFE_FREE(data->new_strokes);
/* free copybuf colormap */
if (data->new_colors) {
diff --git a/source/blender/editors/gpencil/gpencil_select.c b/source/blender/editors/gpencil/gpencil_select.c
index 69734fa1ba8..93bae7d3614 100644
--- a/source/blender/editors/gpencil/gpencil_select.c
+++ b/source/blender/editors/gpencil/gpencil_select.c
@@ -33,6 +33,7 @@
#include "BLI_ghash.h"
#include "BLI_lasso_2d.h"
#include "BLI_math_vector.h"
+#include "BLI_rand.h"
#include "BLI_utildefines.h"
#include "DNA_gpencil_types.h"
@@ -193,6 +194,28 @@ static void deselect_all_selected(bContext *C)
CTX_DATA_END;
}
+static void select_all_stroke_points(bGPdata *gpd, bGPDstroke *gps, bool select)
+{
+ for (int i = 0; i < gps->totpoints; i++) {
+ bGPDspoint *pt = &gps->points[i];
+ if (select) {
+ pt->flag |= GP_SPOINT_SELECT;
+ }
+ else {
+ pt->flag &= ~GP_SPOINT_SELECT;
+ }
+ }
+
+ if (select) {
+ gps->flag |= GP_STROKE_SELECT;
+ BKE_gpencil_stroke_select_index_set(gpd, gps);
+ }
+ else {
+ gps->flag &= ~GP_STROKE_SELECT;
+ BKE_gpencil_stroke_select_index_reset(gps);
+ }
+}
+
static void select_all_curve_points(bGPdata *gpd, bGPDstroke *gps, bGPDcurve *gpc, bool deselect)
{
for (int i = 0; i < gpc->tot_curve_points; i++) {
@@ -513,6 +536,218 @@ void GPENCIL_OT_select_alternate(wmOperatorType *ot)
/** \} */
/* -------------------------------------------------------------------- */
+/** \name Select Random Operator
+ * \{ */
+
+static int gpencil_select_random_exec(bContext *C, wmOperator *op)
+{
+ Object *ob = CTX_data_active_object(C);
+ ToolSettings *ts = CTX_data_tool_settings(C);
+ bGPdata *gpd = ED_gpencil_data_get_active(C);
+ if ((gpd == NULL) || (GPENCIL_NONE_EDIT_MODE(gpd))) {
+ return OPERATOR_CANCELLED;
+ }
+
+ const bool unselect_ends = RNA_boolean_get(op->ptr, "unselect_ends");
+ const bool select = (RNA_enum_get(op->ptr, "action") == SEL_SELECT);
+ const float randfac = RNA_float_get(op->ptr, "ratio");
+ const int seed = WM_operator_properties_select_random_seed_increment_get(op);
+ const int start = (unselect_ends) ? 1 : 0;
+ const bool is_curve_edit = (bool)GPENCIL_CURVE_EDIT_SESSIONS_ON(gpd);
+
+ int selectmode;
+ if (ob && ob->mode == OB_MODE_SCULPT_GPENCIL) {
+ selectmode = gpencil_select_mode_from_sculpt(ts->gpencil_selectmode_sculpt);
+ }
+ else if (ob && ob->mode == OB_MODE_VERTEX_GPENCIL) {
+ selectmode = gpencil_select_mode_from_vertex(ts->gpencil_selectmode_vertex);
+ }
+ else {
+ selectmode = ts->gpencil_selectmode_edit;
+ }
+
+ bool changed = false;
+ int seed_iter = seed;
+ int stroke_idx = 0;
+
+ if (is_curve_edit) {
+ GP_EDITABLE_CURVES_BEGIN(gps_iter, C, gpl, gps, gpc)
+ {
+ /* Only apply to unselected strokes (if select). */
+ if (select) {
+ if ((gps->flag & GP_STROKE_SELECT) || (gps->totpoints == 0)) {
+ continue;
+ }
+ }
+ else {
+ if (((gps->flag & GP_STROKE_SELECT) == 0) || (gps->totpoints == 0)) {
+ continue;
+ }
+ }
+
+ /* Different seed by stroke. */
+ seed_iter += gps->totpoints + stroke_idx;
+ stroke_idx++;
+
+ if (selectmode == GP_SELECTMODE_STROKE) {
+ RNG *rng = BLI_rng_new(seed_iter);
+ const unsigned int j = BLI_rng_get_uint(rng) % gps->totpoints;
+ bool select_stroke = ((gps->totpoints * randfac) <= j) ? true : false;
+ select_stroke ^= select;
+ /* Curve function has select parameter inverted. */
+ select_all_curve_points(gpd, gps, gps->editcurve, !select_stroke);
+ changed = true;
+ BLI_rng_free(rng);
+ }
+ else {
+ int elem_map_len = 0;
+ bGPDcurve_point **elem_map = MEM_mallocN(sizeof(*elem_map) * gpc->tot_curve_points,
+ __func__);
+ bGPDcurve_point *ptc;
+ for (int i = start; i < gpc->tot_curve_points; i++) {
+ bGPDcurve_point *gpc_pt = &gpc->curve_points[i];
+ elem_map[elem_map_len++] = gpc_pt;
+ }
+
+ BLI_array_randomize(elem_map, sizeof(*elem_map), elem_map_len, seed_iter);
+ const int count_select = elem_map_len * randfac;
+ for (int i = 0; i < count_select; i++) {
+ ptc = elem_map[i];
+ if (select) {
+ ptc->flag |= GP_SPOINT_SELECT;
+ BEZT_SEL_ALL(&ptc->bezt);
+ }
+ else {
+ ptc->flag &= ~GP_SPOINT_SELECT;
+ BEZT_DESEL_ALL(&ptc->bezt);
+ }
+ }
+ MEM_freeN(elem_map);
+
+ /* unselect start and end points */
+ if (unselect_ends) {
+ bGPDcurve_point *gpc_pt = &gpc->curve_points[0];
+ gpc_pt->flag &= ~GP_SPOINT_SELECT;
+ BEZT_DESEL_ALL(&gpc_pt->bezt);
+
+ gpc_pt = &gpc->curve_points[gpc->tot_curve_points - 1];
+ gpc_pt->flag &= ~GP_SPOINT_SELECT;
+ BEZT_DESEL_ALL(&gpc_pt->bezt);
+ }
+
+ BKE_gpencil_curve_sync_selection(gpd, gps);
+ }
+
+ changed = true;
+ }
+ GP_EDITABLE_CURVES_END(gps_iter);
+ }
+ else {
+ CTX_DATA_BEGIN (C, bGPDstroke *, gps, editable_gpencil_strokes) {
+ /* Only apply to unselected strokes (if select). */
+ if (select) {
+ if ((gps->flag & GP_STROKE_SELECT) || (gps->totpoints == 0)) {
+ continue;
+ }
+ }
+ else {
+ if (((gps->flag & GP_STROKE_SELECT) == 0) || (gps->totpoints == 0)) {
+ continue;
+ }
+ }
+
+ /* Different seed by stroke. */
+ seed_iter += gps->totpoints + stroke_idx;
+ stroke_idx++;
+
+ if (selectmode == GP_SELECTMODE_STROKE) {
+ RNG *rng = BLI_rng_new(seed_iter);
+ const unsigned int j = BLI_rng_get_uint(rng) % gps->totpoints;
+ bool select_stroke = ((gps->totpoints * randfac) <= j) ? true : false;
+ select_stroke ^= select;
+ select_all_stroke_points(gpd, gps, select_stroke);
+ changed = true;
+ BLI_rng_free(rng);
+ }
+ else {
+ int elem_map_len = 0;
+ bGPDspoint **elem_map = MEM_mallocN(sizeof(*elem_map) * gps->totpoints, __func__);
+ bGPDspoint *pt;
+ for (int i = start; i < gps->totpoints; i++) {
+ pt = &gps->points[i];
+ elem_map[elem_map_len++] = pt;
+ }
+
+ BLI_array_randomize(elem_map, sizeof(*elem_map), elem_map_len, seed_iter);
+ const int count_select = elem_map_len * randfac;
+ for (int i = 0; i < count_select; i++) {
+ pt = elem_map[i];
+ if (select) {
+ pt->flag |= GP_SPOINT_SELECT;
+ }
+ else {
+ pt->flag &= ~GP_SPOINT_SELECT;
+ }
+ }
+ MEM_freeN(elem_map);
+
+ /* unselect start and end points */
+ if (unselect_ends) {
+ pt = &gps->points[0];
+ pt->flag &= ~GP_SPOINT_SELECT;
+
+ pt = &gps->points[gps->totpoints - 1];
+ pt->flag &= ~GP_SPOINT_SELECT;
+ }
+
+ BKE_gpencil_stroke_sync_selection(gpd, gps);
+ }
+
+ changed = true;
+ }
+ CTX_DATA_END;
+ }
+
+ if (changed) {
+ /* updates */
+ DEG_id_tag_update(&gpd->id, ID_RECALC_GEOMETRY);
+
+ /* copy on write tag is needed, or else no refresh happens */
+ DEG_id_tag_update(&gpd->id, ID_RECALC_COPY_ON_WRITE);
+
+ WM_event_add_notifier(C, NC_GPENCIL | NA_SELECTED, NULL);
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, NULL);
+ }
+
+ return OPERATOR_FINISHED;
+}
+
+void GPENCIL_OT_select_random(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Random";
+ ot->idname = "GPENCIL_OT_select_random";
+ ot->description = "Select random points for non selected strokes";
+
+ /* callbacks */
+ ot->exec = gpencil_select_random_exec;
+ ot->poll = gpencil_select_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ WM_operator_properties_select_random(ot);
+ RNA_def_boolean(ot->srna,
+ "unselect_ends",
+ false,
+ "Unselect Ends",
+ "Do not select the first and last point of the stroke");
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
/** \name Select Grouped Operator
* \{ */
diff --git a/source/blender/editors/gpencil/gpencil_utils.c b/source/blender/editors/gpencil/gpencil_utils.c
index ba3d3b584d7..5cc52303cd6 100644
--- a/source/blender/editors/gpencil/gpencil_utils.c
+++ b/source/blender/editors/gpencil/gpencil_utils.c
@@ -341,7 +341,7 @@ bool ED_gpencil_has_keyframe_v3d(Scene *UNUSED(scene), Object *ob, int cfra)
return (gpl->actframe->framenum == cfra);
}
/* XXX: disabled as could be too much of a penalty */
- /* return BKE_gpencil_layer_frame_find(gpl, cfra); */
+ // return BKE_gpencil_layer_frame_find(gpl, cfra);
}
}
diff --git a/source/blender/editors/include/ED_keyframes_draw.h b/source/blender/editors/include/ED_keyframes_draw.h
index d2d22dd38dc..61e37f20b1b 100644
--- a/source/blender/editors/include/ED_keyframes_draw.h
+++ b/source/blender/editors/include/ED_keyframes_draw.h
@@ -28,6 +28,7 @@ extern "C" {
#endif
struct AnimData;
+struct AnimKeylistDrawList;
struct FCurve;
struct MaskLayer;
struct Object;
@@ -42,6 +43,14 @@ struct bGPDlayer;
/* draw simple diamond-shape keyframe */
/* caller should set up vertex format, bind GPU_SHADER_KEYFRAME_DIAMOND,
* immBegin(GPU_PRIM_POINTS, n), then call this n times */
+typedef struct KeyframeShaderBindings {
+ uint pos_id;
+ uint size_id;
+ uint color_id;
+ uint outline_color_id;
+ uint flags_id;
+} KeyframeShaderBindings;
+
void draw_keyframe_shape(float x,
float y,
float size,
@@ -49,11 +58,7 @@ void draw_keyframe_shape(float x,
short key_type,
short mode,
float alpha,
- unsigned int pos_id,
- unsigned int size_id,
- unsigned int color_id,
- unsigned int outline_color_id,
- unsigned int flags_id,
+ const KeyframeShaderBindings *sh_bindings,
short handle_type,
short extreme_type);
@@ -61,65 +66,65 @@ void draw_keyframe_shape(float x,
/* Channel Drawing ------------------ */
/* F-Curve */
-void draw_fcurve_channel(struct View2D *v2d,
+void draw_fcurve_channel(struct AnimKeylistDrawList *draw_list,
struct AnimData *adt,
struct FCurve *fcu,
float ypos,
float yscale_fac,
int saction_flag);
/* Action Group Summary */
-void draw_agroup_channel(struct View2D *v2d,
+void draw_agroup_channel(struct AnimKeylistDrawList *draw_list,
struct AnimData *adt,
struct bActionGroup *agrp,
float ypos,
float yscale_fac,
int saction_flag);
/* Action Summary */
-void draw_action_channel(struct View2D *v2d,
+void draw_action_channel(struct AnimKeylistDrawList *draw_list,
struct AnimData *adt,
struct bAction *act,
float ypos,
float yscale_fac,
int saction_flag);
/* Object Summary */
-void draw_object_channel(struct View2D *v2d,
+void draw_object_channel(struct AnimKeylistDrawList *draw_list,
struct bDopeSheet *ads,
struct Object *ob,
float ypos,
float yscale_fac,
int saction_flag);
/* Scene Summary */
-void draw_scene_channel(struct View2D *v2d,
+void draw_scene_channel(struct AnimKeylistDrawList *draw_list,
struct bDopeSheet *ads,
struct Scene *sce,
float ypos,
float yscale_fac,
int saction_flag);
/* DopeSheet Summary */
-void draw_summary_channel(
- struct View2D *v2d, struct bAnimContext *ac, float ypos, float yscale_fac, int saction_flag);
-/* Grease Pencil datablock summary */
-void draw_gpencil_channel(struct View2D *v2d,
- struct bDopeSheet *ads,
- struct bGPdata *gpd,
+void draw_summary_channel(struct AnimKeylistDrawList *draw_list,
+ struct bAnimContext *ac,
float ypos,
float yscale_fac,
int saction_flag);
/* Grease Pencil Layer */
-void draw_gpl_channel(struct View2D *v2d,
+void draw_gpl_channel(struct AnimKeylistDrawList *draw_list,
struct bDopeSheet *ads,
struct bGPDlayer *gpl,
float ypos,
float yscale_fac,
int saction_flag);
/* Mask Layer */
-void draw_masklay_channel(struct View2D *v2d,
+void draw_masklay_channel(struct AnimKeylistDrawList *draw_list,
struct bDopeSheet *ads,
struct MaskLayer *masklay,
float ypos,
float yscale_fac,
int saction_flag);
+struct AnimKeylistDrawList *ED_keylist_draw_list_create(void);
+void ED_keylist_draw_list_flush(struct AnimKeylistDrawList *draw_list, struct View2D *v2d);
+void ED_keylist_draw_list_free(struct AnimKeylistDrawList *draw_list);
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/editors/include/ED_keyframes_keylist.h b/source/blender/editors/include/ED_keyframes_keylist.h
index d3690fa3aa0..3a9750c1206 100644
--- a/source/blender/editors/include/ED_keyframes_keylist.h
+++ b/source/blender/editors/include/ED_keyframes_keylist.h
@@ -23,6 +23,8 @@
#pragma once
+#include "BLI_range.h"
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -37,7 +39,6 @@ struct Scene;
struct bAnimContext;
struct bDopeSheet;
struct bGPDlayer;
-struct Range2f;
/* ****************************** Base Structs ****************************** */
@@ -138,15 +139,14 @@ typedef enum eKeyframeExtremeDrawOpts {
struct AnimKeylist *ED_keylist_create(void);
void ED_keylist_free(struct AnimKeylist *keylist);
-struct ActKeyColumn *ED_keylist_find_exact(const struct AnimKeylist *keylist, float cfra);
-struct ActKeyColumn *ED_keylist_find_next(const struct AnimKeylist *keylist, float cfra);
-struct ActKeyColumn *ED_keylist_find_prev(const struct AnimKeylist *keylist, float cfra);
-struct ActKeyColumn *ED_keylist_find_any_between(const struct AnimKeylist *keylist,
- float min_fra,
- float max_fra);
+const struct ActKeyColumn *ED_keylist_find_exact(const struct AnimKeylist *keylist, float cfra);
+const struct ActKeyColumn *ED_keylist_find_next(const struct AnimKeylist *keylist, float cfra);
+const struct ActKeyColumn *ED_keylist_find_prev(const struct AnimKeylist *keylist, float cfra);
+const struct ActKeyColumn *ED_keylist_find_any_between(const struct AnimKeylist *keylist,
+ const Range2f frame_range);
bool ED_keylist_is_empty(const struct AnimKeylist *keylist);
const struct ListBase /* ActKeyColumn */ *ED_keylist_listbase(const struct AnimKeylist *keylist);
-bool ED_keylist_frame_range(const struct AnimKeylist *keylist, struct Range2f *r_frame_range);
+bool ED_keylist_frame_range(const struct AnimKeylist *keylist, Range2f *r_frame_range);
/* Key-data Generation --------------- */
@@ -154,34 +154,36 @@ bool ED_keylist_frame_range(const struct AnimKeylist *keylist, struct Range2f *r
void fcurve_to_keylist(struct AnimData *adt,
struct FCurve *fcu,
struct AnimKeylist *keylist,
- int saction_flag);
+ const int saction_flag);
/* Action Group */
void agroup_to_keylist(struct AnimData *adt,
struct bActionGroup *agrp,
struct AnimKeylist *keylist,
- int saction_flag);
+ const int saction_flag);
/* Action */
void action_to_keylist(struct AnimData *adt,
struct bAction *act,
struct AnimKeylist *keylist,
- int saction_flag);
+ const int saction_flag);
/* Object */
void ob_to_keylist(struct bDopeSheet *ads,
struct Object *ob,
struct AnimKeylist *keylist,
- int saction_flag);
+ const int saction_flag);
/* Cache File */
void cachefile_to_keylist(struct bDopeSheet *ads,
struct CacheFile *cache_file,
struct AnimKeylist *keylist,
- int saction_flag);
+ const int saction_flag);
/* Scene */
void scene_to_keylist(struct bDopeSheet *ads,
struct Scene *sce,
struct AnimKeylist *keylist,
- int saction_flag);
+ const int saction_flag);
/* DopeSheet Summary */
-void summary_to_keylist(struct bAnimContext *ac, struct AnimKeylist *keylist, int saction_flag);
+void summary_to_keylist(struct bAnimContext *ac,
+ struct AnimKeylist *keylist,
+ const int saction_flag);
/* Grease Pencil datablock summary */
void gpencil_to_keylist(struct bDopeSheet *ads,
struct bGPdata *gpd,
@@ -199,10 +201,10 @@ void mask_to_keylist(struct bDopeSheet *ads,
short compare_ak_cfraPtr(void *node, void *data);
/* Checks if ActKeyColumn has any block data */
-bool actkeyblock_is_valid(ActKeyColumn *ac);
+bool actkeyblock_is_valid(const ActKeyColumn *ac);
/* Checks if ActKeyColumn can be used as a block (i.e. drawn/used to detect "holds") */
-int actkeyblock_get_valid_hold(ActKeyColumn *ac);
+int actkeyblock_get_valid_hold(const ActKeyColumn *ac);
#ifdef __cplusplus
}
diff --git a/source/blender/editors/interface/interface_align.c b/source/blender/editors/interface/interface_align.c
index dbfdfbf7950..3149675ac04 100644
--- a/source/blender/editors/interface/interface_align.c
+++ b/source/blender/editors/interface/interface_align.c
@@ -343,7 +343,7 @@ static int ui_block_align_butal_cmp(const void *a, const void *b)
* stupid UI code produces widgets which have the same TOP and LEFT positions...
* We do not care really,
* because this happens when UI is way too small to be usable anyway. */
- /* BLI_assert(0); */
+ // BLI_assert(0);
return 0;
}
diff --git a/source/blender/editors/interface/interface_context_menu.c b/source/blender/editors/interface/interface_context_menu.c
index d917534895d..8ace057891d 100644
--- a/source/blender/editors/interface/interface_context_menu.c
+++ b/source/blender/editors/interface/interface_context_menu.c
@@ -952,7 +952,7 @@ bool ui_popup_context_menu_for_button(bContext *C, uiBut *but, const wmEvent *ev
}
/* If the button represents an id, it can set the "id" context pointer. */
- if (U.experimental.use_asset_browser && ED_asset_can_mark_single_from_context(C)) {
+ if (U.experimental.use_extended_asset_browser && ED_asset_can_mark_single_from_context(C)) {
ID *id = CTX_data_pointer_get_type(C, "id", &RNA_ID).data;
/* Gray out items depending on if data-block is an asset. Preferably this could be done via
diff --git a/source/blender/editors/interface/interface_draw.c b/source/blender/editors/interface/interface_draw.c
index 65104885d98..ebebf69bc11 100644
--- a/source/blender/editors/interface/interface_draw.c
+++ b/source/blender/editors/interface/interface_draw.c
@@ -2281,7 +2281,7 @@ static void ui_shadowbox(const rctf *rect, uint pos, uint color, float shadsize,
immVertex2fv(pos, v3);
/* corner shape */
- /* immAttr4ub(color, 0, 0, 0, alpha); */ /* Not needed, done above in previous tri */
+ // immAttr4ub(color, 0, 0, 0, alpha); /* Not needed, done above in previous tri. */
immVertex2fv(pos, v3);
immAttr4ub(color, 0, 0, 0, 0);
immVertex2fv(pos, v4);
@@ -2293,7 +2293,7 @@ static void ui_shadowbox(const rctf *rect, uint pos, uint color, float shadsize,
immVertex2fv(pos, v3);
/* bottom quad */
- /* immAttr4ub(color, 0, 0, 0, alpha); */ /* Not needed, done above in previous tri */
+ // immAttr4ub(color, 0, 0, 0, alpha); /* Not needed, done above in previous tri. */
immVertex2fv(pos, v3);
immAttr4ub(color, 0, 0, 0, 0);
immVertex2fv(pos, v6);
diff --git a/source/blender/editors/interface/interface_eyedropper_driver.c b/source/blender/editors/interface/interface_eyedropper_driver.c
index 8762a4819d4..ccf0e727da8 100644
--- a/source/blender/editors/interface/interface_eyedropper_driver.c
+++ b/source/blender/editors/interface/interface_eyedropper_driver.c
@@ -84,10 +84,7 @@ static void driverdropper_exit(bContext *C, wmOperator *op)
{
WM_cursor_modal_restore(CTX_wm_window(C));
- if (op->customdata) {
- MEM_freeN(op->customdata);
- op->customdata = NULL;
- }
+ MEM_SAFE_FREE(op->customdata);
}
static void driverdropper_sample(bContext *C, wmOperator *op, const wmEvent *event)
diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c
index d920ebbe11a..6f2232fabe5 100644
--- a/source/blender/editors/interface/interface_handlers.c
+++ b/source/blender/editors/interface/interface_handlers.c
@@ -3438,10 +3438,7 @@ static void ui_textedit_begin(bContext *C, uiBut *but, uiHandleButtonData *data)
const bool is_num_but = ELEM(but->type, UI_BTYPE_NUM, UI_BTYPE_NUM_SLIDER);
bool no_zero_strip = false;
- if (data->str) {
- MEM_freeN(data->str);
- data->str = NULL;
- }
+ MEM_SAFE_FREE(data->str);
#ifdef USE_DRAG_MULTINUM
/* this can happen from multi-drag */
@@ -8635,10 +8632,7 @@ static void button_activate_exit(
}
/* clean up button */
- if (but->active) {
- MEM_freeN(but->active);
- but->active = NULL;
- }
+ MEM_SAFE_FREE(but->active);
but->flag &= ~(UI_ACTIVE | UI_SELECT);
but->flag |= UI_BUT_LAST_ACTIVE;
diff --git a/source/blender/editors/interface/interface_icons.c b/source/blender/editors/interface/interface_icons.c
index 2d59bfb92c8..f739830cfdb 100644
--- a/source/blender/editors/interface/interface_icons.c
+++ b/source/blender/editors/interface/interface_icons.c
@@ -299,13 +299,14 @@ static void vicon_keytype_draw_wrapper(
const float yco = y + h / 2 + 0.5f;
GPUVertFormat *format = immVertexFormat();
- const uint pos_id = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- const uint size_id = GPU_vertformat_attr_add(format, "size", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
- uint color_id = GPU_vertformat_attr_add(
+ KeyframeShaderBindings sh_bindings;
+ sh_bindings.pos_id = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ sh_bindings.size_id = GPU_vertformat_attr_add(format, "size", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
+ sh_bindings.color_id = GPU_vertformat_attr_add(
format, "color", GPU_COMP_U8, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
- uint outline_color_id = GPU_vertformat_attr_add(
+ sh_bindings.outline_color_id = GPU_vertformat_attr_add(
format, "outlineColor", GPU_COMP_U8, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
- const uint flags_id = GPU_vertformat_attr_add(format, "flags", GPU_COMP_U32, 1, GPU_FETCH_INT);
+ sh_bindings.flags_id = GPU_vertformat_attr_add(format, "flags", GPU_COMP_U32, 1, GPU_FETCH_INT);
GPU_program_point_size(true);
immBindBuiltinProgram(GPU_SHADER_KEYFRAME_DIAMOND);
@@ -326,11 +327,7 @@ static void vicon_keytype_draw_wrapper(
key_type,
KEYFRAME_SHAPE_BOTH,
alpha,
- pos_id,
- size_id,
- color_id,
- outline_color_id,
- flags_id,
+ &sh_bindings,
handle_type,
KEYFRAME_EXTREME_NONE);
diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c
index 03c67e9b046..ec5a30f7793 100644
--- a/source/blender/editors/interface/interface_layout.c
+++ b/source/blender/editors/interface/interface_layout.c
@@ -282,7 +282,7 @@ static int ui_layout_vary_direction(uiLayout *layout)
static bool ui_layout_variable_size(uiLayout *layout)
{
- /* Note that this code is probably a bit flakey, we'd probably want to know whether it's
+ /* Note that this code is probably a bit flaky, we'd probably want to know whether it's
* variable in X and/or Y, etc. But for now it mimics previous one,
* with addition of variable flag set for children of grid-flow layouts. */
return ui_layout_vary_direction(layout) == UI_ITEM_VARY_X || layout->variable_size;
diff --git a/source/blender/editors/interface/interface_template_asset_view.cc b/source/blender/editors/interface/interface_template_asset_view.cc
index b4ba6a7feab..9b601727e29 100644
--- a/source/blender/editors/interface/interface_template_asset_view.cc
+++ b/source/blender/editors/interface/interface_template_asset_view.cc
@@ -44,7 +44,7 @@
#include "interface_intern.h"
struct AssetViewListData {
- AssetLibraryReference asset_library;
+ AssetLibraryReference asset_library_ref;
bScreen *screen;
};
@@ -62,7 +62,7 @@ static void asset_view_item_but_drag_set(uiBut *but,
/* Context can be null here, it's only needed for a File Browser specific hack that should go
* away before too long. */
ED_asset_handle_get_full_library_path(
- nullptr, &list_data->asset_library, asset_handle, blend_path);
+ nullptr, &list_data->asset_library_ref, asset_handle, blend_path);
if (blend_path[0]) {
ImBuf *imbuf = ED_assetlist_asset_image_get(asset_handle);
@@ -136,7 +136,7 @@ static void asset_view_listener(uiList *ui_list, wmRegionListenerParams *params)
}
}
- if (ED_assetlist_listen(&list_data->asset_library, params->notifier)) {
+ if (ED_assetlist_listen(&list_data->asset_library_ref, params->notifier)) {
ED_region_tag_redraw(params->region);
}
}
@@ -153,7 +153,7 @@ uiListType *UI_UL_asset_view()
}
static void asset_view_template_refresh_asset_collection(
- const AssetLibraryReference &asset_library,
+ const AssetLibraryReference &asset_library_ref,
const AssetFilterSettings &filter_settings,
PointerRNA &assets_dataptr,
const char *assets_propname)
@@ -175,7 +175,7 @@ static void asset_view_template_refresh_asset_collection(
RNA_property_collection_clear(&assets_dataptr, assets_prop);
- ED_assetlist_iterate(&asset_library, [&](AssetHandle asset) {
+ ED_assetlist_iterate(&asset_library_ref, [&](AssetHandle asset) {
if (!ED_asset_filter_matches_asset(&filter_settings, &asset)) {
/* Don't do anything else, but return true to continue iterating. */
return true;
@@ -216,25 +216,25 @@ void uiTemplateAssetView(uiLayout *layout,
PropertyRNA *asset_library_prop = RNA_struct_find_property(asset_library_dataptr,
asset_library_propname);
- AssetLibraryReference asset_library = ED_asset_library_reference_from_enum_value(
+ AssetLibraryReference asset_library_ref = 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) {
+ if (asset_library_ref.type != ASSET_LIBRARY_LOCAL) {
uiItemO(row, "", ICON_FILE_REFRESH, "ASSET_OT_list_refresh");
}
- ED_assetlist_storage_fetch(&asset_library, C);
- ED_assetlist_ensure_previews_job(&asset_library, C);
- const int tot_items = ED_assetlist_size(&asset_library);
+ ED_assetlist_storage_fetch(&asset_library_ref, C);
+ ED_assetlist_ensure_previews_job(&asset_library_ref, C);
+ const int tot_items = ED_assetlist_size(&asset_library_ref);
asset_view_template_refresh_asset_collection(
- asset_library, *filter_settings, *assets_dataptr, assets_propname);
+ asset_library_ref, *filter_settings, *assets_dataptr, assets_propname);
AssetViewListData *list_data = (AssetViewListData *)MEM_mallocN(sizeof(*list_data),
"AssetViewListData");
- list_data->asset_library = asset_library;
+ list_data->asset_library_ref = asset_library_ref;
list_data->screen = CTX_wm_screen(C);
/* TODO can we have some kind of model-view API to handle referencing, filtering and lazy loading
diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c
index 766840909cc..47ff0c9fd3c 100644
--- a/source/blender/editors/interface/interface_templates.c
+++ b/source/blender/editors/interface/interface_templates.c
@@ -2621,6 +2621,72 @@ static void constraint_active_func(bContext *UNUSED(C), void *ob_v, void *con_v)
ED_object_constraint_active_set(ob_v, con_v);
}
+static void constraint_ops_extra_draw(bContext *C, uiLayout *layout, void *con_v)
+{
+ PointerRNA op_ptr;
+ uiLayout *row;
+ bConstraint *con = (bConstraint *)con_v;
+
+ PointerRNA ptr;
+ Object *ob = ED_object_active_context(C);
+
+ RNA_pointer_create(&ob->id, &RNA_Constraint, con, &ptr);
+ uiLayoutSetContextPointer(layout, "constraint", &ptr);
+ uiLayoutSetOperatorContext(layout, WM_OP_INVOKE_DEFAULT);
+
+ uiLayoutSetUnitsX(layout, 4.0f);
+
+ /* Apply. */
+ uiItemO(layout,
+ CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Apply"),
+ ICON_CHECKMARK,
+ "CONSTRAINT_OT_apply");
+
+ /* Duplicate. */
+ uiItemO(layout,
+ CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Duplicate"),
+ ICON_DUPLICATE,
+ "CONSTRAINT_OT_copy");
+
+ uiItemO(layout,
+ CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Copy to Selected"),
+ 0,
+ "CONSTRAINT_OT_copy_to_selected");
+
+ uiItemS(layout);
+
+ /* Move to first. */
+ row = uiLayoutColumn(layout, false);
+ uiItemFullO(row,
+ "CONSTRAINT_OT_move_to_index",
+ IFACE_("Move to First"),
+ ICON_TRIA_UP,
+ NULL,
+ WM_OP_INVOKE_DEFAULT,
+ 0,
+ &op_ptr);
+ RNA_int_set(&op_ptr, "index", 0);
+ if (!con->prev) {
+ uiLayoutSetEnabled(row, false);
+ }
+
+ /* Move to last. */
+ row = uiLayoutColumn(layout, false);
+ uiItemFullO(row,
+ "CONSTRAINT_OT_move_to_index",
+ IFACE_("Move to Last"),
+ ICON_TRIA_DOWN,
+ NULL,
+ WM_OP_INVOKE_DEFAULT,
+ 0,
+ &op_ptr);
+ ListBase *constraint_list = ED_object_constraint_list_from_constraint(ob, con, NULL);
+ RNA_int_set(&op_ptr, "index", BLI_listbase_count(constraint_list) - 1);
+ if (!con->next) {
+ uiLayoutSetEnabled(row, false);
+ }
+}
+
static void draw_constraint_header(uiLayout *layout, Object *ob, bConstraint *con)
{
bPoseChannel *pchan = BKE_pose_channel_active(ob);
@@ -2652,11 +2718,13 @@ static void draw_constraint_header(uiLayout *layout, Object *ob, bConstraint *co
UI_block_emboss_set(block, UI_EMBOSS);
+ uiLayout *row = uiLayoutRow(layout, true);
+
if (proxy_protected == 0) {
- uiItemR(layout, &ptr, "name", 0, "", ICON_NONE);
+ uiItemR(row, &ptr, "name", 0, "", ICON_NONE);
}
else {
- uiItemL(layout, con->name, ICON_NONE);
+ uiItemL(row, con->name, ICON_NONE);
}
/* proxy-protected constraints cannot be edited, so hide up/down + close buttons */
@@ -2697,22 +2765,22 @@ static void draw_constraint_header(uiLayout *layout, Object *ob, bConstraint *co
UI_block_emboss_set(block, UI_EMBOSS);
}
else {
- /* enabled */
- UI_block_emboss_set(block, UI_EMBOSS_NONE_OR_STATUS);
- uiItemR(layout, &ptr, "mute", 0, "", 0);
- UI_block_emboss_set(block, UI_EMBOSS);
+ /* Enabled eye icon. */
+ uiItemR(row, &ptr, "enabled", 0, "", ICON_NONE);
- uiLayoutSetOperatorContext(layout, WM_OP_INVOKE_DEFAULT);
+ /* Extra operators menu. */
+ uiItemMenuF(row, "", ICON_DOWNARROW_HLT, constraint_ops_extra_draw, con);
/* Close 'button' - emboss calls here disable drawing of 'button' behind X */
- UI_block_emboss_set(block, UI_EMBOSS_NONE);
- uiItemO(layout, "", ICON_X, "CONSTRAINT_OT_delete");
- UI_block_emboss_set(block, UI_EMBOSS);
-
- /* Some extra padding at the end, so the 'x' icon isn't too close to drag button. */
- uiItemS(layout);
+ sub = uiLayoutRow(row, false);
+ uiLayoutSetEmboss(sub, UI_EMBOSS_NONE);
+ uiLayoutSetOperatorContext(sub, WM_OP_INVOKE_DEFAULT);
+ uiItemO(sub, "", ICON_X, "CONSTRAINT_OT_delete");
}
+ /* Some extra padding at the end, so the 'x' icon isn't too close to drag button. */
+ uiItemS(layout);
+
/* Set but-locks for protected settings (magic numbers are used here!) */
if (proxy_protected) {
UI_block_lock_set(block, true, TIP_("Cannot edit Proxy-Protected Constraint"));
diff --git a/source/blender/editors/mesh/editmesh_knife.c b/source/blender/editors/mesh/editmesh_knife.c
index 73f6a3f3238..3e3593d18fd 100644
--- a/source/blender/editors/mesh/editmesh_knife.c
+++ b/source/blender/editors/mesh/editmesh_knife.c
@@ -2630,24 +2630,24 @@ static void knife_init_colors(KnifeColors *colors)
}
/* called when modal loop selection gets set up... */
-static void knifetool_init(bContext *C,
+static void knifetool_init(ViewContext *vc,
KnifeTool_OpData *kcd,
const bool only_select,
const bool cut_through,
const bool is_interactive)
{
- Scene *scene = CTX_data_scene(C);
- Object *obedit = CTX_data_edit_object(C);
+ kcd->vc = *vc;
+
+ Scene *scene = vc->scene;
+ Object *obedit = vc->obedit;
/* assign the drawing handle for drawing preview line... */
kcd->scene = scene;
kcd->ob = obedit;
- kcd->region = CTX_wm_region(C);
+ kcd->region = vc->region;
invert_m4_m4_safe_ortho(kcd->ob_imat, kcd->ob->obmat);
- em_setup_viewcontext(C, &kcd->vc);
-
kcd->em = BKE_editmesh_from_object(kcd->ob);
/* cut all the way through the mesh if use_occlude_geometry button not pushed */
@@ -2694,14 +2694,14 @@ static void knifetool_init(bContext *C,
}
/* called when modal loop selection is done... */
-static void knifetool_exit_ex(bContext *C, KnifeTool_OpData *kcd)
+static void knifetool_exit_ex(KnifeTool_OpData *kcd)
{
if (!kcd) {
return;
}
if (kcd->is_interactive) {
- WM_cursor_modal_restore(CTX_wm_window(C));
+ WM_cursor_modal_restore(kcd->vc.win);
/* deactivate the extra drawing stuff in 3D-View */
ED_region_draw_cb_exit(kcd->region->type, kcd->draw_handle);
@@ -2735,10 +2735,10 @@ static void knifetool_exit_ex(bContext *C, KnifeTool_OpData *kcd)
/* destroy kcd itself */
MEM_freeN(kcd);
}
-static void knifetool_exit(bContext *C, wmOperator *op)
+static void knifetool_exit(wmOperator *op)
{
KnifeTool_OpData *kcd = op->customdata;
- knifetool_exit_ex(C, kcd);
+ knifetool_exit_ex(kcd);
op->customdata = NULL;
}
@@ -2827,10 +2827,10 @@ static void knifetool_finish(wmOperator *op)
/** \name Operator (#MESH_OT_knife_tool)
* \{ */
-static void knifetool_cancel(bContext *C, wmOperator *op)
+static void knifetool_cancel(bContext *UNUSED(C), wmOperator *op)
{
/* this is just a wrapper around exit() */
- knifetool_exit(C, op);
+ knifetool_exit(op);
}
wmKeyMap *knifetool_modal_keymap(wmKeyConfig *keyconf)
@@ -2872,7 +2872,7 @@ static int knifetool_modal(bContext *C, wmOperator *op, const wmEvent *event)
bool do_refresh = false;
if (!obedit || obedit->type != OB_MESH || BKE_editmesh_from_object(obedit) != kcd->em) {
- knifetool_exit(C, op);
+ knifetool_exit(op);
ED_workspace_status_text(C, NULL);
return OPERATOR_FINISHED;
}
@@ -2893,7 +2893,7 @@ static int knifetool_modal(bContext *C, wmOperator *op, const wmEvent *event)
/* finish */
ED_region_tag_redraw(kcd->region);
- knifetool_exit(C, op);
+ knifetool_exit(op);
ED_workspace_status_text(C, NULL);
return OPERATOR_CANCELLED;
@@ -2902,7 +2902,7 @@ static int knifetool_modal(bContext *C, wmOperator *op, const wmEvent *event)
ED_region_tag_redraw(kcd->region);
knifetool_finish(op);
- knifetool_exit(C, op);
+ knifetool_exit(op);
ED_workspace_status_text(C, NULL);
return OPERATOR_FINISHED;
@@ -3066,8 +3066,11 @@ static int knifetool_invoke(bContext *C, wmOperator *op, const wmEvent *event)
const bool cut_through = !RNA_boolean_get(op->ptr, "use_occlude_geometry");
const bool wait_for_input = RNA_boolean_get(op->ptr, "wait_for_input");
+ ViewContext vc;
KnifeTool_OpData *kcd;
+ em_setup_viewcontext(C, &vc);
+
if (only_select) {
Object *obedit = CTX_data_edit_object(C);
BMEditMesh *em = BKE_editmesh_from_object(obedit);
@@ -3080,7 +3083,7 @@ static int knifetool_invoke(bContext *C, wmOperator *op, const wmEvent *event)
/* alloc new customdata */
kcd = op->customdata = MEM_callocN(sizeof(KnifeTool_OpData), __func__);
- knifetool_init(C, kcd, only_select, cut_through, true);
+ knifetool_init(&vc, kcd, only_select, cut_through, true);
op->flag |= OP_IS_MODAL_CURSOR_REGION;
@@ -3165,7 +3168,7 @@ static bool edbm_mesh_knife_point_isect(LinkNode *polys, const float cent_ss[2])
/**
* \param use_tag: When set, tag all faces inside the polylines.
*/
-void EDBM_mesh_knife(bContext *C, LinkNode *polys, bool use_tag, bool cut_through)
+void EDBM_mesh_knife(ViewContext *vc, LinkNode *polys, bool use_tag, bool cut_through)
{
KnifeTool_OpData *kcd;
@@ -3176,7 +3179,7 @@ void EDBM_mesh_knife(bContext *C, LinkNode *polys, bool use_tag, bool cut_throug
kcd = MEM_callocN(sizeof(KnifeTool_OpData), __func__);
- knifetool_init(C, kcd, only_select, cut_through, is_interactive);
+ knifetool_init(vc, kcd, only_select, cut_through, is_interactive);
kcd->ignore_edge_snapping = true;
kcd->ignore_vert_snapping = true;
@@ -3313,7 +3316,7 @@ void EDBM_mesh_knife(bContext *C, LinkNode *polys, bool use_tag, bool cut_throug
#undef F_ISECT_SET_OUTSIDE
}
- knifetool_exit_ex(C, kcd);
+ knifetool_exit_ex(kcd);
kcd = NULL;
}
}
diff --git a/source/blender/editors/mesh/editmesh_knife_project.c b/source/blender/editors/mesh/editmesh_knife_project.c
index 09b17acf56d..16661897e87 100644
--- a/source/blender/editors/mesh/editmesh_knife_project.c
+++ b/source/blender/editors/mesh/editmesh_knife_project.c
@@ -32,6 +32,7 @@
#include "BKE_curve.h"
#include "BKE_customdata.h"
#include "BKE_editmesh.h"
+#include "BKE_layer.h"
#include "BKE_mesh.h"
#include "BKE_mesh_runtime.h"
#include "BKE_object.h"
@@ -124,21 +125,39 @@ static LinkNode *knifeproject_poly_from_object(const bContext *C,
static int knifeproject_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
- Object *obedit = CTX_data_edit_object(C);
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
const bool cut_through = RNA_boolean_get(op->ptr, "cut_through");
LinkNode *polys = NULL;
CTX_DATA_BEGIN (C, Object *, ob, selected_objects) {
- if (ob != obedit) {
- polys = knifeproject_poly_from_object(C, scene, ob, polys);
+ if (BKE_object_is_in_editmode(ob)) {
+ continue;
}
+ polys = knifeproject_poly_from_object(C, scene, ob, polys);
}
CTX_DATA_END;
- if (polys) {
- EDBM_mesh_knife(C, polys, true, cut_through);
+ if (polys == NULL) {
+ BKE_report(op->reports,
+ RPT_ERROR,
+ "No other selected objects have wire or boundary edges to use for projection");
+ return OPERATOR_CANCELLED;
+ }
+
+ ViewContext vc;
+ em_setup_viewcontext(C, &vc);
+
+ /* TODO: Ideally meshes would occlude each other, currently they don't
+ * since each knife-project runs as a separate operation. */
+ uint objects_len;
+ Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
+ vc.view_layer, vc.v3d, &objects_len);
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *obedit = objects[ob_index];
+ ED_view3d_viewcontext_init_object(&vc, obedit);
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+
+ EDBM_mesh_knife(&vc, polys, true, cut_through);
/* select only tagged faces */
BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_SELECT, false);
@@ -148,16 +167,12 @@ static int knifeproject_exec(bContext *C, wmOperator *op)
BM_mesh_elem_hflag_enable_test(em->bm, BM_FACE, BM_ELEM_SELECT, true, false, BM_ELEM_TAG);
BM_mesh_select_mode_flush(em->bm);
-
- BLI_linklist_freeN(polys);
-
- return OPERATOR_FINISHED;
}
+ MEM_freeN(objects);
+
+ BLI_linklist_freeN(polys);
- BKE_report(op->reports,
- RPT_ERROR,
- "No other selected objects have wire or boundary edges to use for projection");
- return OPERATOR_CANCELLED;
+ return OPERATOR_FINISHED;
}
void MESH_OT_knife_project(wmOperatorType *ot)
diff --git a/source/blender/editors/mesh/editmesh_utils.c b/source/blender/editors/mesh/editmesh_utils.c
index 85c646d689c..c6a8e771362 100644
--- a/source/blender/editors/mesh/editmesh_utils.c
+++ b/source/blender/editors/mesh/editmesh_utils.c
@@ -355,10 +355,7 @@ void EDBM_mesh_clear(BMEditMesh *em)
/* free tessellation data */
em->tottri = 0;
- if (em->looptris) {
- MEM_freeN(em->looptris);
- em->looptris = NULL;
- }
+ MEM_SAFE_FREE(em->looptris);
}
void EDBM_mesh_load(Main *bmain, Object *ob)
diff --git a/source/blender/editors/mesh/mesh_data.c b/source/blender/editors/mesh/mesh_data.c
index b2379610f65..c075d2550cb 100644
--- a/source/blender/editors/mesh/mesh_data.c
+++ b/source/blender/editors/mesh/mesh_data.c
@@ -1007,15 +1007,8 @@ static int mesh_customdata_custom_splitnormals_add_exec(bContext *C, wmOperator
if (me->flag & ME_AUTOSMOOTH) {
float(*polynors)[3] = MEM_mallocN(sizeof(*polynors) * (size_t)me->totpoly, __func__);
- BKE_mesh_calc_normals_poly(me->mvert,
- NULL,
- me->totvert,
- me->mloop,
- me->mpoly,
- me->totloop,
- me->totpoly,
- polynors,
- true);
+ BKE_mesh_calc_normals_poly(
+ me->mvert, me->totvert, me->mloop, me->totloop, me->mpoly, me->totpoly, polynors);
BKE_edges_sharp_from_angle_set(me->mvert,
me->totvert,
diff --git a/source/blender/editors/mesh/mesh_intern.h b/source/blender/editors/mesh/mesh_intern.h
index f25317e8e85..03c99e40d1e 100644
--- a/source/blender/editors/mesh/mesh_intern.h
+++ b/source/blender/editors/mesh/mesh_intern.h
@@ -150,7 +150,10 @@ void MESH_OT_face_split_by_edges(struct wmOperatorType *ot);
/* *** editmesh_knife.c *** */
void MESH_OT_knife_tool(struct wmOperatorType *ot);
void MESH_OT_knife_project(struct wmOperatorType *ot);
-void EDBM_mesh_knife(struct bContext *C, struct LinkNode *polys, bool use_tag, bool cut_through);
+void EDBM_mesh_knife(struct ViewContext *vc,
+ struct LinkNode *polys,
+ bool use_tag,
+ bool cut_through);
struct wmKeyMap *knifetool_modal_keymap(struct wmKeyConfig *keyconf);
diff --git a/source/blender/editors/mesh/mesh_mirror.c b/source/blender/editors/mesh/mesh_mirror.c
index 5eb69aab48b..1a3e6a59588 100644
--- a/source/blender/editors/mesh/mesh_mirror.c
+++ b/source/blender/editors/mesh/mesh_mirror.c
@@ -365,10 +365,7 @@ void ED_mesh_mirrtopo_init(BMEditMesh *em,
void ED_mesh_mirrtopo_free(MirrTopoStore_t *mesh_topo_store)
{
- if (mesh_topo_store->index_lookup) {
- MEM_freeN(mesh_topo_store->index_lookup);
- }
- mesh_topo_store->index_lookup = NULL;
+ MEM_SAFE_FREE(mesh_topo_store->index_lookup);
mesh_topo_store->prev_vert_tot = -1;
mesh_topo_store->prev_edge_tot = -1;
}
diff --git a/source/blender/editors/object/object_constraint.c b/source/blender/editors/object/object_constraint.c
index 3d0213f1830..e0419e0a4cc 100644
--- a/source/blender/editors/object/object_constraint.c
+++ b/source/blender/editors/object/object_constraint.c
@@ -1483,13 +1483,11 @@ static int constraint_delete_exec(bContext *C, wmOperator *op)
/* free the constraint */
if (BKE_constraint_remove_ex(lb, ob, con, true)) {
- /* there's no active constraint now, so make sure this is the case */
- BKE_constraints_active_set(&ob->constraints, NULL);
/* needed to set the flags on posebones correctly */
ED_object_constraint_update(bmain, ob);
/* relations */
- DEG_relations_tag_update(CTX_data_main(C));
+ DEG_relations_tag_update(bmain);
/* notifiers */
WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT | NA_REMOVED, ob);
@@ -1507,10 +1505,10 @@ static int constraint_delete_exec(bContext *C, wmOperator *op)
static int constraint_delete_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
int retval;
- if (edit_constraint_invoke_properties(C, op, event, &retval)) {
- return constraint_delete_exec(C, op);
+ if (!edit_constraint_invoke_properties(C, op, event, &retval)) {
+ return OPERATOR_CANCELLED;
}
- return OPERATOR_CANCELLED;
+ return constraint_delete_exec(C, op);
}
void CONSTRAINT_OT_delete(wmOperatorType *ot)
@@ -1534,6 +1532,320 @@ void CONSTRAINT_OT_delete(wmOperatorType *ot)
/** \} */
/* ------------------------------------------------------------------- */
+/** \name Apply Constraint Operator
+ * \{ */
+
+static int constraint_apply_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene = CTX_data_scene(C);
+ Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
+ Main *bmain = CTX_data_main(C);
+ Object *ob = ED_object_active_context(C);
+ bConstraint *con = edit_constraint_property_get(C, op, ob, 0);
+ bPoseChannel *pchan;
+ ListBase *constraints = ED_object_constraint_list_from_constraint(ob, con, &pchan);
+
+ /* Store name temporarily for report. */
+ char name[MAX_NAME];
+ strcpy(name, con->name);
+ const bool is_first_constraint = con != constraints->first;
+
+ /* Copy the constraint. */
+ bool success;
+ if (pchan) {
+ success = BKE_constraint_apply_and_remove_for_pose(
+ depsgraph, scene, constraints, ob, con, pchan);
+ }
+ else {
+ success = BKE_constraint_apply_and_remove_for_object(depsgraph, scene, constraints, ob, con);
+ }
+
+ if (!success) {
+ /* Couldn't remove due to some invalid data. */
+ return OPERATOR_CANCELLED;
+ }
+
+ /* Update for any children that may get moved. */
+ DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM);
+
+ /* Needed to set the flags on posebones correctly. */
+ ED_object_constraint_update(bmain, ob);
+
+ DEG_relations_tag_update(bmain);
+ WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT | NA_REMOVED, ob);
+ if (pchan) {
+ WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
+ }
+ else {
+ WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, ob);
+ }
+
+ if (RNA_boolean_get(op->ptr, "report")) {
+ if (is_first_constraint) {
+ BKE_report(op->reports,
+ RPT_INFO,
+ "Applied constraint was not first, result may not be as expected");
+ }
+ else {
+ /* Only add this report if the operator didn't cause another one. The purpose here is
+ * to alert that something happened, and the previous report will do that anyway. */
+ BKE_reportf(op->reports, RPT_INFO, "Applied constraint: %s", name);
+ }
+ }
+
+ return OPERATOR_FINISHED;
+}
+
+static int constraint_apply_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ int retval;
+ if (!edit_constraint_invoke_properties(C, op, event, &retval)) {
+ return OPERATOR_CANCELLED;
+ }
+ return constraint_apply_exec(C, op);
+}
+
+void CONSTRAINT_OT_apply(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Apply Constraint";
+ ot->idname = "CONSTRAINT_OT_apply";
+ ot->description = "Apply constraint and remove from the stack";
+
+ /* callbacks */
+ ot->invoke = constraint_apply_invoke;
+ ot->exec = constraint_apply_exec;
+ ot->poll = edit_constraint_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ edit_constraint_properties(ot);
+ edit_constraint_report_property(ot);
+}
+
+/** \} */
+
+/* ------------------------------------------------------------------- */
+/** \name Copy Constraint Operator
+ * \{ */
+
+static int constraint_copy_exec(bContext *C, wmOperator *op)
+{
+ Main *bmain = CTX_data_main(C);
+ Object *ob = ED_object_active_context(C);
+ bConstraint *con = edit_constraint_property_get(C, op, ob, 0);
+ bPoseChannel *pchan;
+ ListBase *constraints = ED_object_constraint_list_from_constraint(ob, con, &pchan);
+
+ /* Store name temporarily for report. */
+ char name[MAX_NAME];
+ strcpy(name, con->name);
+
+ /* Copy the constraint. */
+ bConstraint *copy_con;
+ if (pchan) {
+ copy_con = BKE_constraint_copy_for_pose(ob, pchan, con);
+ }
+ else {
+ copy_con = BKE_constraint_copy_for_object(ob, con);
+ }
+
+ if (!copy_con) {
+ /* Couldn't remove due to some invalid data. */
+ return OPERATOR_CANCELLED;
+ }
+ /* Move constraint to correct position. */
+ const int new_index = BLI_findindex(constraints, con) + 1;
+ const int current_index = BLI_findindex(constraints, copy_con);
+ BLI_assert(new_index >= 0);
+ BLI_assert(current_index >= 0);
+ BLI_listbase_link_move(constraints, copy_con, new_index - current_index);
+
+ /* Needed to set the flags on posebones correctly. */
+ ED_object_constraint_update(bmain, ob);
+
+ DEG_relations_tag_update(bmain);
+ WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT | NA_ADDED, ob);
+
+ if (RNA_boolean_get(op->ptr, "report")) {
+ BKE_reportf(op->reports, RPT_INFO, "Copied constraint: %s", name);
+ }
+
+ return OPERATOR_FINISHED;
+}
+
+static int constraint_copy_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ int retval;
+ if (!edit_constraint_invoke_properties(C, op, event, &retval)) {
+ return OPERATOR_CANCELLED;
+ }
+ return constraint_copy_exec(C, op);
+}
+
+void CONSTRAINT_OT_copy(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Duplicate Constraint";
+ ot->idname = "CONSTRAINT_OT_copy";
+ ot->description = "Duplicate constraint at the same position in the stack";
+
+ /* callbacks */
+ ot->invoke = constraint_copy_invoke;
+ ot->exec = constraint_copy_exec;
+ ot->poll = edit_constraint_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ edit_constraint_properties(ot);
+ edit_constraint_report_property(ot);
+}
+
+/** \} */
+
+/* ------------------------------------------------------------------- */
+/** \name Copy Constraint To Selected Operator
+ * \{ */
+
+static int constraint_copy_to_selected_exec(bContext *C, wmOperator *op)
+{
+ Main *bmain = CTX_data_main(C);
+ Object *obact = ED_object_active_context(C);
+ bConstraint *con = edit_constraint_property_get(C, op, obact, 0);
+ bPoseChannel *pchan;
+ ED_object_constraint_list_from_constraint(obact, con, &pchan);
+
+ if (pchan) {
+ /* Don't do anything if bone doesn't exist or doesn't have any constraints. */
+ if (pchan->constraints.first == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "No constraints for copying");
+ return OPERATOR_CANCELLED;
+ }
+
+ Object *prev_ob = NULL;
+
+ /* Copy all constraints from active posebone to all selected posebones. */
+ CTX_DATA_BEGIN_WITH_ID (C, bPoseChannel *, chan, selected_pose_bones, Object *, ob) {
+ /* If we're not handling the object we're copying from, copy all constraints over. */
+ if (pchan == chan) {
+ continue;
+ }
+
+ BKE_constraint_copy_for_pose(ob, chan, con);
+ /* Update flags (need to add here, not just copy). */
+ chan->constflag |= pchan->constflag;
+
+ if (prev_ob == ob) {
+ continue;
+ }
+
+ BKE_pose_tag_recalc(bmain, ob->pose);
+ DEG_id_tag_update((ID *)ob, ID_RECALC_GEOMETRY);
+ prev_ob = ob;
+ }
+ CTX_DATA_END;
+ }
+ else {
+ /* Copy all constraints from active object to all selected objects. */
+ CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) {
+ /* If we're not handling the object we're copying from, copy all constraints over. */
+ if (obact == ob) {
+ continue;
+ }
+
+ BKE_constraint_copy_for_object(ob, con);
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY | ID_RECALC_TRANSFORM);
+ }
+ CTX_DATA_END;
+ }
+
+ /* Force depsgraph to get recalculated since new relationships added. */
+ DEG_relations_tag_update(bmain);
+
+ WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT, NULL);
+
+ return OPERATOR_FINISHED;
+}
+
+static int constraint_copy_to_selected_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ int retval;
+ if (!edit_constraint_invoke_properties(C, op, event, &retval)) {
+ return retval;
+ }
+ return constraint_copy_to_selected_exec(C, op);
+}
+
+static bool constraint_copy_to_selected_poll(bContext *C)
+{
+ PointerRNA ptr = CTX_data_pointer_get_type(C, "constraint", &RNA_Constraint);
+ Object *obact = (ptr.owner_id) ? (Object *)ptr.owner_id : ED_object_active_context(C);
+ bConstraint *con = ptr.data;
+ bPoseChannel *pchan;
+ ED_object_constraint_list_from_constraint(obact, con, &pchan);
+
+ if (pchan) {
+ bool found = false;
+ CTX_DATA_BEGIN_WITH_ID (C, bPoseChannel *, chan, selected_pose_bones, Object *, UNUSED(ob)) {
+ if (pchan != chan) {
+ /** NOTE: Can not return here, because CTX_DATA_BEGIN_WITH_ID allocated
+ * a list that needs to be freed by CTX_DATA_END. */
+ found = true;
+ break;
+ }
+ }
+ CTX_DATA_END;
+ if (found) {
+ return true;
+ }
+
+ CTX_wm_operator_poll_msg_set(C, "No other bones are selected");
+ return false;
+ }
+
+ if (!obact) {
+ CTX_wm_operator_poll_msg_set(C, "No selected object to copy from");
+ return false;
+ }
+
+ bool found = false;
+ CTX_DATA_BEGIN (C, Object *, ob, selected_objects) {
+ if (ob != obact) {
+ /** NOTE: Can not return here, because CTX_DATA_BEGIN allocated
+ * a list that needs to be freed by CTX_DATA_END. */
+ found = true;
+ break;
+ }
+ }
+ CTX_DATA_END;
+ if (found) {
+ return true;
+ }
+
+ CTX_wm_operator_poll_msg_set(C, "No other objects are selected");
+ return false;
+}
+
+void CONSTRAINT_OT_copy_to_selected(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Copy Constraint To Selected";
+ ot->idname = "CONSTRAINT_OT_copy_to_selected";
+ ot->description = "Copy constraint to other selected objects/bones";
+
+ /* api callbacks */
+ ot->exec = constraint_copy_to_selected_exec;
+ ot->invoke = constraint_copy_to_selected_invoke;
+ ot->poll = constraint_copy_to_selected_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ edit_constraint_properties(ot);
+}
+
+/** \} */
+
+/* ------------------------------------------------------------------- */
/** \name Move Down Constraint Operator
* \{ */
diff --git a/source/blender/editors/object/object_intern.h b/source/blender/editors/object/object_intern.h
index 6299fdcc7f7..10e016738d0 100644
--- a/source/blender/editors/object/object_intern.h
+++ b/source/blender/editors/object/object_intern.h
@@ -226,6 +226,9 @@ void POSE_OT_ik_add(struct wmOperatorType *ot);
void POSE_OT_ik_clear(struct wmOperatorType *ot);
void CONSTRAINT_OT_delete(struct wmOperatorType *ot);
+void CONSTRAINT_OT_apply(struct wmOperatorType *ot);
+void CONSTRAINT_OT_copy(struct wmOperatorType *ot);
+void CONSTRAINT_OT_copy_to_selected(struct wmOperatorType *ot);
void CONSTRAINT_OT_move_up(struct wmOperatorType *ot);
void CONSTRAINT_OT_move_to_index(struct wmOperatorType *ot);
diff --git a/source/blender/editors/object/object_modes.c b/source/blender/editors/object/object_modes.c
index 36a4f002978..2c58ef02486 100644
--- a/source/blender/editors/object/object_modes.c
+++ b/source/blender/editors/object/object_modes.c
@@ -585,7 +585,7 @@ void OBJECT_OT_transfer_mode(wmOperatorType *ot)
"use_flash_on_transfer",
true,
"Flash On Transfer",
- "Flash the target object when transfering the mode");
+ "Flash the target object when transferring the mode");
}
/** \} */
diff --git a/source/blender/editors/object/object_ops.c b/source/blender/editors/object/object_ops.c
index a438c760d3b..c1928cf7f8a 100644
--- a/source/blender/editors/object/object_ops.c
+++ b/source/blender/editors/object/object_ops.c
@@ -183,6 +183,9 @@ void ED_operatortypes_object(void)
WM_operatortype_append(POSE_OT_ik_add);
WM_operatortype_append(POSE_OT_ik_clear);
WM_operatortype_append(CONSTRAINT_OT_delete);
+ WM_operatortype_append(CONSTRAINT_OT_apply);
+ WM_operatortype_append(CONSTRAINT_OT_copy);
+ WM_operatortype_append(CONSTRAINT_OT_copy_to_selected);
WM_operatortype_append(CONSTRAINT_OT_move_up);
WM_operatortype_append(CONSTRAINT_OT_move_down);
WM_operatortype_append(CONSTRAINT_OT_move_to_index);
diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c
index 92d0deb49d0..ec72ff11683 100644
--- a/source/blender/editors/object/object_relations.c
+++ b/source/blender/editors/object/object_relations.c
@@ -570,6 +570,8 @@ void ED_object_parent_clear(Object *ob, const int type)
/* clear parenting relationship completely */
ob->parent = NULL;
+ ob->partype = PAROBJECT;
+ ob->parsubstr[0] = 0;
break;
}
case CLEAR_PARENT_KEEP_TRANSFORM: {
@@ -2727,26 +2729,24 @@ char *ED_object_ot_drop_named_material_tooltip(bContext *C,
PointerRNA *properties,
const wmEvent *event)
{
- Base *base = ED_view3d_give_base_under_cursor(C, event->mval);
+ Object *ob = ED_view3d_give_object_under_cursor(C, event->mval);
+ if (ob == NULL) {
+ return BLI_strdup("");
+ }
char name[MAX_ID_NAME - 2];
RNA_string_get(properties, "name", name);
- if (base == NULL) {
- return BLI_strdup("");
- }
-
- Object *ob = base->object;
int active_mat_slot = max_ii(ob->actcol, 1);
Material *prev_mat = BKE_object_material_get(ob, active_mat_slot);
char *result;
if (prev_mat) {
- const char *tooltip = TIP_("Drop %s on %s (slot %d, replacing %s).");
+ const char *tooltip = TIP_("Drop %s on %s (slot %d, replacing %s)");
result = BLI_sprintfN(tooltip, name, ob->id.name + 2, active_mat_slot, prev_mat->id.name + 2);
}
else {
- const char *tooltip = TIP_("Drop %s on %s (slot %d).");
+ const char *tooltip = TIP_("Drop %s on %s (slot %d)");
result = BLI_sprintfN(tooltip, name, ob->id.name + 2, active_mat_slot);
}
return result;
@@ -2755,25 +2755,23 @@ char *ED_object_ot_drop_named_material_tooltip(bContext *C,
static int drop_named_material_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
Main *bmain = CTX_data_main(C);
- Base *base = ED_view3d_give_base_under_cursor(C, event->mval);
+ Object *ob = ED_view3d_give_object_under_cursor(C, event->mval);
Material *ma;
char name[MAX_ID_NAME - 2];
RNA_string_get(op->ptr, "name", name);
ma = (Material *)BKE_libblock_find_name(bmain, ID_MA, name);
- if (base == NULL || ma == NULL) {
+ if (ob == NULL || ma == NULL) {
return OPERATOR_CANCELLED;
}
- Object *ob = base->object;
const short active_mat_slot = ob->actcol;
- BKE_object_material_assign(
- CTX_data_main(C), base->object, ma, active_mat_slot, BKE_MAT_ASSIGN_USERPREF);
+ BKE_object_material_assign(CTX_data_main(C), ob, ma, active_mat_slot, BKE_MAT_ASSIGN_USERPREF);
- DEG_id_tag_update(&base->object->id, ID_RECALC_TRANSFORM);
+ DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM);
- WM_event_add_notifier(C, NC_OBJECT | ND_OB_SHADING, base->object);
+ WM_event_add_notifier(C, NC_OBJECT | ND_OB_SHADING, ob);
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, NULL);
WM_event_add_notifier(C, NC_MATERIAL | ND_SHADING_LINKS, ma);
diff --git a/source/blender/editors/object/object_vgroup.c b/source/blender/editors/object/object_vgroup.c
index f64f95c5322..7a42c9d5d8b 100644
--- a/source/blender/editors/object/object_vgroup.c
+++ b/source/blender/editors/object/object_vgroup.c
@@ -1582,7 +1582,7 @@ static void vgroup_fix(
mag = normalize_v3(norm);
if (mag) { /* zeros fix */
d = -dot_v3v3(norm, coord);
- /* dist = (dot_v3v3(norm, m.co) + d); */ /* UNUSED */
+ // dist = (dot_v3v3(norm, m.co) + d); /* UNUSED */
moveCloserToDistanceFromPlane(
depsgraph, scene_eval, object_eval, me, i, norm, coord, d, distToBe, strength, cp);
}
diff --git a/source/blender/editors/physics/particle_edit.c b/source/blender/editors/physics/particle_edit.c
index 5a629058c81..85883a2d29a 100644
--- a/source/blender/editors/physics/particle_edit.c
+++ b/source/blender/editors/physics/particle_edit.c
@@ -2957,10 +2957,7 @@ static int remove_tagged_particles(Object *ob, ParticleSystem *psys, int mirror)
}
edit->points = new_points;
- if (edit->mirror_cache) {
- MEM_freeN(edit->mirror_cache);
- edit->mirror_cache = NULL;
- }
+ MEM_SAFE_FREE(edit->mirror_cache);
if (psys->child) {
MEM_freeN(psys->child);
@@ -3576,10 +3573,7 @@ static void PE_mirror_x(Depsgraph *depsgraph, Scene *scene, Object *ob, int tagg
}
edit->points = new_points;
- if (edit->mirror_cache) {
- MEM_freeN(edit->mirror_cache);
- edit->mirror_cache = NULL;
- }
+ MEM_SAFE_FREE(edit->mirror_cache);
edit->totpoint = psys->totpart = newtotpart;
@@ -4497,10 +4491,7 @@ static int brush_add(const bContext *C, PEData *data, short number)
}
edit->points = new_points;
- if (edit->mirror_cache) {
- MEM_freeN(edit->mirror_cache);
- edit->mirror_cache = NULL;
- }
+ MEM_SAFE_FREE(edit->mirror_cache);
/* create tree for interpolation */
if (pset->flag & PE_INTERPOLATE_ADDED && psys->totpart) {
diff --git a/source/blender/editors/physics/particle_edit_undo.c b/source/blender/editors/physics/particle_edit_undo.c
index 2c7b5c0de6a..601a8385a24 100644
--- a/source/blender/editors/physics/particle_edit_undo.c
+++ b/source/blender/editors/physics/particle_edit_undo.c
@@ -128,10 +128,7 @@ static void undoptcache_to_editcache(PTCacheUndo *undo, PTCacheEdit *edit)
if (edit->points) {
MEM_freeN(edit->points);
}
- if (edit->mirror_cache) {
- MEM_freeN(edit->mirror_cache);
- edit->mirror_cache = NULL;
- }
+ MEM_SAFE_FREE(edit->mirror_cache);
edit->points = MEM_dupallocN(undo->points);
edit->totpoint = undo->totpoint;
diff --git a/source/blender/editors/render/render_preview.c b/source/blender/editors/render/render_preview.c
index bd4c83c107e..95351de45f0 100644
--- a/source/blender/editors/render/render_preview.c
+++ b/source/blender/editors/render/render_preview.c
@@ -47,6 +47,7 @@
#include "DNA_collection_types.h"
#include "DNA_light_types.h"
#include "DNA_material_types.h"
+#include "DNA_mesh_types.h"
#include "DNA_node_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
@@ -265,6 +266,11 @@ static const char *preview_collection_name(const ePreviewType pr_type)
}
}
+static bool render_engine_supports_ray_visibility(const Scene *sce)
+{
+ return !STREQ(sce->r.engine, RE_engine_id_BLENDER_EEVEE);
+}
+
static void switch_preview_collection_visibilty(ViewLayer *view_layer, const ePreviewType pr_type)
{
/* Set appropriate layer as visible. */
@@ -281,29 +287,60 @@ static void switch_preview_collection_visibilty(ViewLayer *view_layer, const ePr
}
}
-static void switch_preview_floor_visibility(ViewLayer *view_layer,
+static const char *preview_floor_material_name(const Scene *scene,
+ const ePreviewRenderMethod pr_method)
+{
+ if (pr_method == PR_ICON_RENDER && render_engine_supports_ray_visibility(scene)) {
+ return "FloorHidden";
+ }
+ return "Floor";
+}
+
+static void switch_preview_floor_material(Main *pr_main,
+ Mesh *me,
+ const Scene *scene,
+ const ePreviewRenderMethod pr_method)
+{
+ if (me->totcol == 0) {
+ return;
+ }
+
+ const char *material_name = preview_floor_material_name(scene, pr_method);
+ Material *mat = BLI_findstring(&pr_main->materials, material_name, offsetof(ID, name) + 2);
+ if (mat) {
+ me->mat[0] = mat;
+ }
+}
+
+static void switch_preview_floor_visibility(Main *pr_main,
+ const Scene *scene,
+ ViewLayer *view_layer,
const ePreviewRenderMethod pr_method)
{
/* Hide floor for icon renders. */
LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) {
if (STREQ(base->object->id.name + 2, "Floor")) {
+ base->object->visibility_flag &= ~OB_HIDE_RENDER;
if (pr_method == PR_ICON_RENDER) {
- base->object->visibility_flag |= OB_HIDE_RENDER;
+ if (!render_engine_supports_ray_visibility(scene)) {
+ base->object->visibility_flag |= OB_HIDE_RENDER;
+ }
}
- else {
- base->object->visibility_flag &= ~OB_HIDE_RENDER;
+ if (base->object->type == OB_MESH) {
+ switch_preview_floor_material(pr_main, base->object->data, scene, pr_method);
}
}
}
}
-static void set_preview_visibility(Scene *scene,
+static void set_preview_visibility(Main *pr_main,
+ Scene *scene,
ViewLayer *view_layer,
const ePreviewType pr_type,
const ePreviewRenderMethod pr_method)
{
switch_preview_collection_visibilty(view_layer, pr_type);
- switch_preview_floor_visibility(view_layer, pr_method);
+ switch_preview_floor_visibility(pr_main, scene, view_layer, pr_method);
BKE_layer_collection_sync(scene, view_layer);
}
@@ -357,10 +394,31 @@ static ID *duplicate_ids(ID *id, const bool allow_failure)
}
}
-static World *preview_get_world(Main *pr_main)
+static const char *preview_world_name(const Scene *sce,
+ const ID_Type id_type,
+ const ePreviewRenderMethod pr_method)
+{
+ /* When rendering material icons the floor will not be shown in the output. Cycles will use a
+ * material trick to show the floor in the reflections, but hide the floor for camera rays. For
+ * Eevee we use a transparent world that has a projected grid.
+ *
+ * In the future when Eevee supports vulkan raytracing we can re-evaluate and perhaps remove this
+ * approximation.
+ */
+ if (id_type == ID_MA && pr_method == PR_ICON_RENDER &&
+ !render_engine_supports_ray_visibility(sce)) {
+ return "WorldFloor";
+ }
+ return "World";
+}
+
+static World *preview_get_world(Main *pr_main,
+ const Scene *sce,
+ const ID_Type id_type,
+ const ePreviewRenderMethod pr_method)
{
World *result = NULL;
- const char *world_name = "World";
+ const char *world_name = preview_world_name(sce, id_type, pr_method);
result = BLI_findstring(&pr_main->worlds, world_name, offsetof(ID, name) + 2);
/* No world found return first world. */
@@ -380,9 +438,13 @@ static void preview_sync_exposure(World *dst, const World *src)
dst->range = src->range;
}
-static World *preview_prepare_world(Main *pr_main, const World *world)
+static World *preview_prepare_world(Main *pr_main,
+ const Scene *sce,
+ const World *world,
+ const ID_Type id_type,
+ const ePreviewRenderMethod pr_method)
{
- World *result = preview_get_world(pr_main);
+ World *result = preview_get_world(pr_main, sce, id_type, pr_method);
if (world) {
preview_sync_exposure(result, world);
}
@@ -436,7 +498,7 @@ static Scene *preview_prepare_scene(
sce->r.cfra = scene->r.cfra;
/* Setup the world. */
- sce->world = preview_prepare_world(pr_main, scene->world);
+ sce->world = preview_prepare_world(pr_main, sce, scene->world, id_type, sp->pr_method);
if (id_type == ID_TE) {
/* Texture is not actually rendered with engine, just set dummy value. */
@@ -458,7 +520,7 @@ static Scene *preview_prepare_scene(
/* Use current scene world to light sphere. */
sce->world = preview_get_localized_world(sp, scene->world);
}
- else if (sce->world) {
+ else if (sce->world && sp->pr_method != PR_ICON_RENDER) {
/* Use a default world color. Using the current
* scene world can be slow if it has big textures. */
sce->world->use_nodes = false;
@@ -472,7 +534,7 @@ static Scene *preview_prepare_scene(
sp->pr_main == G_pr_main_grease_pencil) ?
MA_SPHERE_A :
mat->pr_type;
- set_preview_visibility(sce, view_layer, preview_type, sp->pr_method);
+ set_preview_visibility(pr_main, sce, view_layer, preview_type, sp->pr_method);
if (sp->pr_method != PR_ICON_RENDER) {
if (mat->nodetree && sp->pr_method == PR_NODE_RENDER) {
@@ -536,7 +598,7 @@ static Scene *preview_prepare_scene(
BLI_addtail(&pr_main->lights, la);
}
- set_preview_visibility(sce, view_layer, MA_LAMP, sp->pr_method);
+ set_preview_visibility(pr_main, sce, view_layer, MA_LAMP, sp->pr_method);
if (sce->world) {
/* Only use lighting from the light. */
@@ -571,7 +633,7 @@ static Scene *preview_prepare_scene(
BLI_addtail(&pr_main->worlds, wrld);
}
- set_preview_visibility(sce, view_layer, MA_SKY, sp->pr_method);
+ set_preview_visibility(pr_main, sce, view_layer, MA_SKY, sp->pr_method);
sce->world = wrld;
if (wrld && wrld->nodetree && sp->pr_method == PR_NODE_RENDER) {
diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c
index c351ade9954..e08a4e946f6 100644
--- a/source/blender/editors/screen/area.c
+++ b/source/blender/editors/screen/area.c
@@ -834,9 +834,8 @@ void ED_area_status_text(ScrArea *area, const char *str)
BLI_strncpy(region->headerstr, str, UI_MAX_DRAW_STR);
BLI_str_rstrip(region->headerstr);
}
- else if (region->headerstr) {
- MEM_freeN(region->headerstr);
- region->headerstr = NULL;
+ else {
+ MEM_SAFE_FREE(region->headerstr);
}
ED_region_tag_redraw(region);
}
@@ -859,9 +858,8 @@ void ED_workspace_status_text(bContext *C, const char *str)
}
BLI_strncpy(workspace->status_text, str, UI_MAX_DRAW_STR);
}
- else if (workspace->status_text) {
- MEM_freeN(workspace->status_text);
- workspace->status_text = NULL;
+ else {
+ MEM_SAFE_FREE(workspace->status_text);
}
/* Redraw status bar. */
diff --git a/source/blender/editors/screen/screen_context.c b/source/blender/editors/screen/screen_context.c
index 8123d8bb104..b0181de96a0 100644
--- a/source/blender/editors/screen/screen_context.c
+++ b/source/blender/editors/screen/screen_context.c
@@ -113,7 +113,7 @@ const char *screen_context_dir[] = {
"active_editable_fcurve",
"selected_editable_keyframes",
"ui_list",
- "asset_library",
+ "asset_library_ref",
NULL,
};
@@ -1031,7 +1031,7 @@ static eContextResult screen_ctx_asset_library(const bContext *C, bContextDataRe
{
WorkSpace *workspace = CTX_wm_workspace(C);
CTX_data_pointer_set(
- result, &workspace->id, &RNA_AssetLibraryReference, &workspace->asset_library);
+ result, &workspace->id, &RNA_AssetLibraryReference, &workspace->asset_library_ref);
return CTX_RESULT_OK;
}
@@ -1118,7 +1118,7 @@ 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("asset_library_ref", screen_ctx_asset_library);
register_context_function("ui_list", screen_ctx_ui_list);
}
diff --git a/source/blender/editors/screen/screen_edit.c b/source/blender/editors/screen/screen_edit.c
index 2a81fcfde8f..506b5a9859d 100644
--- a/source/blender/editors/screen/screen_edit.c
+++ b/source/blender/editors/screen/screen_edit.c
@@ -722,10 +722,7 @@ void ED_region_exit(bContext *C, ARegion *region)
WM_event_modal_handler_region_replace(win, region, NULL);
WM_draw_region_free(region, true);
- if (region->headerstr) {
- MEM_freeN(region->headerstr);
- region->headerstr = NULL;
- }
+ MEM_SAFE_FREE(region->headerstr);
if (region->regiontimer) {
WM_event_remove_timer(wm, win, region->regiontimer);
@@ -1653,10 +1650,7 @@ void ED_refresh_viewport_fps(bContext *C)
}
else {
/* playback stopped or shouldn't be running */
- if (scene->fps_info) {
- MEM_freeN(scene->fps_info);
- }
- scene->fps_info = NULL;
+ MEM_SAFE_FREE(scene->fps_info);
}
}
diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c
index d8cef889a40..cff3ecfbbd3 100644
--- a/source/blender/editors/screen/screen_ops.c
+++ b/source/blender/editors/screen/screen_ops.c
@@ -403,7 +403,7 @@ bool ED_operator_object_active_editable_ex(bContext *C, const Object *ob)
}
if (ed_object_hidden(ob)) {
- CTX_wm_operator_poll_msg_set(C, "Cannot edit hidden obect");
+ CTX_wm_operator_poll_msg_set(C, "Cannot edit hidden object");
return false;
}
@@ -1023,10 +1023,7 @@ AZone *ED_area_azones_update(ScrArea *area, const int xy[2])
static void actionzone_exit(wmOperator *op)
{
- if (op->customdata) {
- MEM_freeN(op->customdata);
- }
- op->customdata = NULL;
+ MEM_SAFE_FREE(op->customdata);
G.moving &= ~G_TRANSFORM_WM;
}
@@ -1308,10 +1305,7 @@ static bool area_swap_init(wmOperator *op, const wmEvent *event)
static void area_swap_exit(bContext *C, wmOperator *op)
{
WM_cursor_modal_restore(CTX_wm_window(C));
- if (op->customdata) {
- MEM_freeN(op->customdata);
- }
- op->customdata = NULL;
+ MEM_SAFE_FREE(op->customdata);
}
static void area_swap_cancel(bContext *C, wmOperator *op)
@@ -1892,10 +1886,7 @@ static void area_move_apply(bContext *C, wmOperator *op)
static void area_move_exit(bContext *C, wmOperator *op)
{
- if (op->customdata) {
- MEM_freeN(op->customdata);
- }
- op->customdata = NULL;
+ MEM_SAFE_FREE(op->customdata);
/* this makes sure aligned edges will result in aligned grabbing */
BKE_screen_remove_double_scrverts(CTX_wm_screen(C));
@@ -3086,7 +3077,7 @@ static int keyframe_jump_exec(bContext *C, wmOperator *op)
}
/* find matching keyframe in the right direction */
- ActKeyColumn *ak;
+ const ActKeyColumn *ak;
if (next) {
ak = ED_keylist_find_next(keylist, cfra);
}
diff --git a/source/blender/editors/sculpt_paint/paint_image_2d.c b/source/blender/editors/sculpt_paint/paint_image_2d.c
index 23b90171a1d..a35e248a78c 100644
--- a/source/blender/editors/sculpt_paint/paint_image_2d.c
+++ b/source/blender/editors/sculpt_paint/paint_image_2d.c
@@ -837,10 +837,7 @@ static void brush_painter_2d_refresh_cache(ImagePaintState *s,
if (diameter != cache->lastdiameter || (mask_rotation != cache->last_mask_rotation) ||
renew_maxmask) {
- if (cache->tex_mask) {
- MEM_freeN(cache->tex_mask);
- cache->tex_mask = NULL;
- }
+ MEM_SAFE_FREE(cache->tex_mask);
brush_painter_2d_tex_mapping(s,
tile->canvas,
@@ -862,10 +859,7 @@ static void brush_painter_2d_refresh_cache(ImagePaintState *s,
}
/* curve mask can only change if the size changes */
- if (cache->curve_mask) {
- MEM_freeN(cache->curve_mask);
- cache->curve_mask = NULL;
- }
+ MEM_SAFE_FREE(cache->curve_mask);
cache->curve_mask = brush_painter_curve_mask_new(painter, diameter, size, pos);
diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c
index 8264affc465..7bde864e73f 100644
--- a/source/blender/editors/sculpt_paint/sculpt.c
+++ b/source/blender/editors/sculpt_paint/sculpt.c
@@ -6560,10 +6560,7 @@ static void sculpt_update_tex(const Scene *scene, Sculpt *sd, SculptSession *ss)
Brush *brush = BKE_paint_brush(&sd->paint);
const int radius = BKE_brush_size_get(scene, brush);
- if (ss->texcache) {
- MEM_freeN(ss->texcache);
- ss->texcache = NULL;
- }
+ MEM_SAFE_FREE(ss->texcache);
if (ss->tex_pool) {
BKE_image_pool_free(ss->tex_pool);
diff --git a/source/blender/editors/sculpt_paint/sculpt_dyntopo.c b/source/blender/editors/sculpt_paint/sculpt_dyntopo.c
index 87e0ea7f6a9..ae6dcbdbff4 100644
--- a/source/blender/editors/sculpt_paint/sculpt_dyntopo.c
+++ b/source/blender/editors/sculpt_paint/sculpt_dyntopo.c
@@ -94,15 +94,9 @@ void SCULPT_pbvh_clear(Object *ob)
ss->pbvh = NULL;
}
- if (ss->pmap) {
- MEM_freeN(ss->pmap);
- ss->pmap = NULL;
- }
+ MEM_SAFE_FREE(ss->pmap);
- if (ss->pmap_mem) {
- MEM_freeN(ss->pmap_mem);
- ss->pmap_mem = NULL;
- }
+ MEM_SAFE_FREE(ss->pmap_mem);
BKE_object_free_derived_caches(ob);
diff --git a/source/blender/editors/space_action/action_data.c b/source/blender/editors/space_action/action_data.c
index d69c7ab8d48..717d87c4972 100644
--- a/source/blender/editors/space_action/action_data.c
+++ b/source/blender/editors/space_action/action_data.c
@@ -599,16 +599,13 @@ void ED_animedit_unlink_action(
id_fake_user_clear(&act->id);
}
- /* If in Tweak Mode, don't unlink. Instead, this
- * becomes a shortcut to exit Tweak Mode instead
- */
+ /* If in Tweak Mode, don't unlink. Instead, this becomes a shortcut to exit Tweak Mode. */
if ((adt) && (adt->flag & ADT_NLA_EDIT_ON)) {
- /* Exit Tweak Mode */
BKE_nla_tweakmode_exit(adt);
- /* Flush this to the Action Editor (if that's where this change was initiated) */
- if (area->spacetype == SPACE_ACTION) {
- actedit_change_action(C, NULL);
+ Scene *scene = CTX_data_scene(C);
+ if (scene != NULL) {
+ scene->flag &= ~SCE_NLA_EDIT_ON;
}
}
else {
@@ -660,6 +657,9 @@ static int action_unlink_exec(bContext *C, wmOperator *op)
ED_animedit_unlink_action(C, NULL, adt, adt->action, op->reports, force_delete);
}
+ /* Unlink is also abused to exit NLA tweak mode. */
+ WM_main_add_notifier(NC_ANIMATION | ND_NLA_ACTCHANGE, NULL);
+
return OPERATOR_FINISHED;
}
diff --git a/source/blender/editors/space_action/action_draw.c b/source/blender/editors/space_action/action_draw.c
index ce07b9c5fad..903754f4fb1 100644
--- a/source/blender/editors/space_action/action_draw.c
+++ b/source/blender/editors/space_action/action_draw.c
@@ -302,6 +302,8 @@ void draw_channel_strips(bAnimContext *ac, SpaceAction *saction, ARegion *region
ymax = ACHANNEL_FIRST_TOP(ac);
+ struct AnimKeylistDrawList *draw_list = ED_keylist_draw_list_create();
+
for (ale = anim_data.first; ale; ale = ale->next, ymax -= ACHANNEL_STEP(ac)) {
float ymin = ymax - ACHANNEL_HEIGHT(ac);
float ycenter = (ymin + ymax) / 2.0f;
@@ -316,34 +318,41 @@ void draw_channel_strips(bAnimContext *ac, SpaceAction *saction, ARegion *region
/* draw 'keyframes' for each specific datatype */
switch (ale->datatype) {
case ALE_ALL:
- draw_summary_channel(v2d, ale->data, ycenter, ac->yscale_fac, action_flag);
+ draw_summary_channel(draw_list, ale->data, ycenter, ac->yscale_fac, action_flag);
break;
case ALE_SCE:
- draw_scene_channel(v2d, ads, ale->key_data, ycenter, ac->yscale_fac, action_flag);
+ draw_scene_channel(
+ draw_list, ads, ale->key_data, ycenter, ac->yscale_fac, action_flag);
break;
case ALE_OB:
- draw_object_channel(v2d, ads, ale->key_data, ycenter, ac->yscale_fac, action_flag);
+ draw_object_channel(
+ draw_list, ads, ale->key_data, ycenter, ac->yscale_fac, action_flag);
break;
case ALE_ACT:
- draw_action_channel(v2d, adt, ale->key_data, ycenter, ac->yscale_fac, action_flag);
+ draw_action_channel(
+ draw_list, adt, ale->key_data, ycenter, ac->yscale_fac, action_flag);
break;
case ALE_GROUP:
- draw_agroup_channel(v2d, adt, ale->data, ycenter, ac->yscale_fac, action_flag);
+ draw_agroup_channel(draw_list, adt, ale->data, ycenter, ac->yscale_fac, action_flag);
break;
case ALE_FCURVE:
- draw_fcurve_channel(v2d, adt, ale->key_data, ycenter, ac->yscale_fac, action_flag);
+ draw_fcurve_channel(
+ draw_list, adt, ale->key_data, ycenter, ac->yscale_fac, action_flag);
break;
case ALE_GPFRAME:
- draw_gpl_channel(v2d, ads, ale->data, ycenter, ac->yscale_fac, action_flag);
+ draw_gpl_channel(draw_list, ads, ale->data, ycenter, ac->yscale_fac, action_flag);
break;
case ALE_MASKLAY:
- draw_masklay_channel(v2d, ads, ale->data, ycenter, ac->yscale_fac, action_flag);
+ draw_masklay_channel(draw_list, ads, ale->data, ycenter, ac->yscale_fac, action_flag);
break;
}
}
}
}
+ ED_keylist_draw_list_flush(draw_list, v2d);
+ ED_keylist_draw_list_free(draw_list);
+
/* free temporary channels used for drawing */
ANIM_animdata_freelist(&anim_data);
}
diff --git a/source/blender/editors/space_action/action_select.c b/source/blender/editors/space_action/action_select.c
index 64ccca2c907..9dcfc626a50 100644
--- a/source/blender/editors/space_action/action_select.c
+++ b/source/blender/editors/space_action/action_select.c
@@ -170,10 +170,9 @@ static void actkeys_find_key_in_list_element(bAnimContext *ac,
/* half-size (for either side), but rounded up to nearest int (for easier targeting) */
key_hsize = roundf(key_hsize / 2.0f);
- float xmin = UI_view2d_region_to_view_x(v2d, region_x - (int)key_hsize);
- float xmax = UI_view2d_region_to_view_x(v2d, region_x + (int)key_hsize);
-
- const ActKeyColumn *ak = ED_keylist_find_any_between(keylist, xmin, xmax);
+ const Range2f range = {UI_view2d_region_to_view_x(v2d, region_x - (int)key_hsize),
+ UI_view2d_region_to_view_x(v2d, region_x + (int)key_hsize)};
+ const ActKeyColumn *ak = ED_keylist_find_any_between(keylist, range);
if (ak) {
/* set the frame to use, and apply inverse-correction for NLA-mapping
diff --git a/source/blender/editors/space_buttons/space_buttons.c b/source/blender/editors/space_buttons/space_buttons.c
index 57a7fe894b0..b04291b7ab4 100644
--- a/source/blender/editors/space_buttons/space_buttons.c
+++ b/source/blender/editors/space_buttons/space_buttons.c
@@ -811,6 +811,9 @@ static void buttons_area_listener(const wmSpaceTypeListenerParams *params)
break;
case NC_ANIMATION:
switch (wmn->data) {
+ case ND_NLA_ACTCHANGE:
+ ED_area_tag_redraw(area);
+ break;
case ND_KEYFRAME:
if (ELEM(wmn->action, NA_EDITED, NA_ADDED, NA_REMOVED)) {
ED_area_tag_redraw(area);
diff --git a/source/blender/editors/space_clip/clip_editor.c b/source/blender/editors/space_clip/clip_editor.c
index 67b4fd61d38..834ef847069 100644
--- a/source/blender/editors/space_clip/clip_editor.c
+++ b/source/blender/editors/space_clip/clip_editor.c
@@ -1037,6 +1037,7 @@ static void prefetch_freejob(void *pjv)
if (clip_local != NULL) {
BKE_libblock_free_datablock(&clip_local->id, 0);
BKE_libblock_free_data(&clip_local->id, false);
+ BLI_assert(!clip_local->id.py_instance); /* Or call #BKE_libblock_free_data_py. */
MEM_freeN(clip_local);
}
diff --git a/source/blender/editors/space_clip/tracking_ops_solve.c b/source/blender/editors/space_clip/tracking_ops_solve.c
index 96504651e44..58f9b307ef9 100644
--- a/source/blender/editors/space_clip/tracking_ops_solve.c
+++ b/source/blender/editors/space_clip/tracking_ops_solve.c
@@ -299,10 +299,7 @@ static int clear_solution_exec(bContext *C, wmOperator *UNUSED(op))
track->flag &= ~TRACK_HAS_BUNDLE;
}
- if (reconstruction->cameras != NULL) {
- MEM_freeN(reconstruction->cameras);
- reconstruction->cameras = NULL;
- }
+ MEM_SAFE_FREE(reconstruction->cameras);
reconstruction->camnr = 0;
reconstruction->flag &= ~TRACKING_RECONSTRUCTED;
diff --git a/source/blender/editors/space_file/file_draw.c b/source/blender/editors/space_file/file_draw.c
index 7d9b8583838..9a46579780e 100644
--- a/source/blender/editors/space_file/file_draw.c
+++ b/source/blender/editors/space_file/file_draw.c
@@ -1106,7 +1106,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 == ASSET_LIBRARY_LOCAL) ||
+ if ((asset_params->asset_library_ref.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_ops.c b/source/blender/editors/space_file/file_ops.c
index 944eb9988fa..2f1acd2ca4d 100644
--- a/source/blender/editors/space_file/file_ops.c
+++ b/source/blender/editors/space_file/file_ops.c
@@ -546,6 +546,9 @@ static int file_select_invoke(bContext *C, wmOperator *op, const wmEvent *event)
const bool fill = RNA_boolean_get(op->ptr, "fill");
const bool do_diropen = RNA_boolean_get(op->ptr, "open");
const bool deselect_all = RNA_boolean_get(op->ptr, "deselect_all");
+ const bool only_activate_if_selected = RNA_boolean_get(op->ptr, "only_activate_if_selected");
+ /* Used so right mouse clicks can do both, activate and spawn the context menu. */
+ const bool pass_through = RNA_boolean_get(op->ptr, "pass_through");
if (region->regiontype != RGN_TYPE_WINDOW) {
return OPERATOR_CANCELLED;
@@ -563,8 +566,13 @@ static int file_select_invoke(bContext *C, wmOperator *op, const wmEvent *event)
int numfiles = filelist_files_ensure(sfile->files);
if ((idx >= 0) && (idx < numfiles)) {
+ const bool is_selected = filelist_entry_select_index_get(sfile->files, idx, CHECK_ALL) &
+ FILE_SEL_SELECTED;
+ if (only_activate_if_selected && is_selected) {
+ /* Don't deselect other items. */
+ }
/* single select, deselect all selected first */
- if (!extend) {
+ else if (!extend) {
file_select_deselect_all(sfile, FILE_SEL_SELECTED);
}
}
@@ -593,7 +601,7 @@ static int file_select_invoke(bContext *C, wmOperator *op, const wmEvent *event)
WM_event_add_mousemove(CTX_wm_window(C)); /* for directory changes */
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_PARAMS, NULL);
- return OPERATOR_FINISHED;
+ return pass_through ? (OPERATOR_FINISHED | OPERATOR_PASS_THROUGH) : OPERATOR_FINISHED;
}
void FILE_OT_select(wmOperatorType *ot)
@@ -628,6 +636,20 @@ void FILE_OT_select(wmOperatorType *ot)
"Deselect On Nothing",
"Deselect all when nothing under the cursor");
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ prop = RNA_def_boolean(ot->srna,
+ "only_activate_if_selected",
+ false,
+ "Only Activate if Selected",
+ "Do not change selection if the item under the cursor is already "
+ "selected, only activate it");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ prop = RNA_def_boolean(ot->srna,
+ "pass_through",
+ false,
+ "Pass Through",
+ "Even on successful execution, pass the event on so other operators can "
+ "execute on it as well");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE | PROP_HIDDEN);
}
/** \} */
@@ -1366,7 +1388,9 @@ int file_highlight_set(SpaceFile *sfile, ARegion *region, int mx, int my)
FileSelectParams *params;
int numfiles, origfile;
- if (sfile == NULL || sfile->files == NULL) {
+ /* In case blender starts where the mouse is over a File browser,
+ * this operator can be invoked when the `sfile` or `sfile->layout` isn't initialized yet. */
+ if (sfile == NULL || sfile->files == NULL || sfile->layout == NULL) {
return 0;
}
@@ -2516,7 +2540,7 @@ void file_directory_enter_handle(bContext *C, void *UNUSED(arg_unused), void *UN
/* don't do for now because it selects entire text instead of
* placing cursor at the end */
- /* UI_textbutton_activate_but(C, but); */
+ // UI_textbutton_activate_but(C, but);
}
#if defined(WIN32)
else if (!can_create_dir(params->dir)) {
@@ -2750,20 +2774,6 @@ static void file_rename_state_activate(SpaceFile *sfile, int file_idx, bool requ
}
}
-static int file_rename_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *UNUSED(event))
-{
- ScrArea *area = CTX_wm_area(C);
- SpaceFile *sfile = (SpaceFile *)CTX_wm_space_data(C);
- FileSelectParams *params = ED_fileselect_get_active_params(sfile);
-
- if (params) {
- file_rename_state_activate(sfile, params->active_file, true);
- ED_area_tag_redraw(area);
- }
-
- return OPERATOR_FINISHED;
-}
-
static int file_rename_exec(bContext *C, wmOperator *UNUSED(op))
{
ScrArea *area = CTX_wm_area(C);
@@ -2771,7 +2781,7 @@ static int file_rename_exec(bContext *C, wmOperator *UNUSED(op))
FileSelectParams *params = ED_fileselect_get_active_params(sfile);
if (params) {
- file_rename_state_activate(sfile, params->highlight_file, false);
+ file_rename_state_activate(sfile, params->active_file, false);
ED_area_tag_redraw(area);
}
@@ -2786,7 +2796,6 @@ void FILE_OT_rename(struct wmOperatorType *ot)
ot->idname = "FILE_OT_rename";
/* api callbacks */
- ot->invoke = file_rename_invoke;
ot->exec = file_rename_exec;
/* File browsing only operator (not asset browsing). */
ot->poll = ED_operator_file_browsing_active;
diff --git a/source/blender/editors/space_file/filelist.c b/source/blender/editors/space_file/filelist.c
index 630c9aed157..f8ae4be9471 100644
--- a/source/blender/editors/space_file/filelist.c
+++ b/source/blender/editors/space_file/filelist.c
@@ -379,12 +379,13 @@ enum {
FLF_ASSETS_ONLY = 1 << 4,
};
+struct FileListReadJob;
typedef struct FileList {
FileDirEntryArr filelist;
eFileSelectType type;
/* The library this list was created for. Stored here so we know when to re-read. */
- AssetLibraryReference *asset_library;
+ AssetLibraryReference *asset_library_ref;
short flags;
@@ -415,8 +416,7 @@ typedef struct FileList {
bool (*check_dir_fn)(struct FileList *, char *, const bool);
/* Fill filelist (to be called by read job). */
- void (*read_job_fn)(
- Main *, struct FileList *, const char *, short *, short *, float *, ThreadMutex *);
+ void (*read_job_fn)(struct FileListReadJob *, short *, short *, float *);
/* Filter an entry of current filelist. */
bool (*filter_fn)(struct FileListInternEntry *, const char *, FileListFilter *);
@@ -459,34 +459,22 @@ enum {
static ImBuf *gSpecialFileImages[SPECIAL_IMG_MAX];
-static void filelist_readjob_main(Main *current_main,
- FileList *filelist,
- const char *main_name,
+static void filelist_readjob_main(struct FileListReadJob *job_params,
short *stop,
short *do_update,
- float *progress,
- ThreadMutex *lock);
-static void filelist_readjob_lib(Main *current_main,
- FileList *filelist,
- const char *main_name,
+ float *progress);
+static void filelist_readjob_lib(struct FileListReadJob *job_params,
short *stop,
short *do_update,
- float *progress,
- ThreadMutex *lock);
-static void filelist_readjob_dir(Main *current_main,
- FileList *filelist,
- const char *main_name,
+ float *progress);
+static void filelist_readjob_dir(struct FileListReadJob *job_params,
short *stop,
short *do_update,
- float *progress,
- ThreadMutex *lock);
-static void filelist_readjob_main_assets(Main *current_main,
- FileList *filelist,
- const char *main_name,
+ float *progress);
+static void filelist_readjob_main_assets(struct FileListReadJob *job_params,
short *stop,
short *do_update,
- float *progress,
- ThreadMutex *lock);
+ float *progress);
/* helper, could probably go in BKE actually? */
static int groupname_to_code(const char *group);
@@ -1065,28 +1053,28 @@ static bool filelist_compare_asset_libraries(const AssetLibraryReference *librar
}
/**
- * \param asset_library: May be NULL to unset the library.
+ * \param asset_library_ref: May be NULL to unset the library.
*/
-void filelist_setlibrary(FileList *filelist, const AssetLibraryReference *asset_library)
+void filelist_setlibrary(FileList *filelist, const AssetLibraryReference *asset_library_ref)
{
/* Unset if needed. */
- if (!asset_library) {
- if (filelist->asset_library) {
- MEM_SAFE_FREE(filelist->asset_library);
+ if (!asset_library_ref) {
+ if (filelist->asset_library_ref) {
+ MEM_SAFE_FREE(filelist->asset_library_ref);
filelist->flags |= FL_FORCE_RESET;
}
return;
}
- if (!filelist->asset_library) {
- filelist->asset_library = MEM_mallocN(sizeof(*filelist->asset_library),
- "filelist asset library");
- *filelist->asset_library = *asset_library;
+ if (!filelist->asset_library_ref) {
+ filelist->asset_library_ref = MEM_mallocN(sizeof(*filelist->asset_library_ref),
+ "filelist asset library");
+ *filelist->asset_library_ref = *asset_library_ref;
filelist->flags |= FL_FORCE_RESET;
}
- else if (!filelist_compare_asset_libraries(filelist->asset_library, asset_library)) {
- *filelist->asset_library = *asset_library;
+ else if (!filelist_compare_asset_libraries(filelist->asset_library_ref, asset_library_ref)) {
+ *filelist->asset_library_ref = *asset_library_ref;
filelist->flags |= FL_FORCE_RESET;
}
}
@@ -1791,7 +1779,7 @@ void filelist_free(struct FileList *filelist)
filelist->selection_state = NULL;
}
- MEM_SAFE_FREE(filelist->asset_library);
+ MEM_SAFE_FREE(filelist->asset_library_ref);
memset(&filelist->filter_data, 0, sizeof(filelist->filter_data));
@@ -1867,7 +1855,7 @@ bool filelist_is_dir(struct FileList *filelist, const char *path)
*/
void filelist_setdir(struct FileList *filelist, char *r_dir)
{
- const bool allow_invalid = filelist->asset_library != NULL;
+ const bool allow_invalid = filelist->asset_library_ref != NULL;
BLI_assert(strlen(r_dir) < FILE_MAX_LIBEXTRA);
BLI_path_normalize_dir(BKE_main_blendfile_path_from_global(), r_dir);
@@ -3133,14 +3121,29 @@ static void filelist_readjob_main_recursive(Main *bmain, FileList *filelist)
}
#endif
+typedef struct FileListReadJob {
+ ThreadMutex lock;
+ char main_name[FILE_MAX];
+ Main *current_main;
+ struct FileList *filelist;
+
+ /** Shallow copy of #filelist for thread-safe access.
+ *
+ * The job system calls #filelist_readjob_update which moves any read file from #tmp_filelist
+ * into #filelist in a thread-safe way.
+ *
+ * NOTE: #tmp_filelist is freed in #filelist_readjob_free, so any copied pointers need to be set
+ * to NULL to avoid double-freeing them. */
+ struct FileList *tmp_filelist;
+} FileListReadJob;
+
static void filelist_readjob_do(const bool do_lib,
- FileList *filelist,
- const char *main_name,
+ FileListReadJob *job_params,
const short *stop,
short *do_update,
- float *progress,
- ThreadMutex *lock)
+ float *progress)
{
+ FileList *filelist = job_params->tmp_filelist; /* Use the thread-safe filelist queue. */
ListBase entries = {0};
BLI_Stack *todo_dirs;
TodoDir *td_dir;
@@ -3164,7 +3167,7 @@ static void filelist_readjob_do(const bool do_lib,
BLI_strncpy(dir, filelist->filelist.root, sizeof(dir));
BLI_strncpy(filter_glob, filelist->filter_data.filter_glob, sizeof(filter_glob));
- BLI_path_normalize_dir(main_name, dir);
+ BLI_path_normalize_dir(job_params->main_name, dir);
td_dir->dir = BLI_strdup(dir);
while (!BLI_stack_is_empty(todo_dirs) && !(*stop)) {
@@ -3199,7 +3202,7 @@ static void filelist_readjob_do(const bool do_lib,
if (!nbr_entries) {
is_lib = false;
nbr_entries = filelist_readjob_list_dir(
- subdir, &entries, filter_glob, do_lib, main_name, skip_currpar);
+ subdir, &entries, filter_glob, do_lib, job_params->main_name, skip_currpar);
}
for (entry = entries.first; entry; entry = entry->next) {
@@ -3226,7 +3229,7 @@ static void filelist_readjob_do(const bool do_lib,
else {
/* We have a directory we want to list, add it to todo list! */
BLI_join_dirfile(dir, sizeof(dir), root, entry->relpath);
- BLI_path_normalize_dir(main_name, dir);
+ BLI_path_normalize_dir(job_params->main_name, dir);
td_dir = BLI_stack_push_r(todo_dirs);
td_dir->level = recursion_level + 1;
td_dir->dir = BLI_strdup(dir);
@@ -3236,14 +3239,14 @@ static void filelist_readjob_do(const bool do_lib,
}
if (nbr_entries) {
- BLI_mutex_lock(lock);
+ BLI_mutex_lock(&job_params->lock);
*do_update = true;
BLI_movelisttolist(&filelist->filelist.entries, &entries);
filelist->filelist.nbr_entries += nbr_entries;
- BLI_mutex_unlock(lock);
+ BLI_mutex_unlock(&job_params->lock);
}
nbr_done_dirs++;
@@ -3261,51 +3264,40 @@ static void filelist_readjob_do(const bool do_lib,
BLI_stack_free(todo_dirs);
}
-static void filelist_readjob_dir(Main *UNUSED(current_main),
- FileList *filelist,
- const char *main_name,
+static void filelist_readjob_dir(FileListReadJob *job_params,
short *stop,
short *do_update,
- float *progress,
- ThreadMutex *lock)
+ float *progress)
{
- filelist_readjob_do(false, filelist, main_name, stop, do_update, progress, lock);
+ filelist_readjob_do(false, job_params, stop, do_update, progress);
}
-static void filelist_readjob_lib(Main *UNUSED(current_main),
- FileList *filelist,
- const char *main_name,
+static void filelist_readjob_lib(FileListReadJob *job_params,
short *stop,
short *do_update,
- float *progress,
- ThreadMutex *lock)
+ float *progress)
{
- filelist_readjob_do(true, filelist, main_name, stop, do_update, progress, lock);
+ filelist_readjob_do(true, job_params, stop, do_update, progress);
}
-static void filelist_readjob_main(Main *current_main,
- FileList *filelist,
- const char *main_name,
+static void filelist_readjob_main(FileListReadJob *job_params,
short *stop,
short *do_update,
- float *progress,
- ThreadMutex *lock)
+ float *progress)
{
/* TODO! */
- filelist_readjob_dir(current_main, filelist, main_name, stop, do_update, progress, lock);
+ filelist_readjob_dir(job_params, stop, do_update, progress);
}
/**
* \warning Acts on main, so NOT thread-safe!
*/
-static void filelist_readjob_main_assets(Main *current_main,
- FileList *filelist,
- const char *UNUSED(main_name),
+static void filelist_readjob_main_assets(FileListReadJob *job_params,
short *UNUSED(stop),
short *do_update,
- float *UNUSED(progress),
- ThreadMutex *UNUSED(lock))
+ float *UNUSED(progress))
{
+ FileList *filelist = job_params->tmp_filelist; /* Use the thread-safe filelist queue. */
BLI_assert(BLI_listbase_is_empty(&filelist->filelist.entries) &&
(filelist->filelist.nbr_entries == FILEDIR_NBR_ENTRIES_UNSET));
@@ -3317,7 +3309,7 @@ static void filelist_readjob_main_assets(Main *current_main,
ID *id_iter;
int nbr_entries = 0;
- FOREACH_MAIN_ID_BEGIN (current_main, id_iter) {
+ FOREACH_MAIN_ID_BEGIN (job_params->current_main, id_iter) {
if (!id_iter->asset_data) {
continue;
}
@@ -3349,15 +3341,6 @@ static void filelist_readjob_main_assets(Main *current_main,
}
}
-typedef struct FileListReadJob {
- ThreadMutex lock;
- char main_name[FILE_MAX];
- Main *current_main;
- struct FileList *filelist;
- /** XXX We may use a simpler struct here... just a linked list and root path? */
- struct FileList *tmp_filelist;
-} FileListReadJob;
-
static void filelist_readjob_startjob(void *flrjv, short *stop, short *do_update, float *progress)
{
FileListReadJob *flrj = flrjv;
@@ -3381,17 +3364,11 @@ static void filelist_readjob_startjob(void *flrjv, short *stop, short *do_update
flrj->tmp_filelist->libfiledata = NULL;
memset(&flrj->tmp_filelist->filelist_cache, 0, sizeof(flrj->tmp_filelist->filelist_cache));
flrj->tmp_filelist->selection_state = NULL;
- flrj->tmp_filelist->asset_library = NULL;
+ flrj->tmp_filelist->asset_library_ref = NULL;
BLI_mutex_unlock(&flrj->lock);
- flrj->tmp_filelist->read_job_fn(flrj->current_main,
- flrj->tmp_filelist,
- flrj->main_name,
- stop,
- do_update,
- progress,
- &flrj->lock);
+ flrj->tmp_filelist->read_job_fn(flrj, stop, do_update, progress);
}
static void filelist_readjob_update(void *flrjv)
diff --git a/source/blender/editors/space_file/filelist.h b/source/blender/editors/space_file/filelist.h
index 6915e853681..d67cd89200b 100644
--- a/source/blender/editors/space_file/filelist.h
+++ b/source/blender/editors/space_file/filelist.h
@@ -73,7 +73,7 @@ void filelist_setfilter_options(struct FileList *filelist,
const char *filter_search);
void filelist_filter(struct FileList *filelist);
void filelist_setlibrary(struct FileList *filelist,
- const struct AssetLibraryReference *asset_library);
+ const struct AssetLibraryReference *asset_library_ref);
void filelist_init_icons(void);
void filelist_free_icons(void);
diff --git a/source/blender/editors/space_file/filesel.c b/source/blender/editors/space_file/filesel.c
index 89142b6669b..72e7e0716db 100644
--- a/source/blender/editors/space_file/filesel.c
+++ b/source/blender/editors/space_file/filesel.c
@@ -118,8 +118,8 @@ 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 = ASSET_LIBRARY_LOCAL;
- asset_params->asset_library.custom_library_index = -1;
+ asset_params->asset_library_ref.type = ASSET_LIBRARY_LOCAL;
+ asset_params->asset_library_ref.custom_library_index = -1;
asset_params->import_type = FILE_ASSET_IMPORT_APPEND;
}
@@ -415,7 +415,7 @@ FileAssetSelectParams *ED_fileselect_get_asset_params(const SpaceFile *sfile)
static void fileselect_refresh_asset_params(FileAssetSelectParams *asset_params)
{
- AssetLibraryReference *library = &asset_params->asset_library;
+ AssetLibraryReference *library = &asset_params->asset_library_ref;
FileSelectParams *base_params = &asset_params->base_params;
bUserAssetLibrary *user_library = NULL;
diff --git a/source/blender/editors/space_file/space_file.c b/source/blender/editors/space_file/space_file.c
index d7a6523de26..7deaa2fec60 100644
--- a/source/blender/editors/space_file/space_file.c
+++ b/source/blender/editors/space_file/space_file.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
@@ -176,10 +176,7 @@ static void file_free(SpaceLink *sl)
MEM_SAFE_FREE(sfile->asset_params);
MEM_SAFE_FREE(sfile->runtime);
- if (sfile->layout) {
- MEM_freeN(sfile->layout);
- sfile->layout = NULL;
- }
+ MEM_SAFE_FREE(sfile->layout);
}
/* spacetype; init callback, area size changes, screen set, etc */
@@ -337,11 +334,17 @@ static void file_refresh(const bContext *C, ScrArea *area)
sfile->files = filelist_new(params->type);
params->highlight_file = -1; /* added this so it opens nicer (ton) */
}
+
+ if (!U.experimental.use_extended_asset_browser && ED_fileselect_is_asset_browser(sfile)) {
+ /* Only poses supported as non-experimental right now. */
+ params->filter_id = FILTER_ID_AC;
+ }
+
filelist_settype(sfile->files, params->type);
filelist_setdir(sfile->files, params->dir);
filelist_setrecursion(sfile->files, params->recursion_level);
filelist_setsorting(sfile->files, params->sort, params->flag & FILE_SORT_INVERT);
- filelist_setlibrary(sfile->files, asset_params ? &asset_params->asset_library : NULL);
+ filelist_setlibrary(sfile->files, asset_params ? &asset_params->asset_library_ref : NULL);
filelist_setfilter_options(
sfile->files,
(params->flag & FILE_FILTER) != 0,
@@ -578,6 +581,16 @@ static void file_main_region_message_subscribe(const wmRegionMessageSubscribePar
/* All properties for this space type. */
WM_msg_subscribe_rna(mbus, &ptr, NULL, &msg_sub_value_area_tag_refresh, __func__);
}
+
+ /* Experimental Asset Browser features option. */
+ {
+ PointerRNA ptr;
+ RNA_pointer_create(NULL, &RNA_PreferencesExperimental, &U.experimental, &ptr);
+ PropertyRNA *prop = RNA_struct_find_property(&ptr, "use_extended_asset_browser");
+
+ /* All properties for this space type. */
+ WM_msg_subscribe_rna(mbus, &ptr, prop, &msg_sub_value_area_tag_refresh, __func__);
+ }
}
static bool file_main_region_needs_refresh_before_draw(SpaceFile *sfile)
@@ -855,18 +868,12 @@ static void file_space_subtype_item_extend(bContext *UNUSED(C),
EnumPropertyItem **item,
int *totitem)
{
- if (U.experimental.use_asset_browser) {
- RNA_enum_items_add(item, totitem, rna_enum_space_file_browse_mode_items);
- }
- else {
- RNA_enum_items_add_value(
- item, totitem, rna_enum_space_file_browse_mode_items, FILE_BROWSE_MODE_FILES);
- }
+ RNA_enum_items_add(item, totitem, rna_enum_space_file_browse_mode_items);
}
static const char *file_context_dir[] = {
"active_file",
- "asset_library",
+ "asset_library_ref",
"id",
NULL,
};
@@ -900,14 +907,14 @@ 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")) {
+ if (CTX_data_equals(member, "asset_library_ref")) {
FileAssetSelectParams *asset_params = ED_fileselect_get_asset_params(sfile);
if (!asset_params) {
return CTX_RESULT_NO_DATA;
}
CTX_data_pointer_set(
- result, &screen->id, &RNA_AssetLibraryReference, &asset_params->asset_library);
+ result, &screen->id, &RNA_AssetLibraryReference, &asset_params->asset_library_ref);
return CTX_RESULT_OK;
}
if (CTX_data_equals(member, "id")) {
diff --git a/source/blender/editors/space_graph/graph_buttons.c b/source/blender/editors/space_graph/graph_buttons.c
index ec5f443e2dc..f4c4b6cafcd 100644
--- a/source/blender/editors/space_graph/graph_buttons.c
+++ b/source/blender/editors/space_graph/graph_buttons.c
@@ -364,7 +364,7 @@ static void graph_panel_key_properties(const bContext *C, Panel *panel)
}
block = uiLayoutGetBlock(layout);
- /* UI_block_func_handle_set(block, do_graph_region_buttons, NULL); */
+ // UI_block_func_handle_set(block, do_graph_region_buttons, NULL);
uiLayoutSetPropSep(layout, true);
uiLayoutSetPropDecorate(layout, false);
diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c
index dad354ba8ee..613042a2ab9 100644
--- a/source/blender/editors/space_image/image_ops.c
+++ b/source/blender/editors/space_image/image_ops.c
@@ -2508,10 +2508,7 @@ static ImageNewData *image_new_init(bContext *C, wmOperator *op)
static void image_new_free(wmOperator *op)
{
- if (op->customdata) {
- MEM_freeN(op->customdata);
- op->customdata = NULL;
- }
+ MEM_SAFE_FREE(op->customdata);
}
static int image_new_exec(bContext *C, wmOperator *op)
diff --git a/source/blender/editors/space_info/info_stats.c b/source/blender/editors/space_info/info_stats.c
index 983e04127e0..e749e1a7947 100644
--- a/source/blender/editors/space_info/info_stats.c
+++ b/source/blender/editors/space_info/info_stats.c
@@ -466,10 +466,7 @@ static void stats_update(Depsgraph *depsgraph,
void ED_info_stats_clear(wmWindowManager *wm, ViewLayer *view_layer)
{
- if (view_layer->stats) {
- MEM_freeN(view_layer->stats);
- view_layer->stats = NULL;
- }
+ MEM_SAFE_FREE(view_layer->stats);
LISTBASE_FOREACH (wmWindow *, win, &wm->windows) {
ViewLayer *view_layer_test = WM_window_get_active_view_layer(win);
diff --git a/source/blender/editors/space_nla/nla_channels.c b/source/blender/editors/space_nla/nla_channels.c
index 0498964c549..1b87a8c6b9d 100644
--- a/source/blender/editors/space_nla/nla_channels.c
+++ b/source/blender/editors/space_nla/nla_channels.c
@@ -562,7 +562,8 @@ void NLA_OT_action_pushdown(wmOperatorType *ot)
static bool nla_action_unlink_poll(bContext *C)
{
if (ED_operator_nla_active(C)) {
- return nla_panel_context(C, NULL, NULL, NULL);
+ PointerRNA adt_ptr;
+ return (nla_panel_context(C, &adt_ptr, NULL, NULL) && (adt_ptr.data != NULL));
}
/* something failed... */
diff --git a/source/blender/editors/space_nla/nla_draw.c b/source/blender/editors/space_nla/nla_draw.c
index 2bf4c7d4344..c1b308d213f 100644
--- a/source/blender/editors/space_nla/nla_draw.c
+++ b/source/blender/editors/space_nla/nla_draw.c
@@ -140,13 +140,16 @@ static void nla_action_draw_keyframes(
if (key_len > 0) {
format = immVertexFormat();
- pos_id = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- uint size_id = GPU_vertformat_attr_add(format, "size", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
- uint color_id = GPU_vertformat_attr_add(
+ KeyframeShaderBindings sh_bindings;
+ sh_bindings.pos_id = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ sh_bindings.size_id = GPU_vertformat_attr_add(
+ format, "size", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
+ sh_bindings.color_id = GPU_vertformat_attr_add(
format, "color", GPU_COMP_U8, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
- uint outline_color_id = GPU_vertformat_attr_add(
+ sh_bindings.outline_color_id = GPU_vertformat_attr_add(
format, "outlineColor", GPU_COMP_U8, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
- uint flags_id = GPU_vertformat_attr_add(format, "flags", GPU_COMP_U32, 1, GPU_FETCH_INT);
+ sh_bindings.flags_id = GPU_vertformat_attr_add(
+ format, "flags", GPU_COMP_U32, 1, GPU_FETCH_INT);
GPU_program_point_size(true);
immBindBuiltinProgram(GPU_SHADER_KEYFRAME_DIAMOND);
@@ -165,11 +168,7 @@ static void nla_action_draw_keyframes(
ak->key_type,
KEYFRAME_SHAPE_FRAME,
1.0f,
- pos_id,
- size_id,
- color_id,
- outline_color_id,
- flags_id,
+ &sh_bindings,
KEYFRAME_HANDLE_NONE,
KEYFRAME_EXTREME_NONE);
}
diff --git a/source/blender/editors/space_nla/nla_edit.c b/source/blender/editors/space_nla/nla_edit.c
index 56efcd8571f..c75b874833a 100644
--- a/source/blender/editors/space_nla/nla_edit.c
+++ b/source/blender/editors/space_nla/nla_edit.c
@@ -241,9 +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 tweak-mode on at least one AnimData block,
- * set the flag for this in the active scene and send notifiers
- */
+ /* Clear the tweak-mode flag in the active scene and send notifiers. */
if (ac->scene) {
/* clear editing flag */
ac->scene->flag &= ~SCE_NLA_EDIT_ON;
diff --git a/source/blender/editors/space_node/drawnode.cc b/source/blender/editors/space_node/drawnode.cc
index 95eb1ccc025..0f7a911e3ce 100644
--- a/source/blender/editors/space_node/drawnode.cc
+++ b/source/blender/editors/space_node/drawnode.cc
@@ -3596,8 +3596,26 @@ static void std_node_socket_draw(
break;
}
case SOCK_TEXTURE: {
- uiTemplateID(
- layout, C, ptr, "default_value", "texture.new", nullptr, nullptr, 0, ICON_NONE, nullptr);
+ if (text[0] == '\0') {
+ uiTemplateID(layout,
+ C,
+ ptr,
+ "default_value",
+ "texture.new",
+ nullptr,
+ nullptr,
+ 0,
+ ICON_NONE,
+ nullptr);
+ }
+ else {
+ /* 0.3 split ratio is inconsistent, but use it here because the "New" button is large. */
+ uiLayout *row = uiLayoutSplit(layout, 0.3f, false);
+ uiItemL(row, text, 0);
+ uiTemplateID(
+ row, C, ptr, "default_value", "texture.new", nullptr, nullptr, 0, ICON_NONE, nullptr);
+ }
+
break;
}
case SOCK_MATERIAL: {
diff --git a/source/blender/editors/space_outliner/outliner_edit.c b/source/blender/editors/space_outliner/outliner_edit.c
index 5be6c69363e..738db28a2b6 100644
--- a/source/blender/editors/space_outliner/outliner_edit.c
+++ b/source/blender/editors/space_outliner/outliner_edit.c
@@ -1773,7 +1773,7 @@ static void tree_element_to_path(TreeElement *te,
char buf[128], *name;
temnext = (TreeElement *)(ld->next->data);
- /* tsenext = TREESTORE(temnext); */ /* UNUSED */
+ // tsenext = TREESTORE(temnext); /* UNUSED */
nextptr = &temnext->rnaptr;
name = RNA_struct_name_get_alloc(nextptr, buf, sizeof(buf), NULL);
diff --git a/source/blender/editors/space_outliner/outliner_tools.c b/source/blender/editors/space_outliner/outliner_tools.c
index e3aec572bd3..d88ae82cc9a 100644
--- a/source/blender/editors/space_outliner/outliner_tools.c
+++ b/source/blender/editors/space_outliner/outliner_tools.c
@@ -92,6 +92,7 @@
#include "RNA_define.h"
#include "RNA_enum_types.h"
+#include "SEQ_relations.h"
#include "SEQ_sequencer.h"
#include "outliner_intern.h"
@@ -845,7 +846,7 @@ static void id_override_library_create_fn(bContext *C,
if (!ID_IS_LINKED(te->store_elem->id)) {
break;
}
- /* If we'd need to override that arent ID, but it is not overridable, abort. */
+ /* If we'd need to override that aren't ID, but it is not overridable, abort. */
if (!ID_IS_OVERRIDABLE_LIBRARY(te->store_elem->id)) {
BKE_main_id_tag_all(bmain, LIB_TAG_DOIT, false);
BKE_reportf(reports,
@@ -1281,18 +1282,31 @@ static void ebone_fn(int event, TreeElement *te, TreeStoreElem *UNUSED(tselem),
}
}
-static void sequence_fn(int event, TreeElement *te, TreeStoreElem *tselem, void *scene_ptr)
+static void sequence_fn(int event, TreeElement *te, TreeStoreElem *UNUSED(tselem), void *scene_ptr)
{
Sequence *seq = (Sequence *)te->directdata;
- if (event == OL_DOP_SELECT) {
- Scene *scene = (Scene *)scene_ptr;
- Editing *ed = SEQ_editing_get(scene, false);
- if (BLI_findindex(ed->seqbasep, seq) != -1) {
+ Scene *scene = (Scene *)scene_ptr;
+ Editing *ed = SEQ_editing_get(scene, false);
+ if (BLI_findindex(ed->seqbasep, seq) != -1) {
+ if (event == OL_DOP_SELECT) {
ED_sequencer_select_sequence_single(scene, seq, true);
}
+ else if (event == OL_DOP_DESELECT) {
+ seq->flag &= ~SELECT;
+ }
+ else if (event == OL_DOP_HIDE) {
+ if (!(seq->flag & SEQ_MUTE)) {
+ seq->flag |= SEQ_MUTE;
+ SEQ_relations_invalidate_dependent(scene, seq);
+ }
+ }
+ else if (event == OL_DOP_UNHIDE) {
+ if (seq->flag & SEQ_MUTE) {
+ seq->flag &= ~SEQ_MUTE;
+ SEQ_relations_invalidate_dependent(scene, seq);
+ }
+ }
}
-
- (void)tselem;
}
static void gpencil_layer_fn(int event,
@@ -2709,16 +2723,6 @@ void OUTLINER_OT_modifier_operation(wmOperatorType *ot)
/** \name Data Menu Operator
* \{ */
-/* XXX: select linked is for RNA structs only. */
-static const EnumPropertyItem prop_data_op_types[] = {
- {OL_DOP_SELECT, "SELECT", 0, "Select", ""},
- {OL_DOP_DESELECT, "DESELECT", 0, "Deselect", ""},
- {OL_DOP_HIDE, "HIDE", 0, "Hide", ""},
- {OL_DOP_UNHIDE, "UNHIDE", 0, "Unhide", ""},
- {OL_DOP_SELECT_LINKED, "SELECT_LINKED", 0, "Select Linked", ""},
- {0, NULL, 0, NULL, NULL},
-};
-
static int outliner_data_operation_exec(bContext *C, wmOperator *op)
{
SpaceOutliner *space_outliner = CTX_wm_space_outliner(C);
@@ -2762,6 +2766,8 @@ static int outliner_data_operation_exec(bContext *C, wmOperator *op)
Scene *scene = CTX_data_scene(C);
outliner_do_data_operation(
space_outliner, datalevel, event, &space_outliner->tree, sequence_fn, scene);
+ WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER | NA_SELECTED, scene);
+ ED_undo_push(C, "Sequencer operation");
break;
}
@@ -2789,6 +2795,42 @@ static int outliner_data_operation_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
+/* Dynamically populate an enum of Keying Sets */
+static const EnumPropertyItem *outliner_data_op_sets_enum_item_fn(bContext *C,
+ PointerRNA *UNUSED(ptr),
+ PropertyRNA *UNUSED(prop),
+ bool *UNUSED(r_free))
+{
+ /* Check for invalid states. */
+ if (C == NULL) {
+ return DummyRNA_DEFAULT_items;
+ }
+
+ SpaceOutliner *space_outliner = CTX_wm_space_outliner(C);
+ if (space_outliner == NULL) {
+ return DummyRNA_DEFAULT_items;
+ }
+
+ static const EnumPropertyItem optype_sel_and_hide[] = {
+ {OL_DOP_SELECT, "SELECT", 0, "Select", ""},
+ {OL_DOP_DESELECT, "DESELECT", 0, "Deselect", ""},
+ {OL_DOP_HIDE, "HIDE", 0, "Hide", ""},
+ {OL_DOP_UNHIDE, "UNHIDE", 0, "Unhide", ""},
+ {0, NULL, 0, NULL, NULL}};
+
+ static const EnumPropertyItem optype_sel_linked[] = {
+ {OL_DOP_SELECT_LINKED, "SELECT_LINKED", 0, "Select Linked", ""}, {0, NULL, 0, NULL, NULL}};
+
+ TreeElement *te = get_target_element(space_outliner);
+ TreeStoreElem *tselem = TREESTORE(te);
+
+ if (tselem->type == TSE_RNA_STRUCT) {
+ return optype_sel_linked;
+ }
+
+ return optype_sel_and_hide;
+}
+
void OUTLINER_OT_data_operation(wmOperatorType *ot)
{
/* identifiers */
@@ -2802,7 +2844,8 @@ void OUTLINER_OT_data_operation(wmOperatorType *ot)
ot->flag = 0;
- ot->prop = RNA_def_enum(ot->srna, "type", prop_data_op_types, 0, "Data Operation", "");
+ ot->prop = RNA_def_enum(ot->srna, "type", DummyRNA_DEFAULT_items, 0, "Data Operation", "");
+ RNA_def_enum_funcs(ot->prop, outliner_data_op_sets_enum_item_fn);
}
/** \} */
diff --git a/source/blender/editors/space_sequencer/sequencer_add.c b/source/blender/editors/space_sequencer/sequencer_add.c
index b6b3d1841d2..265a52ed1a6 100644
--- a/source/blender/editors/space_sequencer/sequencer_add.c
+++ b/source/blender/editors/space_sequencer/sequencer_add.c
@@ -159,7 +159,7 @@ static void sequencer_generic_props__internal(wmOperatorType *ot, int flag)
"set_view_transform",
true,
"Set View Transform",
- "Set appropriate view transform based on media colorspace");
+ "Set appropriate view transform based on media color space");
}
}
@@ -565,10 +565,7 @@ static void sequencer_add_init(bContext *UNUSED(C), wmOperator *op)
static void sequencer_add_cancel(bContext *UNUSED(C), wmOperator *op)
{
- if (op->customdata) {
- MEM_freeN(op->customdata);
- }
- op->customdata = NULL;
+ MEM_SAFE_FREE(op->customdata);
}
static bool sequencer_add_draw_check_fn(PointerRNA *UNUSED(ptr),
diff --git a/source/blender/editors/space_text/text_draw.c b/source/blender/editors/space_text/text_draw.c
index 1d8bc427212..b6ba95885e4 100644
--- a/source/blender/editors/space_text/text_draw.c
+++ b/source/blender/editors/space_text/text_draw.c
@@ -686,10 +686,7 @@ static void text_update_drawcache(SpaceText *st, ARegion *region)
}
}
else {
- if (drawcache->line_height) {
- MEM_freeN(drawcache->line_height);
- drawcache->line_height = NULL;
- }
+ MEM_SAFE_FREE(drawcache->line_height);
if (full_update || drawcache->update_flag) {
nlines = BLI_listbase_count(&txt->lines);
diff --git a/source/blender/editors/space_text/text_ops.c b/source/blender/editors/space_text/text_ops.c
index b98dae0cd57..2b78ecb245d 100644
--- a/source/blender/editors/space_text/text_ops.c
+++ b/source/blender/editors/space_text/text_ops.c
@@ -236,10 +236,7 @@ void text_update_line_edited(TextLine *line)
}
/* we just free format here, and let it rebuild during draw */
- if (line->format) {
- MEM_freeN(line->format);
- line->format = NULL;
- }
+ MEM_SAFE_FREE(line->format);
}
void text_update_edited(Text *text)
diff --git a/source/blender/editors/space_view3d/view3d_buttons.c b/source/blender/editors/space_view3d/view3d_buttons.c
index 3428a738dde..b79303551a1 100644
--- a/source/blender/editors/space_view3d/view3d_buttons.c
+++ b/source/blender/editors/space_view3d/view3d_buttons.c
@@ -1456,7 +1456,7 @@ static void v3d_transform_butsR(uiLayout *layout, PointerRNA *ptr)
colsub = uiLayoutColumn(split, true);
uiItemR(colsub, ptr, "location", 0, NULL, ICON_NONE);
colsub = uiLayoutColumn(split, true);
- uiLayoutSetEmboss(colsub, UI_EMBOSS_NONE);
+ uiLayoutSetEmboss(colsub, UI_EMBOSS_NONE_OR_STATUS);
uiItemL(colsub, "", ICON_NONE);
uiItemR(colsub,
ptr,
@@ -1472,7 +1472,7 @@ static void v3d_transform_butsR(uiLayout *layout, PointerRNA *ptr)
colsub = uiLayoutColumn(split, true);
uiItemR(colsub, ptr, "rotation_quaternion", 0, IFACE_("Rotation"), ICON_NONE);
colsub = uiLayoutColumn(split, true);
- uiLayoutSetEmboss(colsub, UI_EMBOSS_NONE);
+ uiLayoutSetEmboss(colsub, UI_EMBOSS_NONE_OR_STATUS);
uiItemR(colsub, ptr, "lock_rotations_4d", UI_ITEM_R_TOGGLE, IFACE_("4L"), ICON_NONE);
if (RNA_boolean_get(ptr, "lock_rotations_4d")) {
uiItemR(colsub,
@@ -1496,7 +1496,7 @@ static void v3d_transform_butsR(uiLayout *layout, PointerRNA *ptr)
colsub = uiLayoutColumn(split, true);
uiItemR(colsub, ptr, "rotation_axis_angle", 0, IFACE_("Rotation"), ICON_NONE);
colsub = uiLayoutColumn(split, true);
- uiLayoutSetEmboss(colsub, UI_EMBOSS_NONE);
+ uiLayoutSetEmboss(colsub, UI_EMBOSS_NONE_OR_STATUS);
uiItemR(colsub, ptr, "lock_rotations_4d", UI_ITEM_R_TOGGLE, IFACE_("4L"), ICON_NONE);
if (RNA_boolean_get(ptr, "lock_rotations_4d")) {
uiItemR(colsub,
@@ -1520,7 +1520,7 @@ static void v3d_transform_butsR(uiLayout *layout, PointerRNA *ptr)
colsub = uiLayoutColumn(split, true);
uiItemR(colsub, ptr, "rotation_euler", 0, IFACE_("Rotation"), ICON_NONE);
colsub = uiLayoutColumn(split, true);
- uiLayoutSetEmboss(colsub, UI_EMBOSS_NONE);
+ uiLayoutSetEmboss(colsub, UI_EMBOSS_NONE_OR_STATUS);
uiItemL(colsub, "", ICON_NONE);
uiItemR(colsub,
ptr,
@@ -1536,7 +1536,7 @@ static void v3d_transform_butsR(uiLayout *layout, PointerRNA *ptr)
colsub = uiLayoutColumn(split, true);
uiItemR(colsub, ptr, "scale", 0, NULL, ICON_NONE);
colsub = uiLayoutColumn(split, true);
- uiLayoutSetEmboss(colsub, UI_EMBOSS_NONE);
+ uiLayoutSetEmboss(colsub, UI_EMBOSS_NONE_OR_STATUS);
uiItemL(colsub, "", ICON_NONE);
uiItemR(colsub,
ptr,
diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c
index 651ae8a3000..b055a0fe947 100644
--- a/source/blender/editors/space_view3d/view3d_edit.c
+++ b/source/blender/editors/space_view3d/view3d_edit.c
@@ -4917,10 +4917,7 @@ static int view3d_clipping_invoke(bContext *C, wmOperator *op, const wmEvent *ev
if (rv3d->rflag & RV3D_CLIPPING) {
rv3d->rflag &= ~RV3D_CLIPPING;
ED_region_tag_redraw(region);
- if (rv3d->clipbb) {
- MEM_freeN(rv3d->clipbb);
- }
- rv3d->clipbb = NULL;
+ MEM_SAFE_FREE(rv3d->clipbb);
return OPERATOR_FINISHED;
}
return WM_gesture_box_invoke(C, op, event);
diff --git a/source/blender/editors/space_view3d/view3d_project.c b/source/blender/editors/space_view3d/view3d_project.c
index d926ea84e0f..88efc530484 100644
--- a/source/blender/editors/space_view3d/view3d_project.c
+++ b/source/blender/editors/space_view3d/view3d_project.c
@@ -843,7 +843,7 @@ bool ED_view3d_unproject_v3(
const int viewport[4] = {0, 0, region->winx, region->winy};
const float region_co[3] = {regionx, regiony, regionz};
- return GPU_matrix_unproject_3fv(region_co, rv3d->viewmat, rv3d->winmat, viewport, world);
+ return GPU_matrix_unproject_3fv(region_co, rv3d->viewinv, rv3d->winmat, viewport, world);
}
/** \} */
diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c
index 96b84bd2a35..4069a72a8fc 100644
--- a/source/blender/editors/transform/transform.c
+++ b/source/blender/editors/transform/transform.c
@@ -78,6 +78,9 @@ static void initSnapSpatial(TransInfo *t, float r_snap[2]);
bool transdata_check_local_islands(TransInfo *t, short around)
{
+ if (t->options & (CTX_CURSOR | CTX_TEXTURE_SPACE)) {
+ return false;
+ }
return ((around == V3D_AROUND_LOCAL_ORIGINS) && (ELEM(t->obedit_type, OB_MESH, OB_GPENCIL)));
}
diff --git a/source/blender/editors/transform/transform.h b/source/blender/editors/transform/transform.h
index 1a61a594f37..1fa123e8507 100644
--- a/source/blender/editors/transform/transform.h
+++ b/source/blender/editors/transform/transform.h
@@ -582,7 +582,7 @@ typedef struct TransInfo {
short around;
/** space-type where transforming is. */
char spacetype;
- /** Avoid looking inside #TransDataContainer.obedit. */
+ /** Type of active object being edited. */
short obedit_type;
/** translation, to show for widget. */
diff --git a/source/blender/editors/transform/transform_convert.c b/source/blender/editors/transform/transform_convert.c
index e77fedfe143..3f730956dd0 100644
--- a/source/blender/editors/transform/transform_convert.c
+++ b/source/blender/editors/transform/transform_convert.c
@@ -1072,7 +1072,8 @@ static void init_proportional_edit(TransInfo *t)
else if (convert_type == TC_MESH_UV && t->flag & T_PROP_CONNECTED) {
/* Already calculated by uv_set_connectivity_distance. */
}
- else if (convert_type == TC_CURVE_VERTS && t->obedit_type == OB_CURVE) {
+ else if (convert_type == TC_CURVE_VERTS) {
+ BLI_assert(t->obedit_type == OB_CURVE);
set_prop_dist(t, false);
}
else {
@@ -1371,7 +1372,6 @@ void createTransData(bContext *C, TransInfo *t)
switch (t->data_type) {
case TC_ACTION_DATA:
- t->obedit_type = -1;
createTransActionData(C, t);
break;
case TC_POSE:
@@ -1394,7 +1394,6 @@ void createTransData(bContext *C, TransInfo *t)
createTransCurveVerts(t);
break;
case TC_GRAPH_EDIT_DATA:
- t->obedit_type = -1;
createTransGraphEditData(C, t);
break;
case TC_GPENCIL:
@@ -1404,9 +1403,6 @@ void createTransData(bContext *C, TransInfo *t)
createTransLatticeVerts(t);
break;
case TC_MASKING_DATA:
- if (t->spacetype == SPACE_CLIP) {
- t->obedit_type = -1;
- }
createTransMaskingData(C, t);
break;
case TC_MBALL_VERTS:
@@ -1425,11 +1421,9 @@ void createTransData(bContext *C, TransInfo *t)
createTransUVs(C, t);
break;
case TC_NLA_DATA:
- t->obedit_type = -1;
createTransNlaData(C, t);
break;
case TC_NODE_DATA:
- t->obedit_type = -1;
createTransNodeData(t);
break;
case TC_OBJECT:
@@ -1473,12 +1467,10 @@ void createTransData(bContext *C, TransInfo *t)
createTransSculpt(C, t);
break;
case TC_SEQ_DATA:
- t->obedit_type = -1;
t->num.flag |= NUM_NO_FRACTION; /* sequencer has no use for floating point transform. */
createTransSeqData(t);
break;
case TC_TRACKING_DATA:
- t->obedit_type = -1;
createTransTrackingData(C, t);
break;
case TC_NONE:
@@ -1492,8 +1484,6 @@ void createTransData(bContext *C, TransInfo *t)
countAndCleanTransDataContainer(t);
init_proportional_edit(t);
-
- BLI_assert((!(t->flag & T_EDIT)) == (!(t->obedit_type != -1)));
}
/** \} */
diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c
index e89ab6729d2..be8e551a1e8 100644
--- a/source/blender/editors/transform/transform_generics.c
+++ b/source/blender/editors/transform/transform_generics.c
@@ -152,8 +152,7 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
t->flag = 0;
- if (obact && !(t->options & (CTX_CURSOR | CTX_TEXTURE_SPACE)) &&
- ELEM(object_mode, OB_MODE_EDIT, OB_MODE_EDIT_GPENCIL)) {
+ if (obact && ELEM(object_mode, OB_MODE_EDIT, OB_MODE_EDIT_GPENCIL)) {
t->obedit_type = obact->type;
}
else {
diff --git a/source/blender/editors/transform/transform_mode.c b/source/blender/editors/transform/transform_mode.c
index 65a673940f8..362ee179e7d 100644
--- a/source/blender/editors/transform/transform_mode.c
+++ b/source/blender/editors/transform/transform_mode.c
@@ -968,9 +968,9 @@ void ElementResize(const TransInfo *t,
float obsizemat[3][3];
/* Reorient the size mat to fit the oriented object. */
mul_m3_m3m3(obsizemat, tmat, td->axismtx);
- /* print_m3("obsizemat", obsizemat); */
+ // print_m3("obsizemat", obsizemat);
TransMat3ToSize(obsizemat, td->axismtx, fsize);
- /* print_v3("fsize", fsize); */
+ // print_v3("fsize", fsize);
}
else {
mat3_to_size(fsize, tmat);
diff --git a/source/blender/editors/transform/transform_mode_edge_slide.c b/source/blender/editors/transform/transform_mode_edge_slide.c
index 066a2853dc7..cfcb17b8da0 100644
--- a/source/blender/editors/transform/transform_mode_edge_slide.c
+++ b/source/blender/editors/transform/transform_mode_edge_slide.c
@@ -852,7 +852,7 @@ static EdgeSlideData *createEdgeSlideVerts_double_side(TransInfo *t, TransDataCo
#undef EDGESLIDE_VERT_IS_INNER
}
- /* EDBM_flag_disable_all(em, BM_ELEM_SELECT); */
+ // EDBM_flag_disable_all(em, BM_ELEM_SELECT);
BLI_assert(STACK_SIZE(sv_array) == (uint)sv_tot);
@@ -1037,7 +1037,7 @@ static EdgeSlideData *createEdgeSlideVerts_single_side(TransInfo *t, TransDataCo
}
}
- /* EDBM_flag_disable_all(em, BM_ELEM_SELECT); */
+ // EDBM_flag_disable_all(em, BM_ELEM_SELECT);
sld->sv = sv_array;
sld->totsv = sv_tot;
diff --git a/source/blender/editors/transform/transform_snap.c b/source/blender/editors/transform/transform_snap.c
index 2619fdf3403..656a1e5d9c7 100644
--- a/source/blender/editors/transform/transform_snap.c
+++ b/source/blender/editors/transform/transform_snap.c
@@ -575,7 +575,7 @@ static void initSnappingMode(TransInfo *t)
{
ToolSettings *ts = t->settings;
/* All obedit types will match. */
- const int obedit_type = t->data_container->obedit ? t->data_container->obedit->type : -1;
+ const int obedit_type = t->obedit_type;
ViewLayer *view_layer = t->view_layer;
Base *base_act = view_layer->basact;
@@ -609,15 +609,22 @@ static void initSnappingMode(TransInfo *t)
}
}
- if ((t->spacetype == SPACE_VIEW3D || t->spacetype == SPACE_IMAGE) &&
- (t->options & CTX_CAMERA) == 0) {
+ if (ELEM(t->spacetype, SPACE_VIEW3D, SPACE_IMAGE) && !(t->options & CTX_CAMERA)) {
/* Only 3D view or UV. */
/* Not with camera selected in camera view. */
setSnappingCallback(t);
- if ((obedit_type != -1) &&
- ELEM(obedit_type, OB_MESH, OB_ARMATURE, OB_CURVE, OB_LATTICE, OB_MBALL)) {
+ if (t->options & (CTX_GPENCIL_STROKES | CTX_CURSOR | CTX_OBMODE_XFORM_OBDATA)) {
+ /* In "Edit Strokes" mode,
+ * snap tool can perform snap to selected or active objects (see T49632)
+ * TODO: perform self snap in gpencil_strokes.
+ *
+ * When we're moving the origins, allow snapping onto our own geometry (see T69132). */
+ t->tsnap.modeSelect = SNAP_ALL;
+ }
+ else if ((obedit_type != -1) &&
+ ELEM(obedit_type, OB_MESH, OB_ARMATURE, OB_CURVE, OB_LATTICE, OB_MBALL)) {
/* Edit mode */
/* Temporary limited to edit mode meshes, armature, curves, metaballs. */
@@ -636,17 +643,7 @@ static void initSnappingMode(TransInfo *t)
}
else if (obedit_type == -1) {
/* Object mode */
- if (t->options & (CTX_GPENCIL_STROKES | CTX_CURSOR | CTX_OBMODE_XFORM_OBDATA)) {
- /* In "Edit Strokes" mode,
- * snap tool can perform snap to selected or active objects (see T49632)
- * TODO: perform self snap in gpencil_strokes.
- *
- * When we're moving the origins, allow snapping onto our own geometry (see T69132). */
- t->tsnap.modeSelect = SNAP_ALL;
- }
- else {
- t->tsnap.modeSelect = SNAP_NOT_SELECTED;
- }
+ t->tsnap.modeSelect = SNAP_NOT_SELECTED;
}
else {
/* Increment if snap is not possible */
diff --git a/source/blender/editors/uvedit/uvedit_parametrizer.c b/source/blender/editors/uvedit/uvedit_parametrizer.c
index f97403a0919..b4bdeace716 100644
--- a/source/blender/editors/uvedit/uvedit_parametrizer.c
+++ b/source/blender/editors/uvedit/uvedit_parametrizer.c
@@ -3399,10 +3399,7 @@ static void p_chart_lscm_end(PChart *chart)
EIG_linear_solver_delete(chart->u.lscm.context);
}
- if (chart->u.lscm.abf_alpha) {
- MEM_freeN(chart->u.lscm.abf_alpha);
- chart->u.lscm.abf_alpha = NULL;
- }
+ MEM_SAFE_FREE(chart->u.lscm.abf_alpha);
chart->u.lscm.context = NULL;
chart->u.lscm.pin1 = NULL;
diff --git a/source/blender/editors/uvedit/uvedit_smart_stitch.c b/source/blender/editors/uvedit/uvedit_smart_stitch.c
index 1bcd1fad9d6..c5485cc1495 100644
--- a/source/blender/editors/uvedit/uvedit_smart_stitch.c
+++ b/source/blender/editors/uvedit/uvedit_smart_stitch.c
@@ -265,26 +265,11 @@ static StitchPreviewer *stitch_preview_init(void)
static void stitch_preview_delete(StitchPreviewer *stitch_preview)
{
if (stitch_preview) {
- if (stitch_preview->preview_polys) {
- MEM_freeN(stitch_preview->preview_polys);
- stitch_preview->preview_polys = NULL;
- }
- if (stitch_preview->uvs_per_polygon) {
- MEM_freeN(stitch_preview->uvs_per_polygon);
- stitch_preview->uvs_per_polygon = NULL;
- }
- if (stitch_preview->preview_stitchable) {
- MEM_freeN(stitch_preview->preview_stitchable);
- stitch_preview->preview_stitchable = NULL;
- }
- if (stitch_preview->preview_unstitchable) {
- MEM_freeN(stitch_preview->preview_unstitchable);
- stitch_preview->preview_unstitchable = NULL;
- }
- if (stitch_preview->static_tris) {
- MEM_freeN(stitch_preview->static_tris);
- stitch_preview->static_tris = NULL;
- }
+ MEM_SAFE_FREE(stitch_preview->preview_polys);
+ MEM_SAFE_FREE(stitch_preview->uvs_per_polygon);
+ MEM_SAFE_FREE(stitch_preview->preview_stitchable);
+ MEM_SAFE_FREE(stitch_preview->preview_unstitchable);
+ MEM_SAFE_FREE(stitch_preview->static_tris);
MEM_freeN(stitch_preview);
}
}
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpenciltint.c b/source/blender/gpencil_modifiers/intern/MOD_gpenciltint.c
index 680f5ab05ec..7ce731c0dd6 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpenciltint.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpenciltint.c
@@ -308,10 +308,7 @@ static void bakeModifier(Main *UNUSED(bmain),
static void freeData(GpencilModifierData *md)
{
TintGpencilModifierData *mmd = (TintGpencilModifierData *)md;
- if (mmd->colorband) {
- MEM_freeN(mmd->colorband);
- mmd->colorband = NULL;
- }
+ MEM_SAFE_FREE(mmd->colorband);
if (mmd->curve_intensity) {
BKE_curvemapping_free(mmd->curve_intensity);
}
diff --git a/source/blender/gpu/GPU_matrix.h b/source/blender/gpu/GPU_matrix.h
index e073263f352..edf16f04349 100644
--- a/source/blender/gpu/GPU_matrix.h
+++ b/source/blender/gpu/GPU_matrix.h
@@ -131,15 +131,11 @@ void GPU_matrix_project_2fv(const float world[3],
float r_win[2]);
bool GPU_matrix_unproject_3fv(const float win[3],
- const float model[4][4],
+ const float model_inverted[4][4],
const float proj[4][4],
const int view[4],
float r_world[3]);
-void GPU_matrix_unproject_3fv_with_precalc(const struct GPUMatrixUnproject_Precalc *unproj_precalc,
- const float win[3],
- float r_world[3]);
-
/* 2D Projection Matrix */
void GPU_matrix_ortho_2d_set(float left, float right, float bottom, float top);
diff --git a/source/blender/gpu/GPU_texture.h b/source/blender/gpu/GPU_texture.h
index f980c8fdcd7..ee4d08d4059 100644
--- a/source/blender/gpu/GPU_texture.h
+++ b/source/blender/gpu/GPU_texture.h
@@ -187,25 +187,25 @@ unsigned int GPU_texture_memory_usage_get(void);
* \a mips is the number of mip level to allocate. It must be >= 1.
*/
GPUTexture *GPU_texture_create_1d(
- const char *name, int w, int mips, eGPUTextureFormat format, const float *data);
+ const char *name, int w, int mip_len, eGPUTextureFormat format, const float *data);
GPUTexture *GPU_texture_create_1d_array(
- const char *name, int w, int h, int mips, eGPUTextureFormat format, const float *data);
+ const char *name, int w, int h, int mip_len, eGPUTextureFormat format, const float *data);
GPUTexture *GPU_texture_create_2d(
- const char *name, int w, int h, int mips, eGPUTextureFormat format, const float *data);
+ const char *name, int w, int h, int mip_len, eGPUTextureFormat format, const float *data);
GPUTexture *GPU_texture_create_2d_array(
- const char *name, int w, int h, int d, int mips, eGPUTextureFormat format, const float *data);
+ const char *name, int w, int h, int d, int mip_len, eGPUTextureFormat format, const float *data);
GPUTexture *GPU_texture_create_3d(const char *name,
int w,
int h,
int d,
- int mips,
+ int mip_len,
eGPUTextureFormat texture_format,
eGPUDataFormat data_format,
const void *data);
GPUTexture *GPU_texture_create_cube(
- const char *name, int w, int mips, eGPUTextureFormat format, const float *data);
+ const char *name, int w, int mip_len, eGPUTextureFormat format, const float *data);
GPUTexture *GPU_texture_create_cube_array(
- const char *name, int w, int d, int mips, eGPUTextureFormat format, const float *data);
+ const char *name, int w, int d, int mip_len, eGPUTextureFormat format, const float *data);
/* Special textures. */
GPUTexture *GPU_texture_create_from_vertbuf(const char *name, struct GPUVertBuf *vert);
diff --git a/source/blender/gpu/intern/gpu_material.c b/source/blender/gpu/intern/gpu_material.c
index 37089785e0e..56e72fbeca9 100644
--- a/source/blender/gpu/intern/gpu_material.c
+++ b/source/blender/gpu/intern/gpu_material.c
@@ -758,6 +758,7 @@ GPUMaterial *GPU_material_from_nodetree(Scene *scene,
/* Only free after GPU_pass_shader_get where GPUUniformBuf
* read data from the local tree. */
ntreeFreeLocalTree(localtree);
+ BLI_assert(!localtree->id.py_instance); /* Or call #BKE_libblock_free_data_py. */
MEM_freeN(localtree);
/* note that even if building the shader fails in some way, we still keep
diff --git a/source/blender/gpu/intern/gpu_matrix.cc b/source/blender/gpu/intern/gpu_matrix.cc
index efa04568401..bbcc241f5e3 100644
--- a/source/blender/gpu/intern/gpu_matrix.cc
+++ b/source/blender/gpu/intern/gpu_matrix.cc
@@ -513,93 +513,55 @@ void GPU_matrix_project_2fv(const float world[3],
win[1] = view[1] + (view[3] * (v[1] + 1)) * 0.5f;
}
-/**
- * The same result could be obtained as follows:
- *
- * \code{.c}
- * float projinv[4][4];
- * invert_m4_m4(projinv, projmat);
- * co[0] = 2 * co[0] - 1;
- * co[1] = 2 * co[1] - 1;
- * co[2] = 2 * co[2] - 1;
- * mul_project_m4_v3(projinv, co);
- * \endcode
- *
- * But that solution loses much precision.
- * Therefore, get the same result without inverting the matrix.
- */
-static void gpu_mul_invert_projmat_m4_unmapped_v3_with_precalc(
- const struct GPUMatrixUnproject_Precalc *precalc, float co[3])
-{
- /* 'precalc->dims' is the result of 'projmat_dimensions(proj, ...)'. */
- co[0] = (float)scalenormd(precalc->dims.xmin, precalc->dims.xmax, co[0]);
- co[1] = (float)scalenormd(precalc->dims.ymin, precalc->dims.ymax, co[1]);
-
- if (precalc->is_persp) {
- co[2] = (precalc->dims.zmax * precalc->dims.zmin) /
- (precalc->dims.zmax + co[2] * (precalc->dims.zmin - precalc->dims.zmax));
- co[0] *= co[2] / precalc->dims.zmin;
- co[1] *= co[2] / precalc->dims.zmin;
- }
- else {
- co[2] = (float)scalenormd(precalc->dims.zmin, precalc->dims.zmax, co[2]);
- }
- co[2] *= -1;
-}
-
-bool GPU_matrix_unproject_precalc(struct GPUMatrixUnproject_Precalc *precalc,
- const float model[4][4],
- const float proj[4][4],
- const int view[4])
-{
- precalc->is_persp = proj[3][3] == 0.0f;
- projmat_dimensions_db(proj,
- &precalc->dims.xmin,
- &precalc->dims.xmax,
- &precalc->dims.ymin,
- &precalc->dims.ymax,
- &precalc->dims.zmin,
- &precalc->dims.zmax);
- if (isinf(precalc->dims.zmax)) {
- /* We cannot retrieve the actual value of the clip_end.
- * Use `FLT_MAX` to avoid NAN's. */
- precalc->dims.zmax = FLT_MAX;
- }
- for (int i = 0; i < 4; i++) {
- precalc->view[i] = (float)view[i];
- }
- if (!invert_m4_m4(precalc->model_inverted, model)) {
- unit_m4(precalc->model_inverted);
- return false;
- }
- return true;
-}
-
-void GPU_matrix_unproject_3fv_with_precalc(const struct GPUMatrixUnproject_Precalc *precalc,
- const float win[3],
- float r_world[3])
-{
- float in[3] = {
- (win[0] - precalc->view[0]) / precalc->view[2],
- (win[1] - precalc->view[1]) / precalc->view[3],
- win[2],
- };
- gpu_mul_invert_projmat_m4_unmapped_v3_with_precalc(precalc, in);
- mul_v3_m4v3(r_world, precalc->model_inverted, in);
-}
-
bool GPU_matrix_unproject_3fv(const float win[3],
- const float model[4][4],
+ const float model_inverted[4][4],
const float proj[4][4],
const int view[4],
float r_world[3])
{
- struct GPUMatrixUnproject_Precalc precalc;
- if (!GPU_matrix_unproject_precalc(&precalc, model, proj, view)) {
- zero_v3(r_world);
+ zero_v3(r_world);
+ float in[3] = {
+ 2 * ((win[0] - view[0]) / view[2]) - 1.0f,
+ 2 * ((win[1] - view[1]) / view[3]) - 1.0f,
+ 2 * win[2] - 1.0f,
+ };
+
+ /**
+ * The same result could be obtained as follows:
+ *
+ * \code{.c}
+ * float projinv[4][4];
+ * invert_m4_m4(projinv, projview);
+ * copy_v3_v3(r_world, in);
+ * mul_project_m4_v3(projinv, r_world);
+ * \endcode
+ *
+ * But that solution loses much precision.
+ * Therefore, get the same result without inverting the project view matrix.
+ */
+
+ float out[3];
+ const bool is_persp = proj[3][3] == 0.0f;
+ if (is_persp) {
+ out[2] = proj[3][2] / (proj[2][2] + in[2]);
+ if (isinf(out[2])) {
+ out[2] = FLT_MAX;
+ }
+ out[0] = out[2] * ((proj[2][0] + in[0]) / proj[0][0]);
+ out[1] = out[2] * ((proj[2][1] + in[1]) / proj[1][1]);
+ out[2] *= -1;
+ }
+ else {
+ out[0] = (-proj[3][0] + in[0]) / proj[0][0];
+ out[1] = (-proj[3][1] + in[1]) / proj[1][1];
+ out[2] = (-proj[3][2] + in[2]) / proj[2][2];
+ }
+
+ if (!is_finite_v3(out)) {
return false;
}
- GPU_matrix_unproject_3fv_with_precalc(&precalc, win, r_world);
+
+ mul_v3_m4v3(r_world, model_inverted, out);
return true;
}
diff --git a/source/blender/gpu/tests/gpu_shader_test.cc b/source/blender/gpu/tests/gpu_shader_test.cc
index 43ff86ebbd8..dbe336af097 100644
--- a/source/blender/gpu/tests/gpu_shader_test.cc
+++ b/source/blender/gpu/tests/gpu_shader_test.cc
@@ -108,7 +108,8 @@ void main() {
EXPECT_NE(shader, nullptr);
/* Construct Texture. */
- GPUTexture *texture = GPU_texture_create_1d("gpu_shader_compute_1d", SIZE, 0, GPU_RGBA32F, NULL);
+ GPUTexture *texture = GPU_texture_create_1d(
+ "gpu_shader_compute_1d", SIZE, 0, GPU_RGBA32F, nullptr);
EXPECT_NE(texture, nullptr);
GPU_shader_bind(shader);
diff --git a/source/blender/imbuf/intern/colormanagement.c b/source/blender/imbuf/intern/colormanagement.c
index 2cc44ebc67b..8b2ac2ed22d 100644
--- a/source/blender/imbuf/intern/colormanagement.c
+++ b/source/blender/imbuf/intern/colormanagement.c
@@ -759,11 +759,7 @@ static bool colormanage_use_look(const char *look, const char *view_name)
void colormanage_cache_free(ImBuf *ibuf)
{
- if (ibuf->display_buffer_flags) {
- MEM_freeN(ibuf->display_buffer_flags);
-
- ibuf->display_buffer_flags = NULL;
- }
+ MEM_SAFE_FREE(ibuf->display_buffer_flags);
if (ibuf->colormanage_cache) {
ColormanageCacheData *cache_data = colormanage_cachedata_get(ibuf);
diff --git a/source/blender/imbuf/intern/moviecache.c b/source/blender/imbuf/intern/moviecache.c
index e395222a214..6cc1932eff6 100644
--- a/source/blender/imbuf/intern/moviecache.c
+++ b/source/blender/imbuf/intern/moviecache.c
@@ -179,10 +179,7 @@ static void IMB_moviecache_destructor(void *p)
item->c_handle = NULL;
/* force cached segments to be updated */
- if (cache->points) {
- MEM_freeN(cache->points);
- cache->points = NULL;
- }
+ MEM_SAFE_FREE(cache->points);
}
}
@@ -355,10 +352,7 @@ static void do_moviecache_put(MovieCache *cache, void *userkey, ImBuf *ibuf, boo
/* cache limiter can't remove unused keys which points to destroyed values */
check_unused_keys(cache);
- if (cache->points) {
- MEM_freeN(cache->points);
- cache->points = NULL;
- }
+ MEM_SAFE_FREE(cache->points);
}
void IMB_moviecache_put(MovieCache *cache, void *userkey, ImBuf *ibuf)
@@ -488,11 +482,7 @@ void IMB_moviecache_get_cache_segments(
}
if (cache->proxy != proxy || cache->render_flags != render_flags) {
- if (cache->points) {
- MEM_freeN(cache->points);
- }
-
- cache->points = NULL;
+ MEM_SAFE_FREE(cache->points);
}
if (cache->points) {
diff --git a/source/blender/imbuf/intern/openexr/openexr_api.cpp b/source/blender/imbuf/intern/openexr/openexr_api.cpp
index a465c6b92bc..cd323e72003 100644
--- a/source/blender/imbuf/intern/openexr/openexr_api.cpp
+++ b/source/blender/imbuf/intern/openexr/openexr_api.cpp
@@ -1711,7 +1711,7 @@ static const char *exr_rgba_channelname(MultiPartInputFile &file, const char *ch
const ChannelList &channels = file.header(0).channels();
for (ChannelList::ConstIterator i = channels.begin(); i != channels.end(); ++i) {
- /* const Channel &channel = i.channel(); */ /* Not used yet */
+ // const Channel &channel = i.channel(); /* Not used yet. */
const char *str = i.name();
int len = strlen(str);
if (len) {
diff --git a/source/blender/io/alembic/intern/abc_reader_nurbs.cc b/source/blender/io/alembic/intern/abc_reader_nurbs.cc
index 2a5f4ecb787..25567aa8c24 100644
--- a/source/blender/io/alembic/intern/abc_reader_nurbs.cc
+++ b/source/blender/io/alembic/intern/abc_reader_nurbs.cc
@@ -90,7 +90,7 @@ static bool set_knots(const FloatArraySamplePtr &knots, float *&nu_knots)
void AbcNurbsReader::readObjectData(Main *bmain, const Alembic::Abc::ISampleSelector &sample_sel)
{
- Curve *cu = static_cast<Curve *>(BKE_curve_add(bmain, "abc_curve", OB_SURF));
+ Curve *cu = static_cast<Curve *>(BKE_curve_add(bmain, m_data_name.c_str(), OB_SURF));
cu->actvert = CU_ACT_NONE;
std::vector<std::pair<INuPatchSchema, IObject>>::iterator it;
@@ -180,8 +180,6 @@ void AbcNurbsReader::readObjectData(Main *bmain, const Alembic::Abc::ISampleSele
BLI_addtail(BKE_curve_nurbs_get(cu), nu);
}
- BLI_strncpy(cu->id.name + 2, m_data_name.c_str(), m_data_name.size() + 1);
-
m_object = BKE_object_add_only_object(bmain, OB_SURF, m_object_name.c_str());
m_object->data = cu;
}
diff --git a/source/blender/io/alembic/intern/abc_reader_object.cc b/source/blender/io/alembic/intern/abc_reader_object.cc
index 00b73d29c5c..d136d8c3e91 100644
--- a/source/blender/io/alembic/intern/abc_reader_object.cc
+++ b/source/blender/io/alembic/intern/abc_reader_object.cc
@@ -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
diff --git a/source/blender/io/collada/AnimationImporter.cpp b/source/blender/io/collada/AnimationImporter.cpp
index e52bdca0d87..e54192abc54 100644
--- a/source/blender/io/collada/AnimationImporter.cpp
+++ b/source/blender/io/collada/AnimationImporter.cpp
@@ -1363,7 +1363,7 @@ void AnimationImporter::add_bone_animation_sampled(Object *ob,
calc_joint_parent_mat_rest(par, nullptr, root, node);
mul_m4_m4m4(temp, par, matfra);
- /* evaluate_joint_world_transform_at_frame(temp, NULL, node, fra); */
+ // evaluate_joint_world_transform_at_frame(temp, NULL, node, fra);
/* calc special matrix */
mul_m4_series(mat, irest, temp, irest_dae, rest);
diff --git a/source/blender/io/gpencil/CMakeLists.txt b/source/blender/io/gpencil/CMakeLists.txt
index fec95be6aa8..4af8b506bd5 100644
--- a/source/blender/io/gpencil/CMakeLists.txt
+++ b/source/blender/io/gpencil/CMakeLists.txt
@@ -33,6 +33,7 @@ set(INC
../../../../intern/clog
../../../../intern/guardedalloc
../../../../intern/utfconv
+ ../../../../extern/nanosvg
)
set(INC_SYS
@@ -44,9 +45,6 @@ set(SRC
intern/gpencil_io_import_base.cc
intern/gpencil_io_import_svg.cc
- # This line must be removed if NanoSVG is moved to extern
- nanosvg/nanosvg.h
-
gpencil_io.h
intern/gpencil_io_base.hh
intern/gpencil_io_export_base.hh
diff --git a/source/blender/io/gpencil/intern/gpencil_io_import_svg.cc b/source/blender/io/gpencil/intern/gpencil_io_import_svg.cc
index db6bbc7768e..941d1137f4d 100644
--- a/source/blender/io/gpencil/intern/gpencil_io_import_svg.cc
+++ b/source/blender/io/gpencil/intern/gpencil_io_import_svg.cc
@@ -42,7 +42,7 @@
#define NANOSVG_ALL_COLOR_KEYWORDS
#define NANOSVG_IMPLEMENTATION
-#include "nanosvg/nanosvg.h"
+#include "nanosvg.h"
using blender::MutableSpan;
diff --git a/source/blender/io/usd/intern/usd_capi_export.cc b/source/blender/io/usd/intern/usd_capi_export.cc
index 25f12e683cf..efa31df25c1 100644
--- a/source/blender/io/usd/intern/usd_capi_export.cc
+++ b/source/blender/io/usd/intern/usd_capi_export.cc
@@ -102,7 +102,7 @@ static void export_startjob(void *customdata,
usd_stage->SetMetadata(pxr::UsdGeomTokens->upAxis, pxr::VtValue(pxr::UsdGeomTokens->z));
usd_stage->SetMetadata(pxr::UsdGeomTokens->metersPerUnit,
- pxr::VtValue(scene->unit.scale_length));
+ static_cast<double>(scene->unit.scale_length));
usd_stage->GetRootLayer()->SetDocumentation(std::string("Blender v") +
BKE_blender_version_string());
diff --git a/source/blender/makesdna/DNA_ID.h b/source/blender/makesdna/DNA_ID.h
index f7f4b0e6104..10a5a0f1c47 100644
--- a/source/blender/makesdna/DNA_ID.h
+++ b/source/blender/makesdna/DNA_ID.h
@@ -551,7 +551,7 @@ enum {
/* tag data-block as having actually increased user-count for the extra virtual user. */
LIB_TAG_EXTRAUSER_SET = 1 << 7,
- /* RESET_AFTER_USE tag newly duplicated/copied IDs.
+ /* RESET_AFTER_USE tag newly duplicated/copied IDs (see #ID_NEW_SET macro above).
* Also used internally in readfile.c to mark data-blocks needing do_versions. */
LIB_TAG_NEW = 1 << 8,
/* RESET_BEFORE_USE free test flag.
@@ -563,13 +563,32 @@ enum {
/**
* The data-block is a copy-on-write/localized version.
*
+ * RESET_NEVER
+ *
* \warning This should not be cleared on existing data.
* If support for this is needed, see T88026 as this flag controls memory ownership
* of physics *shared* pointers.
*/
LIB_TAG_COPIED_ON_WRITE = 1 << 12,
-
+ /**
+ * The data-block is not the original COW ID created by the depsgraph, but has be re-allocated
+ * during the evaluation process of another ID.
+ *
+ * RESET_NEVER
+ *
+ * Typical example is object data, when evaluating the object's modifier stack the final obdata
+ * can be different than the COW initial obdata ID.
+ */
LIB_TAG_COPIED_ON_WRITE_EVAL_RESULT = 1 << 13,
+
+ /**
+ * The data-block is fully outside of any ID management area, and should be considered as a
+ * purely independent data.
+ *
+ * RESET_NEVER
+ *
+ * NOTE: Only used by node-groups currently.
+ */
LIB_TAG_LOCALIZED = 1 << 14,
/* RESET_NEVER tag data-block for freeing etc. behavior
diff --git a/source/blender/makesdna/DNA_asset_types.h b/source/blender/makesdna/DNA_asset_types.h
index ca16e6728dd..2975915eccd 100644
--- a/source/blender/makesdna/DNA_asset_types.h
+++ b/source/blender/makesdna/DNA_asset_types.h
@@ -81,7 +81,7 @@ typedef enum eAssetLibraryType {
// 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
+ * (#bUserAssetLibrary). The name will be taken from #FileSelectParams.asset_library_ref.idname
* then.
* In RNA, we add the index of the custom library to this to identify it by index. So keep
* this last! */
diff --git a/source/blender/makesdna/DNA_gpencil_types.h b/source/blender/makesdna/DNA_gpencil_types.h
index 380d8ad1249..68bd2961f23 100644
--- a/source/blender/makesdna/DNA_gpencil_types.h
+++ b/source/blender/makesdna/DNA_gpencil_types.h
@@ -324,6 +324,7 @@ typedef struct bGPDstroke {
struct bGPDcurve *editcurve;
bGPDstroke_Runtime runtime;
+ void *_pad5;
} bGPDstroke;
/** #bGPDstroke.flag */
diff --git a/source/blender/makesdna/DNA_mesh_types.h b/source/blender/makesdna/DNA_mesh_types.h
index 932f4715298..97f14b2195d 100644
--- a/source/blender/makesdna/DNA_mesh_types.h
+++ b/source/blender/makesdna/DNA_mesh_types.h
@@ -231,6 +231,7 @@ typedef struct Mesh {
* default and Face Sets can be used without affecting the color of the mesh. */
int face_sets_color_default;
+ void *_pad2;
Mesh_Runtime runtime;
} Mesh;
diff --git a/source/blender/makesdna/DNA_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h
index f66de378c35..1bebbc35747 100644
--- a/source/blender/makesdna/DNA_modifier_types.h
+++ b/source/blender/makesdna/DNA_modifier_types.h
@@ -136,6 +136,7 @@ typedef struct ModifierData {
/* Runtime field which contains runtime data which is specific to a modifier type. */
void *runtime;
+ void *_pad1;
} ModifierData;
typedef enum {
@@ -215,6 +216,7 @@ typedef struct LatticeModifierData {
float strength;
short flag;
char _pad[2];
+ void *_pad1;
} LatticeModifierData;
/* Lattice modifier flags. */
@@ -232,6 +234,7 @@ typedef struct CurveModifierData {
short defaxis;
short flag;
char _pad[4];
+ void *_pad1;
} CurveModifierData;
/* Curve modifier flags */
@@ -283,6 +286,7 @@ typedef struct MaskModifierData {
/** Flags for various things. */
short flag;
float threshold;
+ void *_pad1;
} MaskModifierData;
/* Mask Modifier -> mode */
@@ -373,6 +377,7 @@ typedef struct MirrorModifierData {
float uv_offset[2];
float uv_offset_copy[2];
struct Object *mirror_ob;
+ void *_pad1;
} MirrorModifierData;
/* MirrorModifierData->flag */
@@ -451,6 +456,7 @@ typedef struct BevelModifierData {
/** Curve info for the custom profile */
struct CurveProfile *custom_profile;
+ void *_pad2;
} BevelModifierData;
/* BevelModifierData->flags and BevelModifierData->lim_flags */
@@ -535,6 +541,7 @@ typedef struct FluidModifierData {
float time;
/** Domain, inflow, outflow, .... */
int type;
+ void *_pad1;
} FluidModifierData;
/* Fluid modifier flags */
@@ -680,6 +687,7 @@ typedef struct CastModifierData {
/** MAX_VGROUP_NAME. */
char defgrp_name[64];
short flag, type;
+ void *_pad1;
} CastModifierData;
/* Cast modifier flags */
@@ -725,6 +733,7 @@ typedef struct WaveModifierData {
float timeoffs, lifetime;
char _pad1[4];
+ void *_pad2;
} WaveModifierData;
/* WaveModifierData.flag */
@@ -797,6 +806,7 @@ typedef struct HookModifierData {
float force;
/** Optional vertexgroup name, MAX_VGROUP_NAME. */
char name[64];
+ void *_pad1;
} HookModifierData;
typedef struct SoftbodyModifierData {
@@ -1001,6 +1011,7 @@ typedef struct ParticleSystemModifierData {
int totdmvert, totdmedge, totdmface;
short flag;
char _pad[2];
+ void *_pad1;
} ParticleSystemModifierData;
typedef enum {
@@ -1037,6 +1048,7 @@ typedef struct ParticleInstanceModifierData {
char index_layer_name[64];
/** MAX_CUSTOMDATA_LAYER_NAME. */
char value_layer_name[64];
+ void *_pad1;
} ParticleInstanceModifierData;
typedef enum {
@@ -1057,6 +1069,7 @@ typedef struct ExplodeModifierData {
float protect;
/** MAX_CUSTOMDATA_LAYER_NAME. */
char uvname[64];
+ void *_pad1;
} ExplodeModifierData;
typedef struct MultiresModifierData {
@@ -1086,6 +1099,7 @@ typedef struct FluidsimModifierData {
/** Definition is in DNA_object_fluidsim_types.h. */
struct FluidsimSettings *fss;
+ void *_pad1;
} FluidsimModifierData;
/* DEPRECATED, only used for versioning. */
@@ -1202,6 +1216,7 @@ typedef struct SimpleDeformModifierData {
char deform_axis;
char flag;
+ void *_pad1;
} SimpleDeformModifierData;
/* SimpleDeform->flag */
@@ -1310,6 +1325,7 @@ typedef struct ScrewModifierData {
short flag;
char axis;
char _pad[5];
+ void *_pad1;
} ScrewModifierData;
enum {
@@ -1434,6 +1450,7 @@ typedef struct WarpModifierData {
char flag;
char falloff_type;
char _pad[6];
+ void *_pad1;
} WarpModifierData;
/* WarpModifierData->flag */
@@ -1497,6 +1514,7 @@ typedef struct WeightVGEditModifierData {
/* Padding... */
char _pad0[4];
+ void *_pad1;
} WeightVGEditModifierData;
/* WeightVGEdit flags. */
@@ -2064,6 +2082,7 @@ typedef struct DataTransferModifierData {
char defgrp_name[64];
int flags;
+ void *_pad2;
} DataTransferModifierData;
/* DataTransferModifierData.flags */
@@ -2094,6 +2113,7 @@ typedef struct NormalEditModifierData {
float mix_limit;
float offset[3];
char _pad0[4];
+ void *_pad1;
} NormalEditModifierData;
/* NormalEditModifierData.mode */
@@ -2154,6 +2174,7 @@ typedef struct MeshSeqCacheModifierData {
float last_lookup_time;
int _pad1;
+ void *_pad2;
} MeshSeqCacheModifierData;
/* MeshSeqCacheModifierData.read_flag */
@@ -2198,6 +2219,7 @@ typedef struct SurfaceDeformModifierData {
float mat[4][4];
float strength;
char defgrp_name[64];
+ void *_pad1;
} SurfaceDeformModifierData;
/* Surface Deform modifier flags */
@@ -2259,6 +2281,7 @@ typedef struct NodesModifierData {
/* Contains logged information from the last evaluation. This can be used to help the user to
* debug a node tree. */
void *runtime_eval_log;
+ void *_pad1;
} NodesModifierData;
typedef struct MeshToVolumeModifierData {
@@ -2286,6 +2309,7 @@ typedef struct MeshToVolumeModifierData {
float density;
char _pad2[4];
+ void *_pad3;
} MeshToVolumeModifierData;
/* MeshToVolumeModifierData->resolution_mode */
@@ -2332,6 +2356,7 @@ typedef struct VolumeToMeshModifierData {
/** MAX_NAME */
char grid_name[64];
+ void *_pad1;
} VolumeToMeshModifierData;
/** VolumeToMeshModifierData->resolution_mode */
diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h
index 4b08aeb2008..ad7722d3ed0 100644
--- a/source/blender/makesdna/DNA_node_types.h
+++ b/source/blender/makesdna/DNA_node_types.h
@@ -1367,6 +1367,13 @@ typedef struct NodeGeometryCurveSetHandles {
uint8_t mode;
} NodeGeometryCurveSetHandles;
+typedef struct NodeGeometryCurveSelectHandles {
+ /* GeometryNodeCurveHandleType. */
+ uint8_t handle_type;
+ /* GeometryNodeCurveHandleMode. */
+ uint8_t mode;
+} NodeGeometryCurveSelectHandles;
+
typedef struct NodeGeometryCurvePrimitiveLine {
/* GeometryNodeCurvePrimitiveLineMode. */
uint8_t mode;
diff --git a/source/blender/makesdna/DNA_object_types.h b/source/blender/makesdna/DNA_object_types.h
index e7091c78f71..c6d6334118f 100644
--- a/source/blender/makesdna/DNA_object_types.h
+++ b/source/blender/makesdna/DNA_object_types.h
@@ -433,6 +433,7 @@ typedef struct Object {
ObjectLineArt lineart;
/** Runtime evaluation data (keep last). */
+ void *_pad9;
Object_Runtime runtime;
} Object;
diff --git a/source/blender/makesdna/DNA_sequence_types.h b/source/blender/makesdna/DNA_sequence_types.h
index af524ff4866..df18501d2ea 100644
--- a/source/blender/makesdna/DNA_sequence_types.h
+++ b/source/blender/makesdna/DNA_sequence_types.h
@@ -296,6 +296,7 @@ typedef struct Editing {
int64_t disk_cache_timestamp;
EditingRuntime runtime;
+ void *_pad1;
} Editing;
/* ************* Effect Variable Structs ********* */
diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h
index 27d5d83c7cb..863c53615c1 100644
--- a/source/blender/makesdna/DNA_space_types.h
+++ b/source/blender/makesdna/DNA_space_types.h
@@ -763,7 +763,7 @@ typedef struct FileSelectParams {
typedef struct FileAssetSelectParams {
FileSelectParams base_params;
- AssetLibraryReference asset_library;
+ AssetLibraryReference asset_library_ref;
short import_type; /* eFileAssetImportType */
char _pad[6];
diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h
index 5f8a8c6230a..28acf5413b8 100644
--- a/source/blender/makesdna/DNA_userdef_types.h
+++ b/source/blender/makesdna/DNA_userdef_types.h
@@ -645,7 +645,7 @@ typedef struct UserDef_Experimental {
char use_full_frame_compositor;
char use_sculpt_vertex_colors;
char use_sculpt_tools_tilt;
- char use_asset_browser;
+ char use_extended_asset_browser;
char use_override_templates;
char _pad[5];
/** `makesdna` does not allow empty structs. */
diff --git a/source/blender/makesdna/DNA_workspace_types.h b/source/blender/makesdna/DNA_workspace_types.h
index 2bac040ea90..e0294d3534c 100644
--- a/source/blender/makesdna/DNA_workspace_types.h
+++ b/source/blender/makesdna/DNA_workspace_types.h
@@ -139,7 +139,7 @@ typedef struct WorkSpace {
/** 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 asset_library;
+ AssetLibraryReference asset_library_ref;
} WorkSpace;
/**
diff --git a/source/blender/makesdna/intern/makesdna.c b/source/blender/makesdna/intern/makesdna.c
index f2a75a60a44..061c3462a69 100644
--- a/source/blender/makesdna/intern/makesdna.c
+++ b/source/blender/makesdna/intern/makesdna.c
@@ -165,6 +165,10 @@ static char **names;
static char **types;
/** At `types_size[a]` is the size of type `a` on this systems bitness (32 or 64). */
static short *types_size_native;
+/** Contains align requirements for a struct on 32 bit systems. */
+static short *types_align_32;
+/** Contains align requirements for a struct on 64 bit systems. */
+static short *types_align_64;
/** Contains sizes as they are calculated on 32 bit systems. */
static short *types_size_32;
/** Contains sizes as they are calculated on 64 bit systems. */
@@ -406,6 +410,8 @@ static int add_type(const char *str, int size)
types_size_native[index] = size;
types_size_32[index] = size;
types_size_64[index] = size;
+ types_align_32[index] = size;
+ types_align_64[index] = size;
}
return index;
}
@@ -419,7 +425,8 @@ static int add_type(const char *str, int size)
types_size_native[types_len] = size;
types_size_32[types_len] = size;
types_size_64[types_len] = size;
-
+ types_align_32[types_len] = size;
+ types_align_64[types_len] = size;
if (types_len >= max_array_len) {
printf("too many types\n");
return types_len - 1;
@@ -966,7 +973,9 @@ static int calculate_struct_sizes(int firststruct, FILE *file_verify, const char
int size_native = 0;
int size_32 = 0;
int size_64 = 0;
- bool has_pointer = false;
+ /* Sizes of the largest field in a struct. */
+ int max_align_32 = 0;
+ int max_align_64 = 0;
/* check all elements in struct */
for (int b = 0; b < structpoin[1]; b++, sp += 2) {
@@ -995,7 +1004,6 @@ static int calculate_struct_sizes(int firststruct, FILE *file_verify, const char
/* is it a pointer or function pointer? */
if (cp[0] == '*' || cp[1] == '*') {
- has_pointer = 1;
/* has the name an extra length? (array) */
int mul = 1;
if (cp[namelen - 1] == ']') {
@@ -1042,6 +1050,8 @@ static int calculate_struct_sizes(int firststruct, FILE *file_verify, const char
size_native += sizeof(void *) * mul;
size_32 += 4 * mul;
size_64 += 8 * mul;
+ max_align_32 = MAX2(max_align_32, 4);
+ max_align_64 = MAX2(max_align_64, 8);
}
else if (cp[0] == '[') {
/* parsing can cause names "var" and "[3]"
@@ -1087,6 +1097,8 @@ static int calculate_struct_sizes(int firststruct, FILE *file_verify, const char
size_native += mul * types_size_native[type];
size_32 += mul * types_size_32[type];
size_64 += mul * types_size_64[type];
+ max_align_32 = MAX2(max_align_32, types_align_32[type]);
+ max_align_64 = MAX2(max_align_64, types_align_64[type]);
}
else {
size_native = 0;
@@ -1103,16 +1115,42 @@ static int calculate_struct_sizes(int firststruct, FILE *file_verify, const char
types_size_native[structtype] = size_native;
types_size_32[structtype] = size_32;
types_size_64[structtype] = size_64;
- /* Two ways to detect if a struct contains a pointer:
- * has_pointer is set or size_native doesn't match any of 32/64bit lengths. */
- if (has_pointer || size_64 != size_native || size_32 != size_native) {
- if (size_64 % 8) {
+ types_align_32[structtype] = max_align_32;
+ types_align_64[structtype] = max_align_64;
+
+ /* Sanity check 1: alignment should never be 0. */
+ BLI_assert(max_align_32);
+ BLI_assert(max_align_64);
+
+ /* Sanity check 2: alignment should always be equal or smaller than the maximum
+ * size of a build in type which is 8 bytes (ie int64_t or double). */
+ BLI_assert(max_align_32 <= 8);
+ BLI_assert(max_align_64 <= 8);
+
+ if (size_32 % max_align_32) {
+ /* There is an one odd case where only the 32 bit struct has alignment issues
+ * and the 64 bit does not, that can only be fixed by adding a padding pointer
+ * to the struct to resolve the problem. */
+ if ((size_64 % max_align_64 == 0) && (size_32 % max_align_32 == 4)) {
fprintf(stderr,
- "Sizeerror 8 in struct: %s (add %d bytes)\n",
+ "Sizeerror in 32 bit struct: %s (add paddding pointer)\n",
+ types[structtype]);
+ }
+ else {
+ fprintf(stderr,
+ "Sizeerror in 32 bit struct: %s (add %d bytes)\n",
types[structtype],
- size_64 % 8);
- dna_error = 1;
+ max_align_32 - (size_32 % max_align_32));
}
+ dna_error = 1;
+ }
+
+ if (size_64 % max_align_64) {
+ fprintf(stderr,
+ "Sizeerror in 64 bit struct: %s (add %d bytes)\n",
+ types[structtype],
+ max_align_64 - (size_64 % max_align_64));
+ dna_error = 1;
}
if (size_native % 4 && !ELEM(size_native, 1, 2)) {
@@ -1229,6 +1267,9 @@ static int make_structDNA(const char *base_directory,
types_size_native = MEM_callocN(sizeof(short) * max_array_len, "types_size_native");
types_size_32 = MEM_callocN(sizeof(short) * max_array_len, "types_size_32");
types_size_64 = MEM_callocN(sizeof(short) * max_array_len, "types_size_64");
+ types_align_32 = MEM_callocN(sizeof(short) * max_array_len, "types_size_32");
+ types_align_64 = MEM_callocN(sizeof(short) * max_array_len, "types_size_64");
+
structs = MEM_callocN(sizeof(short *) * max_array_len, "structs");
/* Build versioning data */
@@ -1317,7 +1358,11 @@ static int make_structDNA(const char *base_directory,
sp += 2;
/* ? num_types was elem? */
for (b = 0; b < num_types; b++, sp += 2) {
- printf(" %s %s\n", types[sp[0]], names[sp[1]]);
+ printf(" %s %s allign32:%d, allign64:%d\n",
+ types[sp[0]],
+ names[sp[1]],
+ types_align_32[sp[0]],
+ types_align_64[sp[0]]);
}
}
}
@@ -1439,6 +1484,8 @@ static int make_structDNA(const char *base_directory,
MEM_freeN(types_size_native);
MEM_freeN(types_size_32);
MEM_freeN(types_size_64);
+ MEM_freeN(types_align_32);
+ MEM_freeN(types_align_64);
MEM_freeN(structs);
BLI_memarena_free(mem_arena);
diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h
index 97615016016..f206bde4705 100644
--- a/source/blender/makesrna/RNA_access.h
+++ b/source/blender/makesrna/RNA_access.h
@@ -499,6 +499,7 @@ extern StructRNA RNA_Pose;
extern StructRNA RNA_PoseBone;
extern StructRNA RNA_Preferences;
extern StructRNA RNA_PreferencesEdit;
+extern StructRNA RNA_PreferencesExperimental;
extern StructRNA RNA_PreferencesFilePaths;
extern StructRNA RNA_PreferencesInput;
extern StructRNA RNA_PreferencesKeymap;
@@ -827,6 +828,7 @@ unsigned int RNA_struct_count_properties(StructRNA *srna);
/* lower level functions for access to type properties */
const struct ListBase *RNA_struct_type_properties(StructRNA *srna);
+PropertyRNA *RNA_struct_type_find_property_no_base(StructRNA *srna, const char *identifier);
PropertyRNA *RNA_struct_type_find_property(StructRNA *srna, const char *identifier);
FunctionRNA *RNA_struct_find_function(StructRNA *srna, const char *identifier);
diff --git a/source/blender/makesrna/intern/rna_access.c b/source/blender/makesrna/intern/rna_access.c
index c991216da11..41c31dfebcb 100644
--- a/source/blender/makesrna/intern/rna_access.c
+++ b/source/blender/makesrna/intern/rna_access.c
@@ -883,8 +883,7 @@ bool RNA_struct_is_a(const StructRNA *type, const StructRNA *srna)
PropertyRNA *RNA_struct_find_property(PointerRNA *ptr, const char *identifier)
{
- if (identifier[0] == '[' && identifier[1] == '"') { /* " (dummy comment to avoid confusing some
- * function lists in text editors) */
+ if (identifier[0] == '[' && identifier[1] == '"') {
/* id prop lookup, not so common */
PropertyRNA *r_prop = NULL;
PointerRNA r_ptr; /* only support single level props */
@@ -968,19 +967,33 @@ const struct ListBase *RNA_struct_type_properties(StructRNA *srna)
return &srna->cont.properties;
}
-PropertyRNA *RNA_struct_type_find_property(StructRNA *srna, const char *identifier)
+PropertyRNA *RNA_struct_type_find_property_no_base(StructRNA *srna, const char *identifier)
{
return BLI_findstring_ptr(&srna->cont.properties, identifier, offsetof(PropertyRNA, identifier));
}
+/**
+ * \note #RNA_struct_find_property is a higher level alternative to this function
+ * which takes a #PointerRNA instead of a #StructRNA.
+ */
+PropertyRNA *RNA_struct_type_find_property(StructRNA *srna, const char *identifier)
+{
+ for (; srna; srna = srna->base) {
+ PropertyRNA *prop = RNA_struct_type_find_property_no_base(srna, identifier);
+ if (prop != NULL) {
+ return prop;
+ }
+ }
+ return NULL;
+}
+
FunctionRNA *RNA_struct_find_function(StructRNA *srna, const char *identifier)
{
#if 1
FunctionRNA *func;
- StructRNA *type;
- for (type = srna; type; type = type->base) {
+ for (; srna; srna = srna->base) {
func = (FunctionRNA *)BLI_findstring_ptr(
- &type->functions, identifier, offsetof(FunctionRNA, identifier));
+ &srna->functions, identifier, offsetof(FunctionRNA, identifier));
if (func) {
return func;
}
@@ -3003,7 +3016,7 @@ void RNA_property_float_set(PointerRNA *ptr, PropertyRNA *prop, float value)
BLI_assert(RNA_property_type(prop) == PROP_FLOAT);
BLI_assert(RNA_property_array_check(prop) == false);
/* useful to check on bad values but set function should clamp */
- /* BLI_assert(RNA_property_float_clamp(ptr, prop, &value) == 0); */
+ // BLI_assert(RNA_property_float_clamp(ptr, prop, &value) == 0);
if ((idprop = rna_idproperty_check(&prop, ptr))) {
RNA_property_float_clamp(ptr, prop, &value);
@@ -4980,10 +4993,7 @@ void rna_iterator_array_end(CollectionPropertyIterator *iter)
{
ArrayIterator *internal = &iter->internal.array;
- if (internal->free_ptr) {
- MEM_freeN(internal->free_ptr);
- internal->free_ptr = NULL;
- }
+ MEM_SAFE_FREE(internal->free_ptr);
}
PointerRNA rna_array_lookup_int(
diff --git a/source/blender/makesrna/intern/rna_armature.c b/source/blender/makesrna/intern/rna_armature.c
index 49d02524e43..690506fa517 100644
--- a/source/blender/makesrna/intern/rna_armature.c
+++ b/source/blender/makesrna/intern/rna_armature.c
@@ -56,7 +56,7 @@ static void rna_Armature_update_data(Main *UNUSED(bmain), Scene *UNUSED(scene),
DEG_id_tag_update(id, 0);
WM_main_add_notifier(NC_GEOM | ND_DATA, id);
- /*WM_main_add_notifier(NC_OBJECT|ND_POSE, NULL); */
+ // WM_main_add_notifier(NC_OBJECT|ND_POSE, NULL);
}
static void rna_Armature_dependency_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
@@ -994,7 +994,7 @@ static void rna_def_bone_common(StructRNA *srna, int editbone)
}
RNA_def_property_float_sdna(prop, NULL, "rad_head");
/* XXX range is 0 to lim, where lim = 10000.0f * MAX2(1.0, view3d->grid); */
- /*RNA_def_property_range(prop, 0, 1000); */
+ // RNA_def_property_range(prop, 0, 1000);
RNA_def_property_ui_range(prop, 0.01, 100, 0.1, 3);
RNA_def_property_ui_text(
prop, "Envelope Head Radius", "Radius of head of bone (for Envelope deform only)");
@@ -1008,7 +1008,7 @@ static void rna_def_bone_common(StructRNA *srna, int editbone)
}
RNA_def_property_float_sdna(prop, NULL, "rad_tail");
/* XXX range is 0 to lim, where lim = 10000.0f * MAX2(1.0, view3d->grid); */
- /*RNA_def_property_range(prop, 0, 1000); */
+ // RNA_def_property_range(prop, 0, 1000);
RNA_def_property_ui_range(prop, 0.01, 100, 0.1, 3);
RNA_def_property_ui_text(
prop, "Envelope Tail Radius", "Radius of tail of bone (for Envelope deform only)");
@@ -1346,7 +1346,7 @@ static void rna_def_edit_bone(BlenderRNA *brna)
/* calculated and read only, not actual data access */
prop = RNA_def_property(srna, "matrix", PROP_FLOAT, PROP_MATRIX);
- /* RNA_def_property_float_sdna(prop, NULL, ""); */ /* Doesn't access any real data. */
+ // RNA_def_property_float_sdna(prop, NULL, ""); /* Doesn't access any real data. */
RNA_def_property_multi_array(prop, 2, rna_matrix_dimsize_4x4);
// RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_flag(prop, PROP_THICK_WRAP); /* no reference to original data */
diff --git a/source/blender/makesrna/intern/rna_asset.c b/source/blender/makesrna/intern/rna_asset.c
index 80b2594d0c9..1e583f4ca52 100644
--- a/source/blender/makesrna/intern/rna_asset.c
+++ b/source/blender/makesrna/intern/rna_asset.c
@@ -273,7 +273,7 @@ static void rna_def_asset_handle_api(StructRNA *srna)
parm = RNA_def_pointer(func, "asset_file_handle", "FileSelectEntry", "", "");
RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
parm = RNA_def_pointer(func,
- "asset_library",
+ "asset_library_ref",
"AssetLibraryReference",
"",
"The asset library containing the given asset, only valid if the asset "
@@ -319,7 +319,7 @@ 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");
+ srna, "Asset Library Reference", "Identifier to refer to the asset library");
}
/**
@@ -329,7 +329,7 @@ PropertyRNA *rna_def_asset_library_reference_common(struct StructRNA *srna,
const char *get,
const char *set)
{
- PropertyRNA *prop = RNA_def_property(srna, "asset_library", PROP_ENUM, PROP_NONE);
+ PropertyRNA *prop = RNA_def_property(srna, "asset_library_ref", 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");
diff --git a/source/blender/makesrna/intern/rna_constraint.c b/source/blender/makesrna/intern/rna_constraint.c
index e36d052d27c..5968c8bac8f 100644
--- a/source/blender/makesrna/intern/rna_constraint.c
+++ b/source/blender/makesrna/intern/rna_constraint.c
@@ -3509,6 +3509,12 @@ void RNA_def_constraint(BlenderRNA *brna)
RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
RNA_def_property_ui_icon(prop, ICON_HIDE_OFF, -1);
+ prop = RNA_def_property(srna, "enabled", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", CONSTRAINT_OFF);
+ RNA_def_property_ui_text(prop, "Enabled", "Use the results of this constraint");
+ RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
+ RNA_def_property_ui_icon(prop, ICON_HIDE_ON, 1);
+
prop = RNA_def_property(srna, "show_expanded", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_flag(prop, PROP_NO_DEG_UPDATE);
RNA_def_property_boolean_sdna(prop, NULL, "ui_expand_flag", 0);
diff --git a/source/blender/makesrna/intern/rna_curveprofile.c b/source/blender/makesrna/intern/rna_curveprofile.c
index b3ab8cc15a2..66c0fc72c7a 100644
--- a/source/blender/makesrna/intern/rna_curveprofile.c
+++ b/source/blender/makesrna/intern/rna_curveprofile.c
@@ -23,9 +23,6 @@
#include "DNA_curve_types.h"
#include "DNA_curveprofile_types.h"
-#include "DNA_texture_types.h"
-
-#include "BLI_utildefines.h"
#include "RNA_define.h"
#include "rna_internal.h"
@@ -37,31 +34,7 @@
# include "RNA_access.h"
-# include "DNA_image_types.h"
-# include "DNA_material_types.h"
-# include "DNA_movieclip_types.h"
-# include "DNA_node_types.h"
-# include "DNA_object_types.h"
-# include "DNA_particle_types.h"
-# include "DNA_sequence_types.h"
-
-# include "MEM_guardedalloc.h"
-
-# include "BKE_colorband.h"
# include "BKE_curveprofile.h"
-# include "BKE_image.h"
-# include "BKE_linestyle.h"
-# include "BKE_movieclip.h"
-# include "BKE_node.h"
-
-# include "DEG_depsgraph.h"
-
-# include "ED_node.h"
-
-# include "IMB_colormanagement.h"
-# include "IMB_imbuf.h"
-
-# include "SEQ_sequencer.h"
/**
* Set both handle types for all selected points in the profile-- faster than changing types
diff --git a/source/blender/makesrna/intern/rna_gpencil.c b/source/blender/makesrna/intern/rna_gpencil.c
index aad6f1231dd..3e5dce64c7b 100644
--- a/source/blender/makesrna/intern/rna_gpencil.c
+++ b/source/blender/makesrna/intern/rna_gpencil.c
@@ -2117,7 +2117,7 @@ static void rna_def_gpencil_layer(BlenderRNA *brna)
prop = RNA_def_property(srna, "use_viewlayer_masks", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", GP_LAYER_DISABLE_MASKS_IN_VIEWLAYER);
RNA_def_property_ui_text(
- prop, "Use Masks in Render", "Include the mask layers when rendering the viewlayer");
+ prop, "Use Masks in Render", "Include the mask layers when rendering the view-layer");
RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
/* blend mode */
diff --git a/source/blender/makesrna/intern/rna_mesh.c b/source/blender/makesrna/intern/rna_mesh.c
index 9caff88a3a5..fbc578acb8e 100644
--- a/source/blender/makesrna/intern/rna_mesh.c
+++ b/source/blender/makesrna/intern/rna_mesh.c
@@ -1687,7 +1687,7 @@ static void rna_def_mvert(BlenderRNA *brna)
RNA_def_property_update(prop, 0, "rna_Mesh_update_data_legacy_deg_tag_all");
prop = RNA_def_property(srna, "normal", PROP_FLOAT, PROP_DIRECTION);
- /* RNA_def_property_float_sdna(prop, NULL, "no"); */
+ // RNA_def_property_float_sdna(prop, NULL, "no");
RNA_def_property_array(prop, 3);
RNA_def_property_range(prop, -1.0f, 1.0f);
RNA_def_property_float_funcs(
diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c
index 802690b4bb6..8906b1a6d34 100644
--- a/source/blender/makesrna/intern/rna_nodetree.c
+++ b/source/blender/makesrna/intern/rna_nodetree.c
@@ -439,6 +439,34 @@ static const EnumPropertyItem rna_node_geometry_attribute_randomize_operation_it
{0, NULL, 0, NULL, NULL},
};
+static const EnumPropertyItem rna_node_geometry_curve_handle_type_items[] = {
+ {GEO_NODE_CURVE_HANDLE_FREE,
+ "FREE",
+ ICON_HANDLE_FREE,
+ "Free",
+ "The handle can be moved anywhere, and doesn't influence the point's other handle"},
+ {GEO_NODE_CURVE_HANDLE_AUTO,
+ "AUTO",
+ ICON_HANDLE_AUTO,
+ "Auto",
+ "The location is automatically calculated to be smooth"},
+ {GEO_NODE_CURVE_HANDLE_VECTOR,
+ "VECTOR",
+ ICON_HANDLE_VECTOR,
+ "Vector",
+ "The location is calculated to point to the next/previous control point"},
+ {GEO_NODE_CURVE_HANDLE_ALIGN,
+ "ALIGN",
+ ICON_HANDLE_ALIGNED,
+ "Align",
+ "The location is constrained to point in the opposite direction as the other handle"},
+ {0, NULL, 0, NULL, NULL}};
+
+static const EnumPropertyItem rna_node_geometry_curve_handle_side_items[] = {
+ {GEO_NODE_CURVE_HANDLE_LEFT, "LEFT", ICON_NONE, "Left", "Use the left handles"},
+ {GEO_NODE_CURVE_HANDLE_RIGHT, "RIGHT", ICON_NONE, "Right", "Use the right handles"},
+ {0, NULL, 0, NULL, NULL}};
+
#ifndef RNA_RUNTIME
static const EnumPropertyItem node_sampler_type_items[] = {
{0, "NEAREST", 0, "Nearest", ""},
@@ -1008,7 +1036,7 @@ static void rna_NodeTree_get_from_context(
void *ret1, *ret2, *ret3;
RNA_pointer_create(NULL, ntreetype->rna_ext.srna, NULL, &ptr); /* dummy */
- /* RNA_struct_find_function(&ptr, "get_from_context"); */
+ // RNA_struct_find_function(&ptr, "get_from_context");
func = &rna_NodeTree_get_from_context_func;
RNA_parameter_list_create(&list, &ptr, func);
@@ -2959,7 +2987,7 @@ static void rna_NodeSocketInterface_register_properties(bNodeTree *ntree,
}
RNA_pointer_create((ID *)ntree, &RNA_NodeSocketInterface, stemp, &ptr);
- /* RNA_struct_find_function(&ptr, "register_properties"); */
+ // RNA_struct_find_function(&ptr, "register_properties");
func = &rna_NodeSocketInterface_register_properties_func;
RNA_parameter_list_create(&list, &ptr, func);
@@ -2985,7 +3013,7 @@ static void rna_NodeSocketInterface_init_socket(
RNA_pointer_create((ID *)ntree, &RNA_NodeSocketInterface, stemp, &ptr);
RNA_pointer_create((ID *)ntree, &RNA_Node, node, &node_ptr);
RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, sock, &sock_ptr);
- /* RNA_struct_find_function(&ptr, "init_socket"); */
+ // RNA_struct_find_function(&ptr, "init_socket");
func = &rna_NodeSocketInterface_init_socket_func;
RNA_parameter_list_create(&list, &ptr, func);
@@ -3015,7 +3043,7 @@ static void rna_NodeSocketInterface_from_socket(bNodeTree *ntree,
RNA_pointer_create((ID *)ntree, &RNA_NodeSocketInterface, stemp, &ptr);
RNA_pointer_create((ID *)ntree, &RNA_Node, node, &node_ptr);
RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, sock, &sock_ptr);
- /* RNA_struct_find_function(&ptr, "from_socket"); */
+ // RNA_struct_find_function(&ptr, "from_socket");
func = &rna_NodeSocketInterface_from_socket_func;
RNA_parameter_list_create(&list, &ptr, func);
@@ -9460,50 +9488,40 @@ static void def_geo_curve_spline_type(StructRNA *srna)
static void def_geo_curve_set_handles(StructRNA *srna)
{
- static const EnumPropertyItem type_items[] = {
- {GEO_NODE_CURVE_HANDLE_FREE,
- "FREE",
- ICON_HANDLE_FREE,
- "Free",
- "The handle can be moved anywhere, and doesn't influence the point's other handle"},
- {GEO_NODE_CURVE_HANDLE_AUTO,
- "AUTO",
- ICON_HANDLE_AUTO,
- "Auto",
- "The location is automatically calculated to be smooth"},
- {GEO_NODE_CURVE_HANDLE_VECTOR,
- "VECTOR",
- ICON_HANDLE_VECTOR,
- "Vector",
- "The location is calculated to point to the next/previous control point"},
- {GEO_NODE_CURVE_HANDLE_ALIGN,
- "ALIGN",
- ICON_HANDLE_ALIGNED,
- "Align",
- "The location is constrained to point in the opposite direction as the other handle"},
- {0, NULL, 0, NULL, NULL}};
-
- static const EnumPropertyItem mode_items[] = {
- {GEO_NODE_CURVE_HANDLE_LEFT, "LEFT", ICON_NONE, "Left", "Update the left handles"},
- {GEO_NODE_CURVE_HANDLE_RIGHT, "RIGHT", ICON_NONE, "Right", "Update the right handles"},
- {0, NULL, 0, NULL, NULL}};
-
PropertyRNA *prop;
RNA_def_struct_sdna_from(srna, "NodeGeometryCurveSetHandles", "storage");
prop = RNA_def_property(srna, "handle_type", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "handle_type");
- RNA_def_property_enum_items(prop, type_items);
+ RNA_def_property_enum_items(prop, rna_node_geometry_curve_handle_type_items);
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update");
prop = RNA_def_property(srna, "mode", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_items(prop, mode_items);
+ RNA_def_property_enum_items(prop, rna_node_geometry_curve_handle_side_items);
RNA_def_property_ui_text(prop, "Mode", "Whether to update left and right handles");
RNA_def_property_flag(prop, PROP_ENUM_FLAG);
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update");
}
+static void def_geo_curve_select_handles(StructRNA *srna)
+{
+ PropertyRNA *prop;
+
+ RNA_def_struct_sdna_from(srna, "NodeGeometryCurveSelectHandles", "storage");
+
+ prop = RNA_def_property(srna, "handle_type", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "handle_type");
+ RNA_def_property_enum_items(prop, rna_node_geometry_curve_handle_type_items);
+ RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update");
+
+ prop = RNA_def_property(srna, "mode", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_items(prop, rna_node_geometry_curve_handle_side_items);
+ RNA_def_property_ui_text(prop, "Mode", "Whether to check the type of left and right handles");
+ RNA_def_property_flag(prop, PROP_ENUM_FLAG);
+ RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update");
+}
+
static void def_geo_curve_primitive_circle(StructRNA *srna)
{
static const EnumPropertyItem mode_items[] = {
diff --git a/source/blender/makesrna/intern/rna_object.c b/source/blender/makesrna/intern/rna_object.c
index bef430b0314..0f6b89722a4 100644
--- a/source/blender/makesrna/intern/rna_object.c
+++ b/source/blender/makesrna/intern/rna_object.c
@@ -218,6 +218,12 @@ static EnumPropertyItem instance_items_pointcloud[] = {
{OB_DUPLIVERTS, "POINTS", 0, "Points", "Instantiate child objects on all points"},
{0, NULL, 0, NULL, NULL},
};
+
+static EnumPropertyItem instance_items_empty[] = {
+ {0, "NONE", 0, "None", ""},
+ INSTANCE_ITEM_COLLECTION,
+ {0, NULL, 0, NULL, NULL},
+};
#endif
#undef INSTANCE_ITEMS_SHARED
#undef INSTANCE_ITEM_COLLECTION
@@ -751,7 +757,7 @@ static const EnumPropertyItem *rna_Object_instance_type_itemf(bContext *UNUSED(C
const EnumPropertyItem *item;
if (ob->type == OB_EMPTY) {
- item = instance_items;
+ item = instance_items_empty;
}
else if (ob->type == OB_POINTCLOUD) {
item = instance_items_pointcloud;
diff --git a/source/blender/makesrna/intern/rna_particle.c b/source/blender/makesrna/intern/rna_particle.c
index de4cfb2b61a..f732e14d905 100644
--- a/source/blender/makesrna/intern/rna_particle.c
+++ b/source/blender/makesrna/intern/rna_particle.c
@@ -1851,20 +1851,20 @@ static void rna_def_particle(BlenderRNA *brna)
prop = RNA_def_property(srna, "birth_time", PROP_FLOAT, PROP_TIME);
RNA_def_property_float_sdna(prop, NULL, "time");
- /* RNA_def_property_range(prop, lowerLimitf, upperLimitf); */
+ // RNA_def_property_range(prop, lowerLimitf, upperLimitf);
RNA_def_property_ui_text(prop, "Birth Time", "");
prop = RNA_def_property(srna, "lifetime", PROP_FLOAT, PROP_TIME);
- /* RNA_def_property_range(prop, lowerLimitf, upperLimitf); */
+ // RNA_def_property_range(prop, lowerLimitf, upperLimitf);
RNA_def_property_ui_text(prop, "Lifetime", "");
prop = RNA_def_property(srna, "die_time", PROP_FLOAT, PROP_TIME);
RNA_def_property_float_sdna(prop, NULL, "dietime");
- /* RNA_def_property_range(prop, lowerLimitf, upperLimitf); */
+ // RNA_def_property_range(prop, lowerLimitf, upperLimitf);
RNA_def_property_ui_text(prop, "Die Time", "");
prop = RNA_def_property(srna, "size", PROP_FLOAT, PROP_NONE);
- /* RNA_def_property_range(prop, lowerLimitf, upperLimitf); */
+ // RNA_def_property_range(prop, lowerLimitf, upperLimitf);
RNA_def_property_ui_text(prop, "Size", "");
/* */
@@ -3658,7 +3658,7 @@ static void rna_def_particle_system(BlenderRNA *brna)
/* access to particle settings is redirected through functions */
/* to allow proper id-buttons functionality */
prop = RNA_def_property(srna, "settings", PROP_POINTER, PROP_NONE);
- /*RNA_def_property_pointer_sdna(prop, NULL, "part"); */
+ // RNA_def_property_pointer_sdna(prop, NULL, "part");
RNA_def_property_struct_type(prop, "ParticleSettings");
RNA_def_property_flag(prop, PROP_EDITABLE | PROP_NEVER_NULL);
RNA_def_property_pointer_funcs(
diff --git a/source/blender/makesrna/intern/rna_sequencer.c b/source/blender/makesrna/intern/rna_sequencer.c
index 74fe2a26505..dad77b4aad5 100644
--- a/source/blender/makesrna/intern/rna_sequencer.c
+++ b/source/blender/makesrna/intern/rna_sequencer.c
@@ -148,9 +148,9 @@ static void rna_Sequence_invalidate_preprocessed_update(Main *UNUSED(bmain),
}
}
-static void rna_Sequence_invalidate_composite_update(Main *UNUSED(bmain),
- Scene *UNUSED(scene),
- PointerRNA *ptr)
+static void UNUSED_FUNCTION(rna_Sequence_invalidate_composite_update)(Main *UNUSED(bmain),
+ Scene *UNUSED(scene),
+ PointerRNA *ptr)
{
Scene *scene = (Scene *)ptr->owner_id;
Editing *ed = SEQ_editing_get(scene, false);
@@ -1900,7 +1900,7 @@ static void rna_def_sequence(BlenderRNA *brna)
/* stupid 0-100 -> 0-1 */
RNA_def_property_float_funcs(prop, "rna_Sequence_opacity_get", "rna_Sequence_opacity_set", NULL);
RNA_def_property_update(
- prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_composite_update");
+ prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_preprocessed_update");
prop = RNA_def_property(srna, "effect_fader", PROP_FLOAT, PROP_FACTOR);
RNA_def_property_range(prop, 0.0f, 1.0f);
diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c
index c7a5c43255a..5ab13e7b44e 100644
--- a/source/blender/makesrna/intern/rna_space.c
+++ b/source/blender/makesrna/intern/rna_space.c
@@ -2582,13 +2582,13 @@ static int rna_FileAssetSelectParams_asset_library_get(PointerRNA *ptr)
/* Just an extra sanity check to ensure this isn't somehow called for RNA_FileSelectParams. */
BLI_assert(ptr->type == &RNA_FileAssetSelectParams);
- return ED_asset_library_reference_to_enum_value(&params->asset_library);
+ return ED_asset_library_reference_to_enum_value(&params->asset_library_ref);
}
static void rna_FileAssetSelectParams_asset_library_set(PointerRNA *ptr, int value)
{
FileAssetSelectParams *params = ptr->data;
- params->asset_library = ED_asset_library_reference_from_enum_value(value);
+ params->asset_library_ref = ED_asset_library_reference_from_enum_value(value);
}
static void rna_FileAssetSelectParams_asset_category_set(PointerRNA *ptr, uint64_t value)
@@ -7330,6 +7330,13 @@ static void rna_def_space_clip(BlenderRNA *brna)
RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_MOVIECLIP);
RNA_def_property_update(prop, NC_MOVIECLIP | ND_DISPLAY, NULL);
+ /* transform */
+ prop = RNA_def_property(srna, "cursor_location", PROP_FLOAT, PROP_XYZ);
+ RNA_def_property_float_sdna(prop, NULL, "cursor");
+ RNA_def_property_array(prop, 2);
+ RNA_def_property_ui_text(prop, "2D Cursor Location", "2D cursor location for this view");
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_CLIP, NULL);
+
/* pivot point */
prop = RNA_def_property(srna, "pivot_point", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "around");
diff --git a/source/blender/makesrna/intern/rna_speaker.c b/source/blender/makesrna/intern/rna_speaker.c
index 43f0d27f514..2dce9d32006 100644
--- a/source/blender/makesrna/intern/rna_speaker.c
+++ b/source/blender/makesrna/intern/rna_speaker.c
@@ -55,7 +55,9 @@ static void rna_def_speaker(BlenderRNA *brna)
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_ui_text(prop, "Mute", "Mute the speaker");
RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_SOUND);
- /* RNA_def_property_update(prop, 0, "rna_Speaker_update"); */
+# if 0
+ RNA_def_property_update(prop, 0, "rna_Speaker_update");
+# endif
prop = RNA_def_property(srna, "sound", PROP_POINTER, PROP_NONE);
RNA_def_property_struct_type(prop, "Sound");
@@ -63,24 +65,30 @@ static void rna_def_speaker(BlenderRNA *brna)
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_ui_text(prop, "Sound", "Sound data-block used by this speaker");
- /* RNA_def_property_float_funcs(prop, NULL, "rna_Speaker_sound_set", NULL); */
- /* RNA_def_property_update(prop, 0, "rna_Speaker_update"); */
+# if 0
+ RNA_def_property_float_funcs(prop, NULL, "rna_Speaker_sound_set", NULL);
+ RNA_def_property_update(prop, 0, "rna_Speaker_update");
+# endif
prop = RNA_def_property(srna, "volume_max", PROP_FLOAT, PROP_FACTOR);
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_range(prop, 0.0f, 1.0f);
RNA_def_property_ui_text(
prop, "Maximum Volume", "Maximum volume, no matter how near the object is");
- /* RNA_def_property_float_funcs(prop, NULL, "rna_Speaker_volume_max_set", NULL); */
- /* RNA_def_property_update(prop, 0, "rna_Speaker_update"); */
+# if 0
+ RNA_def_property_float_funcs(prop, NULL, "rna_Speaker_volume_max_set", NULL);
+ RNA_def_property_update(prop, 0, "rna_Speaker_update");
+# endif
prop = RNA_def_property(srna, "volume_min", PROP_FLOAT, PROP_FACTOR);
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_range(prop, 0.0f, 1.0f);
RNA_def_property_ui_text(
prop, "Minimum Volume", "Minimum volume, no matter how far away the object is");
- /* RNA_def_property_float_funcs(prop, NULL, "rna_Speaker_volume_min_set", NULL); */
- /* RNA_def_property_update(prop, 0, "rna_Speaker_update"); */
+# if 0
+ RNA_def_property_float_funcs(prop, NULL, "rna_Speaker_volume_min_set", NULL);
+ RNA_def_property_update(prop, 0, "rna_Speaker_update");
+# endif
prop = RNA_def_property(srna, "distance_max", PROP_FLOAT, PROP_NONE);
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
@@ -89,24 +97,30 @@ static void rna_def_speaker(BlenderRNA *brna)
prop,
"Maximum Distance",
"Maximum distance for volume calculation, no matter how far away the object is");
- /* RNA_def_property_float_funcs(prop, NULL, "rna_Speaker_distance_max_set", NULL); */
- /* RNA_def_property_update(prop, 0, "rna_Speaker_update"); */
+# if 0
+ RNA_def_property_float_funcs(prop, NULL, "rna_Speaker_distance_max_set", NULL);
+ RNA_def_property_update(prop, 0, "rna_Speaker_update");
+# endif
prop = RNA_def_property(srna, "distance_reference", PROP_FLOAT, PROP_NONE);
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_range(prop, 0.0f, FLT_MAX);
RNA_def_property_ui_text(
prop, "Reference Distance", "Reference distance at which volume is 100%");
- /* RNA_def_property_float_funcs(prop, NULL, "rna_Speaker_distance_reference_set", NULL); */
- /* RNA_def_property_update(prop, 0, "rna_Speaker_update"); */
+# if 0
+ RNA_def_property_float_funcs(prop, NULL, "rna_Speaker_distance_reference_set", NULL);
+ RNA_def_property_update(prop, 0, "rna_Speaker_update");
+# endif
prop = RNA_def_property(srna, "attenuation", PROP_FLOAT, PROP_NONE);
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_range(prop, 0.0f, FLT_MAX);
RNA_def_property_ui_text(
prop, "Attenuation", "How strong the distance affects volume, depending on distance model");
- /* RNA_def_property_float_funcs(prop, NULL, "rna_Speaker_attenuation_set", NULL); */
- /* RNA_def_property_update(prop, 0, "rna_Speaker_update"); */
+# if 0
+ RNA_def_property_float_funcs(prop, NULL, "rna_Speaker_attenuation_set", NULL);
+ RNA_def_property_update(prop, 0, "rna_Speaker_update");
+# endif
prop = RNA_def_property(srna, "cone_angle_outer", PROP_FLOAT, PROP_NONE);
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
@@ -116,8 +130,10 @@ static void rna_def_speaker(BlenderRNA *brna)
"Outer Cone Angle",
"Angle of the outer cone, in degrees, outside this cone the volume is "
"the outer cone volume, between inner and outer cone the volume is interpolated");
- /* RNA_def_property_float_funcs(prop, NULL, "rna_Speaker_cone_angle_outer_set", NULL); */
- /* RNA_def_property_update(prop, 0, "rna_Speaker_update"); */
+# if 0
+ RNA_def_property_float_funcs(prop, NULL, "rna_Speaker_cone_angle_outer_set", NULL);
+ RNA_def_property_update(prop, 0, "rna_Speaker_update");
+# endif
prop = RNA_def_property(srna, "cone_angle_inner", PROP_FLOAT, PROP_NONE);
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
@@ -126,29 +142,37 @@ static void rna_def_speaker(BlenderRNA *brna)
prop,
"Inner Cone Angle",
"Angle of the inner cone, in degrees, inside the cone the volume is 100%");
- /* RNA_def_property_float_funcs(prop, NULL, "rna_Speaker_cone_angle_inner_set", NULL); */
- /* RNA_def_property_update(prop, 0, "rna_Speaker_update"); */
+# if 0
+ RNA_def_property_float_funcs(prop, NULL, "rna_Speaker_cone_angle_inner_set", NULL);
+ RNA_def_property_update(prop, 0, "rna_Speaker_update");
+# endif
prop = RNA_def_property(srna, "cone_volume_outer", PROP_FLOAT, PROP_FACTOR);
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_range(prop, 0.0f, 1.0f);
RNA_def_property_ui_text(prop, "Outer Cone Volume", "Volume outside the outer cone");
- /* RNA_def_property_float_funcs(prop, NULL, "rna_Speaker_cone_volume_outer_set", NULL); */
- /* RNA_def_property_update(prop, 0, "rna_Speaker_update"); */
+# if 0
+ RNA_def_property_float_funcs(prop, NULL, "rna_Speaker_cone_volume_outer_set", NULL);
+ RNA_def_property_update(prop, 0, "rna_Speaker_update");
+# endif
prop = RNA_def_property(srna, "volume", PROP_FLOAT, PROP_FACTOR);
RNA_def_property_range(prop, 0.0f, 1.0f);
RNA_def_property_ui_text(prop, "Volume", "How loud the sound is");
RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_SOUND);
- /* RNA_def_property_float_funcs(prop, NULL, "rna_Speaker_volume_set", NULL); */
- /* RNA_def_property_update(prop, 0, "rna_Speaker_update"); */
+# if 0
+ RNA_def_property_float_funcs(prop, NULL, "rna_Speaker_volume_set", NULL);
+ RNA_def_property_update(prop, 0, "rna_Speaker_update");
+# endif
prop = RNA_def_property(srna, "pitch", PROP_FLOAT, PROP_NONE);
RNA_def_property_range(prop, 0.1f, 10.0f);
RNA_def_property_ui_text(prop, "Pitch", "Playback pitch of the sound");
RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_SOUND);
- /* RNA_def_property_float_funcs(prop, NULL, "rna_Speaker_pitch_set", NULL); */
- /* RNA_def_property_update(prop, 0, "rna_Speaker_update"); */
+# if 0
+ RNA_def_property_float_funcs(prop, NULL, "rna_Speaker_pitch_set", NULL);
+ RNA_def_property_update(prop, 0, "rna_Speaker_update");
+# endif
/* common */
rna_def_animdata_common(srna);
diff --git a/source/blender/makesrna/intern/rna_text.c b/source/blender/makesrna/intern/rna_text.c
index 1351c027004..52f762e5494 100644
--- a/source/blender/makesrna/intern/rna_text.c
+++ b/source/blender/makesrna/intern/rna_text.c
@@ -240,8 +240,7 @@ static void rna_def_text(BlenderRNA *brna)
prop = RNA_def_property(srna, "use_module", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flags", TXT_ISSCRIPT);
- RNA_def_property_ui_text(
- prop, "Register", "Run this text as a script on loading, Text name must end with \".py\"");
+ RNA_def_property_ui_text(prop, "Register", "Run this text as a Python script on loading");
prop = RNA_def_property(srna, "indentation", PROP_ENUM, PROP_NONE); /* as an enum */
RNA_def_property_enum_bitflag_sdna(prop, NULL, "flags");
diff --git a/source/blender/makesrna/intern/rna_ui.c b/source/blender/makesrna/intern/rna_ui.c
index a88b100435a..c506a533032 100644
--- a/source/blender/makesrna/intern/rna_ui.c
+++ b/source/blender/makesrna/intern/rna_ui.c
@@ -1458,7 +1458,7 @@ static void rna_def_panel(BlenderRNA *brna)
RNA_def_property_string_sdna(prop, NULL, "type->description");
RNA_def_property_string_maxlength(prop, RNA_DYN_DESCR_MAX); /* else it uses the pointer size! */
RNA_def_property_string_funcs(prop, NULL, NULL, "rna_Panel_bl_description_set");
- /* RNA_def_property_clear_flag(prop, PROP_EDITABLE); */
+ // RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_flag(prop, PROP_REGISTER_OPTIONAL);
RNA_def_property_clear_flag(prop, PROP_NEVER_NULL); /* check for NULL */
@@ -1820,7 +1820,7 @@ static void rna_def_menu(BlenderRNA *brna)
RNA_def_property_string_sdna(prop, NULL, "type->description");
RNA_def_property_string_maxlength(prop, RNA_DYN_DESCR_MAX); /* else it uses the pointer size! */
RNA_def_property_string_funcs(prop, NULL, NULL, "rna_Menu_bl_description_set");
- /* RNA_def_property_clear_flag(prop, PROP_EDITABLE); */
+ // RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_flag(prop, PROP_REGISTER_OPTIONAL);
RNA_def_property_clear_flag(prop, PROP_NEVER_NULL); /* check for NULL */
diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c
index d29a90a1886..483506d5733 100644
--- a/source/blender/makesrna/intern/rna_userdef.c
+++ b/source/blender/makesrna/intern/rna_userdef.c
@@ -6155,7 +6155,7 @@ static void rna_def_userdef_filepaths(BlenderRNA *brna)
prop,
"Python Scripts Directory",
"Alternate script path, matching the default layout with subdirectories: "
- "startup, addons, modules, and presets (requires restart)");
+ "startup, add-ons, modules, and presets (requires restart)");
/* TODO: editing should reset sys.path! */
prop = RNA_def_property(srna, "i18n_branches_directory", PROP_STRING, PROP_DIRPATH);
@@ -6297,12 +6297,12 @@ static void rna_def_userdef_experimental(BlenderRNA *brna)
RNA_def_property_ui_text(
prop, "Sculpt Mode Tilt Support", "Support for pen tablet tilt events in Sculpt Mode");
- prop = RNA_def_property(srna, "use_asset_browser", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "use_asset_browser", 1);
- RNA_def_property_ui_text(
- prop,
- "Asset Browser",
- "Enable Asset Browser editor and operators to manage data-blocks as asset");
+ prop = RNA_def_property(srna, "use_extended_asset_browser", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_ui_text(prop,
+ "Extended Asset Browser",
+ "Enable Asset Browser editor and operators to manage regular "
+ "data-blocks as assets, not just poses");
+ RNA_def_property_update(prop, 0, "rna_userdef_ui_update");
prop = RNA_def_property(srna, "use_override_templates", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "use_override_templates", 1);
diff --git a/source/blender/makesrna/intern/rna_wm.c b/source/blender/makesrna/intern/rna_wm.c
index 667f3822935..b910648495b 100644
--- a/source/blender/makesrna/intern/rna_wm.c
+++ b/source/blender/makesrna/intern/rna_wm.c
@@ -1915,7 +1915,7 @@ static void rna_def_operator(BlenderRNA *brna)
/* Without setting the length the pointer size would be used. -3 because `.` -> `_OT_`. */
RNA_def_property_string_maxlength(prop, OP_MAX_TYPENAME - 3);
RNA_def_property_string_funcs(prop, NULL, NULL, "rna_Operator_bl_idname_set");
- /* RNA_def_property_clear_flag(prop, PROP_EDITABLE); */
+ // RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_flag(prop, PROP_REGISTER);
RNA_def_struct_name_property(srna, prop);
@@ -1923,7 +1923,7 @@ static void rna_def_operator(BlenderRNA *brna)
RNA_def_property_string_sdna(prop, NULL, "type->name");
RNA_def_property_string_maxlength(prop, RNA_DYN_DESCR_MAX); /* else it uses the pointer size! */
RNA_def_property_string_funcs(prop, NULL, NULL, "rna_Operator_bl_label_set");
- /* RNA_def_property_clear_flag(prop, PROP_EDITABLE); */
+ // RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_flag(prop, PROP_REGISTER);
prop = RNA_def_property(srna, "bl_translation_context", PROP_STRING, PROP_NONE);
@@ -1943,7 +1943,7 @@ static void rna_def_operator(BlenderRNA *brna)
"rna_Operator_bl_description_get",
"rna_Operator_bl_description_length",
"rna_Operator_bl_description_set");
- /* RNA_def_property_clear_flag(prop, PROP_EDITABLE); */
+ // RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_flag(prop, PROP_REGISTER_OPTIONAL);
prop = RNA_def_property(srna, "bl_undo_group", PROP_STRING, PROP_NONE);
@@ -1953,7 +1953,7 @@ static void rna_def_operator(BlenderRNA *brna)
"rna_Operator_bl_undo_group_get",
"rna_Operator_bl_undo_group_length",
"rna_Operator_bl_undo_group_set");
- /* RNA_def_property_clear_flag(prop, PROP_EDITABLE); */
+ // RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_flag(prop, PROP_REGISTER_OPTIONAL);
prop = RNA_def_property(srna, "bl_options", PROP_ENUM, PROP_NONE);
@@ -2013,7 +2013,7 @@ static void rna_def_macro_operator(BlenderRNA *brna)
RNA_def_property_string_sdna(prop, NULL, "type->idname");
RNA_def_property_string_maxlength(prop, OP_MAX_TYPENAME); /* else it uses the pointer size! */
RNA_def_property_string_funcs(prop, NULL, NULL, "rna_Operator_bl_idname_set");
- /* RNA_def_property_clear_flag(prop, PROP_EDITABLE); */
+ // RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_flag(prop, PROP_REGISTER);
RNA_def_struct_name_property(srna, prop);
@@ -2021,7 +2021,7 @@ static void rna_def_macro_operator(BlenderRNA *brna)
RNA_def_property_string_sdna(prop, NULL, "type->name");
RNA_def_property_string_maxlength(prop, RNA_DYN_DESCR_MAX); /* else it uses the pointer size! */
RNA_def_property_string_funcs(prop, NULL, NULL, "rna_Operator_bl_label_set");
- /* RNA_def_property_clear_flag(prop, PROP_EDITABLE); */
+ // RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_flag(prop, PROP_REGISTER);
prop = RNA_def_property(srna, "bl_translation_context", PROP_STRING, PROP_NONE);
@@ -2041,7 +2041,7 @@ static void rna_def_macro_operator(BlenderRNA *brna)
"rna_Operator_bl_description_get",
"rna_Operator_bl_description_length",
"rna_Operator_bl_description_set");
- /* RNA_def_property_clear_flag(prop, PROP_EDITABLE); */
+ // RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_flag(prop, PROP_REGISTER_OPTIONAL);
prop = RNA_def_property(srna, "bl_undo_group", PROP_STRING, PROP_NONE);
@@ -2051,7 +2051,7 @@ static void rna_def_macro_operator(BlenderRNA *brna)
"rna_Operator_bl_undo_group_get",
"rna_Operator_bl_undo_group_length",
"rna_Operator_bl_undo_group_set");
- /* RNA_def_property_clear_flag(prop, PROP_EDITABLE); */
+ // RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_flag(prop, PROP_REGISTER_OPTIONAL);
prop = RNA_def_property(srna, "bl_options", PROP_ENUM, PROP_NONE);
@@ -2073,11 +2073,13 @@ static void rna_def_operator_type_macro(BlenderRNA *brna)
srna, "Operator Macro", "Storage of a sub operator in a macro after it has been added");
RNA_def_struct_sdna(srna, "wmOperatorTypeMacro");
- /* prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE); */
- /* RNA_def_property_clear_flag(prop, PROP_EDITABLE); */
- /* RNA_def_property_string_sdna(prop, NULL, "idname"); */
- /* RNA_def_property_ui_text(prop, "Name", "Name of the sub operator"); */
- /* RNA_def_struct_name_property(srna, prop); */
+# if 0
+ prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_string_sdna(prop, NULL, "idname");
+ RNA_def_property_ui_text(prop, "Name", "Name of the sub operator");
+ RNA_def_struct_name_property(srna, prop);
+# endif
prop = RNA_def_property(srna, "properties", PROP_POINTER, PROP_NONE);
RNA_def_property_flag(prop, PROP_NEVER_NULL);
diff --git a/source/blender/makesrna/intern/rna_wm_api.c b/source/blender/makesrna/intern/rna_wm_api.c
index bde15daa682..e123604cbe9 100644
--- a/source/blender/makesrna/intern/rna_wm_api.c
+++ b/source/blender/makesrna/intern/rna_wm_api.c
@@ -230,7 +230,7 @@ static wmKeyMapItem *rna_KeyMap_item_new(wmKeyMap *km,
bool repeat,
bool head)
{
- /* wmWindowManager *wm = CTX_wm_manager(C); */
+ // wmWindowManager *wm = CTX_wm_manager(C);
wmKeyMapItem *kmi = NULL;
char idname_bl[OP_MAX_TYPENAME];
int modifier = 0;
diff --git a/source/blender/makesrna/intern/rna_wm_gizmo.c b/source/blender/makesrna/intern/rna_wm_gizmo.c
index 6a1574f3dbe..febb0e14e07 100644
--- a/source/blender/makesrna/intern/rna_wm_gizmo.c
+++ b/source/blender/makesrna/intern/rna_wm_gizmo.c
@@ -80,7 +80,7 @@ static void rna_gizmo_draw_cb(const struct bContext *C, struct wmGizmo *gz)
ParameterList list;
FunctionRNA *func;
RNA_pointer_create(NULL, gz->type->rna_ext.srna, gz, &gz_ptr);
- /* RNA_struct_find_function(&gz_ptr, "draw"); */
+ /* Reference `RNA_struct_find_function(&gz_ptr, "draw")` directly. */
func = &rna_Gizmo_draw_func;
RNA_parameter_list_create(&list, &gz_ptr, func);
RNA_parameter_set_lookup(&list, "context", &C);
@@ -98,7 +98,7 @@ static void rna_gizmo_draw_select_cb(const struct bContext *C, struct wmGizmo *g
ParameterList list;
FunctionRNA *func;
RNA_pointer_create(NULL, gz->type->rna_ext.srna, gz, &gz_ptr);
- /* RNA_struct_find_function(&gz_ptr, "draw_select"); */
+ /* Reference `RNA_struct_find_function(&gz_ptr, "draw_select")` directly. */
func = &rna_Gizmo_draw_select_func;
RNA_parameter_list_create(&list, &gz_ptr, func);
RNA_parameter_set_lookup(&list, "context", &C);
@@ -117,7 +117,7 @@ static int rna_gizmo_test_select_cb(struct bContext *C, struct wmGizmo *gz, cons
ParameterList list;
FunctionRNA *func;
RNA_pointer_create(NULL, gz->type->rna_ext.srna, gz, &gz_ptr);
- /* RNA_struct_find_function(&gz_ptr, "test_select"); */
+ /* Reference `RNA_struct_find_function(&gz_ptr, "test_select")` directly. */
func = &rna_Gizmo_test_select_func;
RNA_parameter_list_create(&list, &gz_ptr, func);
RNA_parameter_set_lookup(&list, "context", &C);
@@ -144,7 +144,7 @@ static int rna_gizmo_modal_cb(struct bContext *C,
FunctionRNA *func;
const int tweak_flag_int = tweak_flag;
RNA_pointer_create(NULL, gz->type->rna_ext.srna, gz, &gz_ptr);
- /* RNA_struct_find_function(&gz_ptr, "modal"); */
+ /* Reference `RNA_struct_find_function(&gz_ptr, "modal")` directly. */
func = &rna_Gizmo_modal_func;
RNA_parameter_list_create(&list, &gz_ptr, func);
RNA_parameter_set_lookup(&list, "context", &C);
@@ -168,7 +168,7 @@ static void rna_gizmo_setup_cb(struct wmGizmo *gz)
ParameterList list;
FunctionRNA *func;
RNA_pointer_create(NULL, gz->type->rna_ext.srna, gz, &gz_ptr);
- /* RNA_struct_find_function(&gz_ptr, "setup"); */
+ /* Reference `RNA_struct_find_function(&gz_ptr, "setup")` directly. */
func = &rna_Gizmo_setup_func;
RNA_parameter_list_create(&list, &gz_ptr, func);
gzgroup->type->rna_ext.call((bContext *)NULL, &gz_ptr, func, &list);
@@ -183,7 +183,7 @@ static int rna_gizmo_invoke_cb(struct bContext *C, struct wmGizmo *gz, const str
ParameterList list;
FunctionRNA *func;
RNA_pointer_create(NULL, gz->type->rna_ext.srna, gz, &gz_ptr);
- /* RNA_struct_find_function(&gz_ptr, "invoke"); */
+ /* Reference `RNA_struct_find_function(&gz_ptr, "invoke")` directly. */
func = &rna_Gizmo_invoke_func;
RNA_parameter_list_create(&list, &gz_ptr, func);
RNA_parameter_set_lookup(&list, "context", &C);
@@ -206,7 +206,7 @@ static void rna_gizmo_exit_cb(struct bContext *C, struct wmGizmo *gz, bool cance
ParameterList list;
FunctionRNA *func;
RNA_pointer_create(NULL, gz->type->rna_ext.srna, gz, &gz_ptr);
- /* RNA_struct_find_function(&gz_ptr, "exit"); */
+ /* Reference `RNA_struct_find_function(&gz_ptr, "exit")` directly. */
func = &rna_Gizmo_exit_func;
RNA_parameter_list_create(&list, &gz_ptr, func);
RNA_parameter_set_lookup(&list, "context", &C);
@@ -226,7 +226,7 @@ static void rna_gizmo_select_refresh_cb(struct wmGizmo *gz)
ParameterList list;
FunctionRNA *func;
RNA_pointer_create(NULL, gz->type->rna_ext.srna, gz, &gz_ptr);
- /* RNA_struct_find_function(&gz_ptr, "select_refresh"); */
+ /* Reference `RNA_struct_find_function(&gz_ptr, "select_refresh")` directly. */
func = &rna_Gizmo_select_refresh_func;
RNA_parameter_list_create(&list, &gz_ptr, func);
gzgroup->type->rna_ext.call((bContext *)NULL, &gz_ptr, func, &list);
@@ -785,7 +785,7 @@ static void rna_gizmogroup_invoke_prepare_cb(const bContext *C,
FunctionRNA *func;
RNA_pointer_create(NULL, gzgroup->type->rna_ext.srna, gzgroup, &gzgroup_ptr);
- /* RNA_struct_find_function(&wgroupr, "invoke_prepare"); */
+ /* Reference `RNA_struct_find_function(&wgroupr, "invoke_prepare")` directly. */
func = &rna_GizmoGroup_invoke_prepare_func;
RNA_parameter_list_create(&list, &gzgroup_ptr, func);
@@ -1033,7 +1033,7 @@ static void rna_def_gizmo(BlenderRNA *brna, PropertyRNA *cprop)
RNA_def_property_string_sdna(prop, NULL, "type->idname");
RNA_def_property_string_maxlength(prop, MAX_NAME);
RNA_def_property_string_funcs(prop, NULL, NULL, "rna_Gizmo_bl_idname_set");
- /* RNA_def_property_clear_flag(prop, PROP_EDITABLE); */
+ // RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_flag(prop, PROP_REGISTER);
RNA_define_verify_sdna(1); /* not in sdna */
@@ -1362,7 +1362,7 @@ static void rna_def_gizmogroup(BlenderRNA *brna)
RNA_def_property_string_sdna(prop, NULL, "type->name");
RNA_def_property_string_maxlength(prop, MAX_NAME); /* else it uses the pointer size! */
RNA_def_property_string_funcs(prop, NULL, NULL, "rna_GizmoGroup_bl_label_set");
- /* RNA_def_property_clear_flag(prop, PROP_EDITABLE); */
+ // RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_flag(prop, PROP_REGISTER);
prop = RNA_def_property(srna, "bl_space_type", PROP_ENUM, PROP_NONE);
diff --git a/source/blender/makesrna/intern/rna_workspace.c b/source/blender/makesrna/intern/rna_workspace.c
index 95f62d7de16..d76ad254140 100644
--- a/source/blender/makesrna/intern/rna_workspace.c
+++ b/source/blender/makesrna/intern/rna_workspace.c
@@ -112,13 +112,13 @@ static void rna_WorkSpace_owner_ids_clear(WorkSpace *workspace)
static int rna_WorkSpace_asset_library_get(PointerRNA *ptr)
{
const WorkSpace *workspace = ptr->data;
- return ED_asset_library_reference_to_enum_value(&workspace->asset_library);
+ return ED_asset_library_reference_to_enum_value(&workspace->asset_library_ref);
}
static void rna_WorkSpace_asset_library_set(PointerRNA *ptr, int value)
{
WorkSpace *workspace = ptr->data;
- workspace->asset_library = ED_asset_library_reference_from_enum_value(value);
+ workspace->asset_library_ref = ED_asset_library_reference_from_enum_value(value);
}
static bToolRef *rna_WorkSpace_tools_from_tkey(WorkSpace *workspace,
diff --git a/source/blender/makesrna/intern/rna_world.c b/source/blender/makesrna/intern/rna_world.c
index 1ca0eb74cf5..a66e3090548 100644
--- a/source/blender/makesrna/intern/rna_world.c
+++ b/source/blender/makesrna/intern/rna_world.c
@@ -216,7 +216,7 @@ void RNA_def_world(BlenderRNA *brna)
RNA_def_property_array(prop, 3);
RNA_def_property_float_array_default(prop, default_world_color);
RNA_def_property_ui_text(prop, "Color", "Color of the background");
- /* RNA_def_property_update(prop, 0, "rna_World_update"); */
+ // RNA_def_property_update(prop, 0, "rna_World_update");
/* render-only uses this */
RNA_def_property_update(prop, 0, "rna_World_draw_update");
diff --git a/source/blender/makesrna/intern/rna_xr.c b/source/blender/makesrna/intern/rna_xr.c
index 9a512e351cb..4cab92ad878 100644
--- a/source/blender/makesrna/intern/rna_xr.c
+++ b/source/blender/makesrna/intern/rna_xr.c
@@ -96,7 +96,7 @@ static XrActionMapBinding *rna_XrActionMapBinding_find(XrActionMapItem *ami, con
# endif
}
-static int rna_XrActionMapBinding_axis0_flag_get(PointerRNA *ptr)
+static int rna_XrActionMapBinding_axis0_region_get(PointerRNA *ptr)
{
# ifdef WITH_XR_OPENXR
XrActionMapBinding *amb = ptr->data;
@@ -112,7 +112,7 @@ static int rna_XrActionMapBinding_axis0_flag_get(PointerRNA *ptr)
return 0;
}
-static void rna_XrActionMapBinding_axis0_flag_set(PointerRNA *ptr, int value)
+static void rna_XrActionMapBinding_axis0_region_set(PointerRNA *ptr, int value)
{
# ifdef WITH_XR_OPENXR
XrActionMapBinding *amb = ptr->data;
@@ -123,7 +123,7 @@ static void rna_XrActionMapBinding_axis0_flag_set(PointerRNA *ptr, int value)
# endif
}
-static int rna_XrActionMapBinding_axis1_flag_get(PointerRNA *ptr)
+static int rna_XrActionMapBinding_axis1_region_get(PointerRNA *ptr)
{
# ifdef WITH_XR_OPENXR
XrActionMapBinding *amb = ptr->data;
@@ -139,7 +139,7 @@ static int rna_XrActionMapBinding_axis1_flag_get(PointerRNA *ptr)
return 0;
}
-static void rna_XrActionMapBinding_axis1_flag_set(PointerRNA *ptr, int value)
+static void rna_XrActionMapBinding_axis1_region_set(PointerRNA *ptr, int value)
{
# ifdef WITH_XR_OPENXR
XrActionMapBinding *amb = ptr->data;
@@ -289,12 +289,7 @@ static void rna_XrActionMapItem_bimanual_set(PointerRNA *ptr, bool value)
{
# ifdef WITH_XR_OPENXR
XrActionMapItem *ami = ptr->data;
- if (value) {
- ami->action_flag |= XR_ACTION_BIMANUAL;
- }
- else {
- ami->action_flag &= ~XR_ACTION_BIMANUAL;
- }
+ SET_FLAG_FROM_TEST(ami->action_flag, value, XR_ACTION_BIMANUAL);
# else
UNUSED_VARS(ptr, value);
# endif
@@ -317,18 +312,13 @@ static void rna_XrActionMapItem_haptic_match_user_paths_set(PointerRNA *ptr, boo
{
# ifdef WITH_XR_OPENXR
XrActionMapItem *ami = ptr->data;
- if (value) {
- ami->haptic_flag |= XR_HAPTIC_MATCHUSERPATHS;
- }
- else {
- ami->haptic_flag &= ~XR_HAPTIC_MATCHUSERPATHS;
- }
+ SET_FLAG_FROM_TEST(ami->haptic_flag, value, XR_HAPTIC_MATCHUSERPATHS);
# else
UNUSED_VARS(ptr, value);
# endif
}
-static int rna_XrActionMapItem_haptic_flag_get(PointerRNA *ptr)
+static int rna_XrActionMapItem_haptic_mode_get(PointerRNA *ptr)
{
# ifdef WITH_XR_OPENXR
XrActionMapItem *ami = ptr->data;
@@ -345,7 +335,7 @@ static int rna_XrActionMapItem_haptic_flag_get(PointerRNA *ptr)
return XR_HAPTIC_PRESS;
}
-static void rna_XrActionMapItem_haptic_flag_set(PointerRNA *ptr, int value)
+static void rna_XrActionMapItem_haptic_mode_set(PointerRNA *ptr, int value)
{
# ifdef WITH_XR_OPENXR
XrActionMapItem *ami = ptr->data;
@@ -622,7 +612,6 @@ static bool rna_XrSessionState_action_create(bContext *C,
const bool is_button_action = (is_float_action || ami->type == XR_BOOLEAN_INPUT);
wmOperatorType *ot = NULL;
IDProperty *op_properties = NULL;
- const char *haptic_name = NULL;
int64_t haptic_duration_msec;
if (is_button_action) {
@@ -635,7 +624,6 @@ static bool rna_XrSessionState_action_create(bContext *C,
}
}
- haptic_name = &ami->haptic_name[0];
haptic_duration_msec = (int64_t)(ami->haptic_duration * 1000.0f);
}
@@ -647,7 +635,7 @@ static bool rna_XrSessionState_action_create(bContext *C,
subaction_paths,
ot,
op_properties,
- is_button_action ? &haptic_name : NULL,
+ is_button_action ? ami->haptic_name : NULL,
is_button_action ? &haptic_duration_msec : NULL,
is_button_action ? &ami->haptic_frequency : NULL,
is_button_action ? &ami->haptic_amplitude : NULL,
@@ -803,7 +791,7 @@ bool rna_XrSessionState_haptic_action_apply(bContext *C,
return WM_xr_haptic_action_apply(&wm->xr,
action_set_name,
action_name,
- user_path[0] ? &user_path : NULL,
+ user_path[0] ? user_path : NULL,
&duration_msec,
&frequency,
&amplitude);
@@ -820,20 +808,19 @@ void rna_XrSessionState_haptic_action_stop(bContext *C,
{
# ifdef WITH_XR_OPENXR
wmWindowManager *wm = CTX_wm_manager(C);
- WM_xr_haptic_action_stop(
- &wm->xr, action_set_name, action_name, user_path[0] ? &user_path : NULL);
+ WM_xr_haptic_action_stop(&wm->xr, action_set_name, action_name, user_path[0] ? user_path : NULL);
# else
UNUSED_VARS(C, action_set_name, action_name, user_path);
# endif
}
static void rna_XrSessionState_controller_grip_location_get(bContext *C,
- int *index,
+ int index,
float r_values[3])
{
# ifdef WITH_XR_OPENXR
const wmWindowManager *wm = CTX_wm_manager(C);
- WM_xr_session_state_controller_grip_location_get(&wm->xr, *index, r_values);
+ WM_xr_session_state_controller_grip_location_get(&wm->xr, index, r_values);
# else
UNUSED_VARS(C, index);
zero_v3(r_values);
@@ -854,12 +841,12 @@ static void rna_XrSessionState_controller_grip_rotation_get(bContext *C,
}
static void rna_XrSessionState_controller_aim_location_get(bContext *C,
- int *index,
+ int index,
float r_values[3])
{
# ifdef WITH_XR_OPENXR
const wmWindowManager *wm = CTX_wm_manager(C);
- WM_xr_session_state_controller_aim_location_get(&wm->xr, *index, r_values);
+ WM_xr_session_state_controller_aim_location_get(&wm->xr, index, r_values);
# else
UNUSED_VARS(C, index);
zero_v3(r_values);
@@ -1061,7 +1048,7 @@ static void rna_def_xr_actionmap_bindings(BlenderRNA *brna, PropertyRNA *cprop)
RNA_def_struct_ui_text(srna, "XR Action Map Bindings", "Collection of XR action map bindings");
func = RNA_def_function(srna, "new", "rna_XrActionMapBinding_new");
- parm = RNA_def_string(func, "name", NULL, 0, "Name of the action map binding", "");
+ parm = RNA_def_string(func, "name", NULL, MAX_NAME, "Name of the action map binding", "");
RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
parm = RNA_def_boolean(func,
"replace_existing",
@@ -1110,7 +1097,7 @@ static void rna_def_xr_actionmap_items(BlenderRNA *brna, PropertyRNA *cprop)
RNA_def_struct_ui_text(srna, "XR Action Map Items", "Collection of XR action map items");
func = RNA_def_function(srna, "new", "rna_XrActionMapItem_new");
- parm = RNA_def_string(func, "name", NULL, 0, "Name of the action map item", "");
+ parm = RNA_def_string(func, "name", NULL, MAX_NAME, "Name of the action map item", "");
RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
parm = RNA_def_boolean(func,
"replace_existing",
@@ -1314,7 +1301,7 @@ static void rna_def_xr_actionmap(BlenderRNA *brna)
prop = RNA_def_property(srna, "haptic_mode", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, rna_enum_xr_haptic_flags);
RNA_def_property_enum_funcs(
- prop, "rna_XrActionMapItem_haptic_flag_get", "rna_XrActionMapItem_haptic_flag_set", NULL);
+ prop, "rna_XrActionMapItem_haptic_mode_get", "rna_XrActionMapItem_haptic_mode_set", NULL);
RNA_def_property_ui_text(prop, "Haptic mode", "Haptic application mode");
prop = RNA_def_property(srna, "bindings", PROP_COLLECTION, PROP_NONE);
@@ -1357,8 +1344,8 @@ static void rna_def_xr_actionmap(BlenderRNA *brna)
prop = RNA_def_property(srna, "axis0_region", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, rna_enum_xr_axis0_flags);
RNA_def_property_enum_funcs(prop,
- "rna_XrActionMapBinding_axis0_flag_get",
- "rna_XrActionMapBinding_axis0_flag_set",
+ "rna_XrActionMapBinding_axis0_region_get",
+ "rna_XrActionMapBinding_axis0_region_set",
NULL);
RNA_def_property_ui_text(
prop, "Axis 0 Region", "Action execution region for the first input axis");
@@ -1366,8 +1353,8 @@ static void rna_def_xr_actionmap(BlenderRNA *brna)
prop = RNA_def_property(srna, "axis1_region", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, rna_enum_xr_axis1_flags);
RNA_def_property_enum_funcs(prop,
- "rna_XrActionMapBinding_axis1_flag_get",
- "rna_XrActionMapBinding_axis1_flag_set",
+ "rna_XrActionMapBinding_axis1_region_get",
+ "rna_XrActionMapBinding_axis1_region_set",
NULL);
RNA_def_property_ui_text(
prop, "Axis 1 Region", "Action execution region for the second input axis");
@@ -1695,16 +1682,16 @@ static void rna_def_xr_session_state(BlenderRNA *brna)
RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED);
parm = RNA_def_int(func, "index", 0, 0, 255, "Index", "Controller index", 0, 255);
RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
- RNA_def_float_translation(func,
- "location",
- 3,
- NULL,
- -FLT_MAX,
- FLT_MAX,
- "Location",
- "Controller grip location",
- -FLT_MAX,
- FLT_MAX);
+ parm = RNA_def_float_translation(func,
+ "location",
+ 3,
+ NULL,
+ -FLT_MAX,
+ FLT_MAX,
+ "Location",
+ "Controller grip location",
+ -FLT_MAX,
+ FLT_MAX);
RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_OUTPUT);
func = RNA_def_function(
@@ -1739,16 +1726,16 @@ static void rna_def_xr_session_state(BlenderRNA *brna)
RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED);
parm = RNA_def_int(func, "index", 0, 0, 255, "Index", "Controller index", 0, 255);
RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
- RNA_def_float_translation(func,
- "location",
- 3,
- NULL,
- -FLT_MAX,
- FLT_MAX,
- "Location",
- "Controller aim location",
- -FLT_MAX,
- FLT_MAX);
+ parm = RNA_def_float_translation(func,
+ "location",
+ 3,
+ NULL,
+ -FLT_MAX,
+ FLT_MAX,
+ "Location",
+ "Controller aim location",
+ -FLT_MAX,
+ FLT_MAX);
RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_OUTPUT);
func = RNA_def_function(
diff --git a/source/blender/modifiers/intern/MOD_normal_edit.c b/source/blender/modifiers/intern/MOD_normal_edit.c
index e7750f0a0d1..1dbdcf87d63 100644
--- a/source/blender/modifiers/intern/MOD_normal_edit.c
+++ b/source/blender/modifiers/intern/MOD_normal_edit.c
@@ -556,15 +556,13 @@ static Mesh *normalEditModifier_do(NormalEditModifierData *enmd,
polynors = CustomData_add_layer(pdata, CD_NORMAL, CD_CALLOC, NULL, num_polys);
CustomData_set_layer_flag(pdata, CD_NORMAL, CD_FLAG_TEMPORARY);
}
- BKE_mesh_calc_normals_poly(mvert,
- NULL,
- num_verts,
- mloop,
- mpoly,
- num_loops,
- num_polys,
- polynors,
- (result->runtime.cd_dirty_vert & CD_MASK_NORMAL) ? false : true);
+ if (result->runtime.cd_dirty_vert & CD_MASK_NORMAL) {
+ BKE_mesh_calc_normals_poly_and_vertex(
+ mvert, num_verts, mloop, num_loops, mpoly, num_polys, polynors, NULL);
+ }
+ else {
+ BKE_mesh_calc_normals_poly(mvert, num_verts, mloop, num_loops, mpoly, num_polys, polynors);
+ }
result->runtime.cd_dirty_vert &= ~CD_MASK_NORMAL;
diff --git a/source/blender/modifiers/intern/MOD_solidify_extrude.c b/source/blender/modifiers/intern/MOD_solidify_extrude.c
index e97190b1878..00fa6e24a64 100644
--- a/source/blender/modifiers/intern/MOD_solidify_extrude.c
+++ b/source/blender/modifiers/intern/MOD_solidify_extrude.c
@@ -259,14 +259,12 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex
/* calculate only face normals */
poly_nors = MEM_malloc_arrayN(numPolys, sizeof(*poly_nors), __func__);
BKE_mesh_calc_normals_poly(orig_mvert,
- NULL,
(int)numVerts,
orig_mloop,
- orig_mpoly,
(int)numLoops,
+ orig_mpoly,
(int)numPolys,
- poly_nors,
- true);
+ poly_nors);
}
STACK_INIT(new_vert_arr, numVerts * 2);
@@ -507,8 +505,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. */
if ((smd->flag & MOD_SOLIDIFY_EVEN) == 0) {
/* no even thickness, very simple */
- float scalar_short;
- float scalar_short_vgroup;
+ float ofs_new_vgroup;
/* for clamping */
float *vert_lens = NULL;
@@ -597,7 +594,7 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex
uint i_orig, i_end;
bool do_shell_align;
- scalar_short = scalar_short_vgroup = ofs_new / 32767.0f;
+ ofs_new_vgroup = ofs_new;
INIT_VERT_ARRAY_OFFSETS(false);
@@ -606,36 +603,40 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex
if (dvert) {
MDeformVert *dv = &dvert[i];
if (defgrp_invert) {
- scalar_short_vgroup = 1.0f - BKE_defvert_find_weight(dv, defgrp_index);
+ ofs_new_vgroup = 1.0f - BKE_defvert_find_weight(dv, defgrp_index);
}
else {
- scalar_short_vgroup = BKE_defvert_find_weight(dv, defgrp_index);
+ ofs_new_vgroup = BKE_defvert_find_weight(dv, defgrp_index);
}
- scalar_short_vgroup = (offset_fac_vg + (scalar_short_vgroup * offset_fac_vg_inv)) *
- scalar_short;
+ ofs_new_vgroup = (offset_fac_vg + (ofs_new_vgroup * offset_fac_vg_inv)) * ofs_new;
}
if (do_clamp && offset > FLT_EPSILON) {
/* always reset because we may have set before */
if (dvert == NULL) {
- scalar_short_vgroup = scalar_short;
+ ofs_new_vgroup = ofs_new;
}
if (do_angle_clamp) {
float cos_ang = cosf(((2 * M_PI) - vert_angs[i]) * 0.5f);
if (cos_ang > 0) {
float max_off = sqrtf(vert_lens[i]) * 0.5f / cos_ang;
if (max_off < offset * 0.5f) {
- scalar_short_vgroup *= max_off / offset * 2;
+ ofs_new_vgroup *= max_off / offset * 2;
}
}
}
else {
if (vert_lens[i] < offset_sq) {
float scalar = sqrtf(vert_lens[i]) / offset;
- scalar_short_vgroup *= scalar;
+ ofs_new_vgroup *= scalar;
}
}
}
- madd_v3v3short_fl(mv->co, mv->no, scalar_short_vgroup);
+ if (vert_nors) {
+ madd_v3_v3fl(mv->co, vert_nors[i], ofs_new_vgroup);
+ }
+ else {
+ madd_v3v3short_fl(mv->co, mv->no, ofs_new_vgroup / 32767.0f);
+ }
}
}
@@ -643,7 +644,7 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex
uint i_orig, i_end;
bool do_shell_align;
- scalar_short = scalar_short_vgroup = ofs_orig / 32767.0f;
+ ofs_new_vgroup = ofs_orig;
/* as above but swapped */
INIT_VERT_ARRAY_OFFSETS(true);
@@ -653,36 +654,40 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex
if (dvert) {
MDeformVert *dv = &dvert[i];
if (defgrp_invert) {
- scalar_short_vgroup = 1.0f - BKE_defvert_find_weight(dv, defgrp_index);
+ ofs_new_vgroup = 1.0f - BKE_defvert_find_weight(dv, defgrp_index);
}
else {
- scalar_short_vgroup = BKE_defvert_find_weight(dv, defgrp_index);
+ ofs_new_vgroup = BKE_defvert_find_weight(dv, defgrp_index);
}
- scalar_short_vgroup = (offset_fac_vg + (scalar_short_vgroup * offset_fac_vg_inv)) *
- scalar_short;
+ ofs_new_vgroup = (offset_fac_vg + (ofs_new_vgroup * offset_fac_vg_inv)) * ofs_orig;
}
if (do_clamp && offset > FLT_EPSILON) {
/* always reset because we may have set before */
if (dvert == NULL) {
- scalar_short_vgroup = scalar_short;
+ ofs_new_vgroup = ofs_orig;
}
if (do_angle_clamp) {
float cos_ang = cosf(vert_angs[i_orig] * 0.5f);
if (cos_ang > 0) {
float max_off = sqrtf(vert_lens[i]) * 0.5f / cos_ang;
if (max_off < offset * 0.5f) {
- scalar_short_vgroup *= max_off / offset * 2;
+ ofs_new_vgroup *= max_off / offset * 2;
}
}
}
else {
if (vert_lens[i] < offset_sq) {
float scalar = sqrtf(vert_lens[i]) / offset;
- scalar_short_vgroup *= scalar;
+ ofs_new_vgroup *= scalar;
}
}
}
- madd_v3v3short_fl(mv->co, mv->no, scalar_short_vgroup);
+ if (vert_nors) {
+ madd_v3_v3fl(mv->co, vert_nors[i], ofs_new_vgroup);
+ }
+ else {
+ madd_v3v3short_fl(mv->co, mv->no, ofs_new_vgroup / 32767.0f);
+ }
}
}
diff --git a/source/blender/modifiers/intern/MOD_solidify_nonmanifold.c b/source/blender/modifiers/intern/MOD_solidify_nonmanifold.c
index 18d308e5f02..5b4716a1a43 100644
--- a/source/blender/modifiers/intern/MOD_solidify_nonmanifold.c
+++ b/source/blender/modifiers/intern/MOD_solidify_nonmanifold.c
@@ -211,15 +211,8 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md,
/* Calculate only face normals. */
poly_nors = MEM_malloc_arrayN(numPolys, sizeof(*poly_nors), __func__);
- BKE_mesh_calc_normals_poly(orig_mvert,
- NULL,
- (int)numVerts,
- orig_mloop,
- orig_mpoly,
- (int)numLoops,
- (int)numPolys,
- poly_nors,
- true);
+ BKE_mesh_calc_normals_poly(
+ orig_mvert, (int)numVerts, orig_mloop, (int)numLoops, orig_mpoly, (int)numPolys, poly_nors);
NewFaceRef *face_sides_arr = MEM_malloc_arrayN(
numPolys * 2, sizeof(*face_sides_arr), "face_sides_arr in solidify");
diff --git a/source/blender/modifiers/intern/MOD_weighted_normal.c b/source/blender/modifiers/intern/MOD_weighted_normal.c
index 3b147c69716..1ee64b935b7 100644
--- a/source/blender/modifiers/intern/MOD_weighted_normal.c
+++ b/source/blender/modifiers/intern/MOD_weighted_normal.c
@@ -615,8 +615,8 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *
polynors = CustomData_add_layer(pdata, CD_NORMAL, CD_CALLOC, NULL, numPolys);
CustomData_set_layer_flag(pdata, CD_NORMAL, CD_FLAG_TEMPORARY);
}
- BKE_mesh_calc_normals_poly(
- mvert, NULL, numVerts, mloop, mpoly, numLoops, numPolys, polynors, false);
+ BKE_mesh_calc_normals_poly_and_vertex(
+ mvert, numVerts, mloop, numLoops, mpoly, numPolys, polynors, NULL);
const float split_angle = mesh->smoothresh;
short(*clnors)[2];
diff --git a/source/blender/nodes/CMakeLists.txt b/source/blender/nodes/CMakeLists.txt
index 10dcf942b91..c3b1980648d 100644
--- a/source/blender/nodes/CMakeLists.txt
+++ b/source/blender/nodes/CMakeLists.txt
@@ -175,6 +175,7 @@ set(SRC
geometry/nodes/node_geo_curve_primitive_star.cc
geometry/nodes/node_geo_curve_resample.cc
geometry/nodes/node_geo_curve_reverse.cc
+ geometry/nodes/node_geo_curve_select_by_handle_type.cc
geometry/nodes/node_geo_curve_set_handles.cc
geometry/nodes/node_geo_curve_spline_type.cc
geometry/nodes/node_geo_curve_subdivide.cc
diff --git a/source/blender/nodes/NOD_geometry.h b/source/blender/nodes/NOD_geometry.h
index 26f81efca72..c3464aa052b 100644
--- a/source/blender/nodes/NOD_geometry.h
+++ b/source/blender/nodes/NOD_geometry.h
@@ -96,6 +96,7 @@ void register_node_type_geo_point_translate(void);
void register_node_type_geo_points_to_volume(void);
void register_node_type_geo_raycast(void);
void register_node_type_geo_sample_texture(void);
+void register_node_type_geo_select_by_handle_type(void);
void register_node_type_geo_select_by_material(void);
void register_node_type_geo_separate_components(void);
void register_node_type_geo_subdivision_surface(void);
diff --git a/source/blender/nodes/NOD_static_types.h b/source/blender/nodes/NOD_static_types.h
index cc5be95208c..c5899f3bfc1 100644
--- a/source/blender/nodes/NOD_static_types.h
+++ b/source/blender/nodes/NOD_static_types.h
@@ -303,6 +303,7 @@ DefNode(GeometryNode, GEO_NODE_CURVE_PRIMITIVE_STAR, 0, "CURVE_PRIMITIVE_STAR",
DefNode(GeometryNode, GEO_NODE_CURVE_RESAMPLE, def_geo_curve_resample, "CURVE_RESAMPLE", CurveResample, "Resample Curve", "")
DefNode(GeometryNode, GEO_NODE_CURVE_REVERSE, 0, "CURVE_REVERSE", CurveReverse, "Curve Reverse", "")
DefNode(GeometryNode, GEO_NODE_CURVE_SET_HANDLES, def_geo_curve_set_handles, "CURVE_SET_HANDLES", CurveSetHandles, "Set Handle Type", "")
+DefNode(GeometryNode, GEO_NODE_CURVE_SELECT_HANDLES, def_geo_curve_select_handles, "CURVE_SELECT_HANDLES", CurveSelectHandles, "Select by Handle Type", "")
DefNode(GeometryNode, GEO_NODE_CURVE_SPLINE_TYPE, def_geo_curve_spline_type, "CURVE_SPLINE_TYPE", CurveSplineType, "Set Spline Type", "")
DefNode(GeometryNode, GEO_NODE_CURVE_SUBDIVIDE, def_geo_curve_subdivide, "CURVE_SUBDIVIDE", CurveSubdivide, "Curve Subdivide", "")
DefNode(GeometryNode, GEO_NODE_CURVE_TO_MESH, 0, "CURVE_TO_MESH", CurveToMesh, "Curve to Mesh", "")
diff --git a/source/blender/nodes/geometry/nodes/node_geo_attribute_sample_texture.cc b/source/blender/nodes/geometry/nodes/node_geo_attribute_sample_texture.cc
index e0a3f5ad334..5f02061da97 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_attribute_sample_texture.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_attribute_sample_texture.cc
@@ -30,7 +30,7 @@
static bNodeSocketTemplate geo_node_attribute_sample_texture_in[] = {
{SOCK_GEOMETRY, N_("Geometry")},
- {SOCK_TEXTURE, N_("Texture")},
+ {SOCK_TEXTURE, N_("Texture"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, PROP_NONE, SOCK_HIDE_LABEL},
{SOCK_STRING, N_("Mapping")},
{SOCK_STRING, N_("Result")},
{-1, ""},
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 91d569282c3..91e08d7777b 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_convex_hull.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_convex_hull.cc
@@ -304,6 +304,8 @@ static void geo_node_convex_hull_exec(GeoNodeExecParams params)
}
params.set_output("Convex Hull", GeometrySet::create_with_mesh(mesh));
#else
+ params.error_message_add(NodeWarningType::Error,
+ TIP_("Disabled, Blender was compiled without Bullet"));
params.set_output("Convex Hull", geometry_set);
#endif /* WITH_BULLET */
}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_select_by_handle_type.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_select_by_handle_type.cc
new file mode 100644
index 00000000000..fb21c05b0c0
--- /dev/null
+++ b/source/blender/nodes/geometry/nodes/node_geo_curve_select_by_handle_type.cc
@@ -0,0 +1,147 @@
+/*
+ * 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 "BKE_spline.hh"
+
+#include "UI_interface.h"
+#include "UI_resources.h"
+
+#include "node_geometry_util.hh"
+
+static bNodeSocketTemplate geo_node_select_by_handle_type_in[] = {
+ {SOCK_GEOMETRY, N_("Geometry")},
+ {SOCK_STRING, N_("Selection")},
+ {-1, ""},
+};
+
+static bNodeSocketTemplate geo_node_select_by_handle_type_out[] = {
+ {SOCK_GEOMETRY, N_("Geometry")},
+ {-1, ""},
+};
+
+static void geo_node_curve_select_by_handle_type_layout(uiLayout *layout,
+ bContext *UNUSED(C),
+ PointerRNA *ptr)
+{
+ uiItemR(layout, ptr, "mode", UI_ITEM_R_EXPAND, nullptr, ICON_NONE);
+ uiItemR(layout, ptr, "handle_type", 0, "", ICON_NONE);
+}
+
+static void geo_node_curve_select_by_handle_type_init(bNodeTree *UNUSED(tree), bNode *node)
+{
+ NodeGeometryCurveSelectHandles *data = (NodeGeometryCurveSelectHandles *)MEM_callocN(
+ sizeof(NodeGeometryCurveSelectHandles), __func__);
+
+ data->handle_type = GEO_NODE_CURVE_HANDLE_AUTO;
+ data->mode = GEO_NODE_CURVE_HANDLE_LEFT | GEO_NODE_CURVE_HANDLE_RIGHT;
+ node->storage = data;
+}
+
+static BezierSpline::HandleType handle_type_from_input_type(const GeometryNodeCurveHandleType type)
+{
+ switch (type) {
+ case GEO_NODE_CURVE_HANDLE_AUTO:
+ return BezierSpline::HandleType::Auto;
+ case GEO_NODE_CURVE_HANDLE_ALIGN:
+ return BezierSpline::HandleType::Align;
+ case GEO_NODE_CURVE_HANDLE_FREE:
+ return BezierSpline::HandleType::Free;
+ case GEO_NODE_CURVE_HANDLE_VECTOR:
+ return BezierSpline::HandleType::Vector;
+ }
+ BLI_assert_unreachable();
+ return BezierSpline::HandleType::Auto;
+}
+
+namespace blender::nodes {
+
+static void select_curve_by_handle_type(const CurveEval &curve,
+ const BezierSpline::HandleType type,
+ const GeometryNodeCurveHandleMode mode,
+ const MutableSpan<bool> r_selection)
+{
+ const Array<int> offsets = curve.control_point_offsets();
+ Span<SplinePtr> splines = curve.splines();
+ threading::parallel_for(splines.index_range(), 128, [&](IndexRange range) {
+ for (const int i_spline : range) {
+ const Spline &spline = *splines[i_spline];
+ if (spline.type() == Spline::Type::Bezier) {
+ const BezierSpline &bezier_spline = static_cast<const BezierSpline &>(spline);
+ Span<BezierSpline::HandleType> types_left = bezier_spline.handle_types_left();
+ Span<BezierSpline::HandleType> types_right = bezier_spline.handle_types_right();
+ for (const int i_point : IndexRange(bezier_spline.size())) {
+ r_selection[offsets[i_spline] + i_point] = (mode & GEO_NODE_CURVE_HANDLE_LEFT &&
+ types_left[i_point] == type) ||
+ (mode & GEO_NODE_CURVE_HANDLE_RIGHT &&
+ types_right[i_point] == type);
+ }
+ }
+ else {
+ r_selection.slice(offsets[i_spline], offsets[i_spline + 1]).fill(false);
+ }
+ }
+ });
+}
+
+static void geo_node_select_by_handle_type_exec(GeoNodeExecParams params)
+{
+ const NodeGeometryCurveSelectHandles *storage =
+ (const NodeGeometryCurveSelectHandles *)params.node().storage;
+ const BezierSpline::HandleType handle_type = handle_type_from_input_type(
+ (GeometryNodeCurveHandleType)storage->handle_type);
+ const GeometryNodeCurveHandleMode mode = (GeometryNodeCurveHandleMode)storage->mode;
+
+ GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry");
+ geometry_set = bke::geometry_set_realize_instances(geometry_set);
+
+ CurveComponent &curve_component = geometry_set.get_component_for_write<CurveComponent>();
+ const CurveEval *curve = curve_component.get_for_read();
+
+ if (curve != nullptr) {
+ const std::string selection_name = params.extract_input<std::string>("Selection");
+ OutputAttribute_Typed<bool> selection =
+ curve_component.attribute_try_get_for_output_only<bool>(selection_name, ATTR_DOMAIN_POINT);
+ if (selection) {
+ select_curve_by_handle_type(*curve, handle_type, mode, selection.as_span());
+ selection.save();
+ }
+ }
+
+ params.set_output("Geometry", std::move(geometry_set));
+}
+
+} // namespace blender::nodes
+
+void register_node_type_geo_select_by_handle_type()
+{
+ static bNodeType ntype;
+
+ geo_node_type_base(
+ &ntype, GEO_NODE_CURVE_SELECT_HANDLES, "Select by Handle Type", NODE_CLASS_GEOMETRY, 0);
+ node_type_socket_templates(
+ &ntype, geo_node_select_by_handle_type_in, geo_node_select_by_handle_type_out);
+ ntype.geometry_node_execute = blender::nodes::geo_node_select_by_handle_type_exec;
+ node_type_init(&ntype, geo_node_curve_select_by_handle_type_init);
+ node_type_storage(&ntype,
+ "NodeGeometryCurveSelectHandles",
+ node_free_standard_storage,
+ node_copy_standard_storage);
+ ntype.draw_buttons = geo_node_curve_select_by_handle_type_layout;
+
+ nodeRegisterType(&ntype);
+}
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 96c6f073ab3..131f9548b40 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
@@ -126,11 +126,11 @@ static Mesh *create_circle_mesh(const float radius,
MutableSpan<MEdge> edges{mesh->medge, mesh->totedge};
MutableSpan<MPoly> polys{mesh->mpoly, mesh->totpoly};
- float angle = 0.0f;
- const float angle_delta = 2.0f * M_PI / static_cast<float>(verts_num);
- for (MVert &vert : verts) {
- copy_v3_v3(vert.co, float3(std::cos(angle) * radius, std::sin(angle) * radius, 0.0f));
- angle += angle_delta;
+ /* Assign vertex coordinates. */
+ const float angle_delta = 2.0f * (M_PI / static_cast<float>(verts_num));
+ for (const int i : IndexRange(verts_num)) {
+ const float angle = i * angle_delta;
+ copy_v3_v3(verts[i].co, float3(std::cos(angle) * radius, std::sin(angle) * radius, 0.0f));
}
if (fill_type == GEO_NODE_MESH_CIRCLE_FILL_TRIANGLE_FAN) {
copy_v3_v3(verts.last().co, float3(0));
diff --git a/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_cone.cc b/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_cone.cc
index 790a518e584..b834f5e2fa0 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_cone.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_cone.cc
@@ -318,9 +318,9 @@ Mesh *create_cylinder_or_cone_mesh(const float radius_top,
/* Calculate vertex positions. */
const int top_verts_start = 0;
const int bottom_verts_start = top_verts_start + (!top_is_point ? verts_num : 1);
- float angle = 0.0f;
- const float angle_delta = 2.0f * M_PI / static_cast<float>(verts_num);
+ const float angle_delta = 2.0f * (M_PI / static_cast<float>(verts_num));
for (const int i : IndexRange(verts_num)) {
+ const float angle = i * angle_delta;
const float x = std::cos(angle);
const float y = std::sin(angle);
if (!top_is_point) {
@@ -330,7 +330,6 @@ Mesh *create_cylinder_or_cone_mesh(const float radius_top,
copy_v3_v3(verts[bottom_verts_start + i].co,
float3(x * radius_bottom, y * radius_bottom, -height));
}
- angle += angle_delta;
}
if (top_is_point) {
copy_v3_v3(verts[top_verts_start].co, float3(0.0f, 0.0f, height));
diff --git a/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_grid.cc b/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_grid.cc
index 7a97ae8e318..410290c79ee 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_grid.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_grid.cc
@@ -79,19 +79,17 @@ static Mesh *create_grid_mesh(const int verts_x,
MutableSpan<MPoly> polys{mesh->mpoly, mesh->totpoly};
{
- const float dx = size_x / edges_x;
- const float dy = size_y / edges_y;
- float x = -size_x * 0.5;
+ const float dx = edges_x == 0 ? 0.0f : size_x / edges_x;
+ const float dy = edges_y == 0 ? 0.0f : size_y / edges_y;
+ const float x_shift = edges_x / 2.0f;
+ const float y_shift = edges_y / 2.0f;
for (const int x_index : IndexRange(verts_x)) {
- float y = -size_y * 0.5;
for (const int y_index : IndexRange(verts_y)) {
const int vert_index = x_index * verts_y + y_index;
- verts[vert_index].co[0] = x;
- verts[vert_index].co[1] = y;
+ verts[vert_index].co[0] = (x_index - x_shift) * dx;
+ verts[vert_index].co[1] = (y_index - y_shift) * dy;
verts[vert_index].co[2] = 0.0f;
- y += dy;
}
- x += dx;
}
}
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 a193c05daa1..2e6d8ca34c8 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
@@ -118,11 +118,9 @@ static Mesh *create_line_mesh(const float3 start, const float3 delta, const int
short normal[3];
normal_float_to_short_v3(normal, delta.normalized());
- float3 co = start;
for (const int i : verts.index_range()) {
- copy_v3_v3(verts[i].co, co);
+ copy_v3_v3(verts[i].co, start + delta * i);
copy_v3_v3_short(verts[i].no, normal);
- co += delta;
}
fill_edge_data(edges);
diff --git a/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_uv_sphere.cc b/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_uv_sphere.cc
index fe456dc4564..affba602234 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_uv_sphere.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_uv_sphere.cc
@@ -69,26 +69,24 @@ static void calculate_sphere_vertex_data(MutableSpan<MVert> verts,
const int rings)
{
const float delta_theta = M_PI / rings;
- const float delta_phi = (2 * M_PI) / segments;
+ const float delta_phi = (2.0f * M_PI) / segments;
copy_v3_v3(verts[0].co, float3(0.0f, 0.0f, radius));
normal_float_to_short_v3(verts[0].no, float3(0.0f, 0.0f, 1.0f));
int vert_index = 1;
- float theta = delta_theta;
- for (const int UNUSED(ring) : IndexRange(rings - 1)) {
- float phi = 0.0f;
- const float z = cosf(theta);
- for (const int UNUSED(segment) : IndexRange(segments)) {
+ for (const int ring : IndexRange(1, rings - 1)) {
+ const float theta = ring * delta_theta;
+ const float z = std::cos(theta);
+ for (const int segment : IndexRange(1, segments)) {
+ const float phi = segment * delta_phi;
const float sin_theta = std::sin(theta);
const float x = sin_theta * std::cos(phi);
const float y = sin_theta * std::sin(phi);
copy_v3_v3(verts[vert_index].co, float3(x, y, z) * radius);
normal_float_to_short_v3(verts[vert_index].no, float3(x, y, z));
- phi += delta_phi;
vert_index++;
}
- theta += delta_theta;
}
copy_v3_v3(verts.last().co, float3(0.0f, 0.0f, -radius));
diff --git a/source/blender/nodes/geometry/nodes/node_geo_raycast.cc b/source/blender/nodes/geometry/nodes/node_geo_raycast.cc
index 0c1d8645411..88e3bf17d43 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_raycast.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_raycast.cc
@@ -63,20 +63,20 @@ static void geo_node_raycast_init(bNodeTree *UNUSED(tree), bNode *node)
node->storage = data;
}
+namespace blender::nodes {
+
static void geo_node_raycast_update(bNodeTree *UNUSED(ntree), bNode *node)
{
NodeGeometryRaycast *node_storage = (NodeGeometryRaycast *)node->storage;
- blender::nodes::update_attribute_input_socket_availabilities(
+ update_attribute_input_socket_availabilities(
*node,
"Ray Direction",
(GeometryNodeAttributeInputMode)node_storage->input_type_ray_direction);
- blender::nodes::update_attribute_input_socket_availabilities(
+ update_attribute_input_socket_availabilities(
*node, "Ray Length", (GeometryNodeAttributeInputMode)node_storage->input_type_ray_length);
}
-namespace blender::nodes {
-
-static void raycast_to_mesh(const Mesh *mesh,
+static void raycast_to_mesh(const Mesh &mesh,
const VArray<float3> &ray_origins,
const VArray<float3> &ray_directions,
const VArray<float> &ray_lengths,
@@ -95,62 +95,64 @@ 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, mesh, BVHTREE_FROM_LOOPTRI, 4);
-
- if (tree_data.tree != nullptr) {
- for (const int i : ray_origins.index_range()) {
- const float ray_length = ray_lengths[i];
- const float3 ray_origin = ray_origins[i];
- const float3 ray_direction = ray_directions[i].normalized();
-
- BVHTreeRayHit hit;
- hit.index = -1;
- hit.dist = ray_length;
- if (BLI_bvhtree_ray_cast(tree_data.tree,
- ray_origin,
- ray_direction,
- 0.0f,
- &hit,
- tree_data.raycast_callback,
- &tree_data) != -1) {
- if (!r_hit.is_empty()) {
- r_hit[i] = hit.index >= 0;
- }
- if (!r_hit_indices.is_empty()) {
- /* Index should always be a valid looptri index, use 0 when hit failed. */
- r_hit_indices[i] = max_ii(hit.index, 0);
- }
- if (!r_hit_positions.is_empty()) {
- r_hit_positions[i] = hit.co;
- }
- if (!r_hit_normals.is_empty()) {
- r_hit_normals[i] = hit.no;
- }
- if (!r_hit_distances.is_empty()) {
- r_hit_distances[i] = hit.dist;
- }
+ BKE_bvhtree_from_mesh_get(&tree_data, &mesh, BVHTREE_FROM_LOOPTRI, 4);
+ if (tree_data.tree == nullptr) {
+ free_bvhtree_from_mesh(&tree_data);
+ return;
+ }
+
+ for (const int i : ray_origins.index_range()) {
+ const float ray_length = ray_lengths[i];
+ const float3 ray_origin = ray_origins[i];
+ const float3 ray_direction = ray_directions[i].normalized();
+
+ BVHTreeRayHit hit;
+ hit.index = -1;
+ hit.dist = ray_length;
+ if (BLI_bvhtree_ray_cast(tree_data.tree,
+ ray_origin,
+ ray_direction,
+ 0.0f,
+ &hit,
+ tree_data.raycast_callback,
+ &tree_data) != -1) {
+ if (!r_hit.is_empty()) {
+ r_hit[i] = hit.index >= 0;
+ }
+ if (!r_hit_indices.is_empty()) {
+ /* Index should always be a valid looptri index, use 0 when hit failed. */
+ r_hit_indices[i] = max_ii(hit.index, 0);
+ }
+ if (!r_hit_positions.is_empty()) {
+ r_hit_positions[i] = hit.co;
}
- else {
- if (!r_hit.is_empty()) {
- r_hit[i] = false;
- }
- if (!r_hit_indices.is_empty()) {
- r_hit_indices[i] = 0;
- }
- if (!r_hit_positions.is_empty()) {
- r_hit_positions[i] = float3(0.0f, 0.0f, 0.0f);
- }
- if (!r_hit_normals.is_empty()) {
- r_hit_normals[i] = float3(0.0f, 0.0f, 0.0f);
- }
- if (!r_hit_distances.is_empty()) {
- r_hit_distances[i] = ray_length;
- }
+ if (!r_hit_normals.is_empty()) {
+ r_hit_normals[i] = hit.no;
+ }
+ if (!r_hit_distances.is_empty()) {
+ r_hit_distances[i] = hit.dist;
+ }
+ }
+ else {
+ if (!r_hit.is_empty()) {
+ r_hit[i] = false;
+ }
+ if (!r_hit_indices.is_empty()) {
+ r_hit_indices[i] = 0;
+ }
+ if (!r_hit_positions.is_empty()) {
+ r_hit_positions[i] = float3(0.0f, 0.0f, 0.0f);
+ }
+ if (!r_hit_normals.is_empty()) {
+ r_hit_normals[i] = float3(0.0f, 0.0f, 0.0f);
+ }
+ if (!r_hit_distances.is_empty()) {
+ r_hit_distances[i] = ray_length;
}
}
-
- free_bvhtree_from_mesh(&tree_data);
}
+
+ free_bvhtree_from_mesh(&tree_data);
}
static bke::mesh_surface_sample::eAttributeMapMode get_map_mode(
@@ -166,7 +168,7 @@ static bke::mesh_surface_sample::eAttributeMapMode get_map_mode(
}
static void raycast_from_points(const GeoNodeExecParams &params,
- const GeometrySet &src_geometry,
+ const GeometrySet &target_geometry,
GeometryComponent &dst_component,
const StringRef hit_name,
const StringRef hit_position_name,
@@ -177,7 +179,8 @@ static void raycast_from_points(const GeoNodeExecParams &params,
{
BLI_assert(hit_attribute_names.size() == hit_attribute_output_names.size());
- const MeshComponent *src_mesh_component = src_geometry.get_component_for_read<MeshComponent>();
+ const MeshComponent *src_mesh_component =
+ target_geometry.get_component_for_read<MeshComponent>();
if (src_mesh_component == nullptr) {
return;
}
@@ -211,8 +214,7 @@ static void raycast_from_points(const GeoNodeExecParams &params,
dst_component.attribute_try_get_for_output_only<float>(hit_distance_name, result_domain);
/* Positions and looptri indices are always needed for interpolation,
- * so create temporary arrays if no output attribute is given.
- */
+ * so create temporary arrays if no output attribute is given. */
Array<int> hit_indices;
Array<float3> hit_positions_internal;
if (!hit_attribute_names.is_empty()) {
@@ -232,7 +234,7 @@ static void raycast_from_points(const GeoNodeExecParams &params,
hit_distance_attribute.as_span() :
MutableSpan<float>();
- raycast_to_mesh(src_mesh,
+ raycast_to_mesh(*src_mesh,
ray_origins,
ray_directions,
ray_lengths,
@@ -268,34 +270,32 @@ static void raycast_from_points(const GeoNodeExecParams &params,
static void geo_node_raycast_exec(GeoNodeExecParams params)
{
GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry");
- GeometrySet cast_geometry_set = params.extract_input<GeometrySet>("Target Geometry");
+ GeometrySet target_geometry_set = params.extract_input<GeometrySet>("Target Geometry");
const std::string hit_name = params.extract_input<std::string>("Is Hit");
const std::string hit_position_name = params.extract_input<std::string>("Hit Position");
const std::string hit_normal_name = params.extract_input<std::string>("Hit Normal");
const std::string hit_distance_name = params.extract_input<std::string>("Hit Distance");
- const Array<std::string> hit_attribute_names = {
- params.extract_input<std::string>("Target Attribute")};
- const Array<std::string> hit_attribute_output_names = {
- params.extract_input<std::string>("Hit Attribute")};
+ const Array<std::string> hit_names = {params.extract_input<std::string>("Target Attribute")};
+ const Array<std::string> hit_output_names = {params.extract_input<std::string>("Hit Attribute")};
geometry_set = bke::geometry_set_realize_instances(geometry_set);
- cast_geometry_set = bke::geometry_set_realize_instances(cast_geometry_set);
+ target_geometry_set = bke::geometry_set_realize_instances(target_geometry_set);
- static const Array<GeometryComponentType> SupportedTypes = {
+ static const Array<GeometryComponentType> types = {
GEO_COMPONENT_TYPE_MESH, GEO_COMPONENT_TYPE_POINT_CLOUD, GEO_COMPONENT_TYPE_CURVE};
- for (GeometryComponentType geo_type : SupportedTypes) {
- if (geometry_set.has(geo_type)) {
+ for (const GeometryComponentType type : types) {
+ if (geometry_set.has(type)) {
raycast_from_points(params,
- cast_geometry_set,
- geometry_set.get_component_for_write(geo_type),
+ target_geometry_set,
+ geometry_set.get_component_for_write(type),
hit_name,
hit_position_name,
hit_normal_name,
hit_distance_name,
- hit_attribute_names,
- hit_attribute_output_names);
+ hit_names,
+ hit_output_names);
}
}
@@ -312,7 +312,7 @@ void register_node_type_geo_raycast()
node_type_socket_templates(&ntype, geo_node_raycast_in, geo_node_raycast_out);
node_type_size_preset(&ntype, NODE_SIZE_LARGE);
node_type_init(&ntype, geo_node_raycast_init);
- node_type_update(&ntype, geo_node_raycast_update);
+ node_type_update(&ntype, blender::nodes::geo_node_raycast_update);
node_type_storage(
&ntype, "NodeGeometryRaycast", node_free_standard_storage, node_copy_standard_storage);
ntype.geometry_node_execute = blender::nodes::geo_node_raycast_exec;
diff --git a/source/blender/nodes/geometry/nodes/node_geo_volume_to_mesh.cc b/source/blender/nodes/geometry/nodes/node_geo_volume_to_mesh.cc
index 403f4906d07..4c1151bf6c2 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_volume_to_mesh.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_volume_to_mesh.cc
@@ -149,6 +149,9 @@ static void geo_node_volume_to_mesh_exec(GeoNodeExecParams params)
#ifdef WITH_OPENVDB
create_mesh_from_volume(geometry_set_in, geometry_set_out, params);
+#else
+ params.error_message_add(NodeWarningType::Error,
+ TIP_("Disabled, Blender was compiled without OpenVDB"));
#endif
params.set_output("Geometry", geometry_set_out);
diff --git a/source/blender/nodes/shader/node_shader_tree.c b/source/blender/nodes/shader/node_shader_tree.c
index 7367f73d171..98edc133a1d 100644
--- a/source/blender/nodes/shader/node_shader_tree.c
+++ b/source/blender/nodes/shader/node_shader_tree.c
@@ -531,6 +531,7 @@ static void ntree_shader_groups_flatten(bNodeTree *localtree)
bNodeTree *ngroup = (bNodeTree *)node->id;
ntreeFreeLocalNode(localtree, node);
ntreeFreeTree(ngroup);
+ BLI_assert(!ngroup->id.py_instance); /* Or call #BKE_libblock_free_data_py. */
MEM_freeN(ngroup);
}
else {
diff --git a/source/blender/python/gpu/gpu_py_shader.c b/source/blender/python/gpu/gpu_py_shader.c
index b3f1c186716..41c40fdeb96 100644
--- a/source/blender/python/gpu/gpu_py_shader.c
+++ b/source/blender/python/gpu/gpu_py_shader.c
@@ -44,14 +44,28 @@
/** \name Enum Conversion.
* \{ */
+#define PYDOC_BUILTIN_SHADER_LIST \
+ " - ``2D_FLAT_COLOR``\n" \
+ " - ``2D_IMAGE``\n" \
+ " - ``2D_SMOOTH_COLOR``\n" \
+ " - ``2D_UNIFORM_COLOR``\n" \
+ " - ``3D_FLAT_COLOR``\n" \
+ " - ``3D_SMOOTH_COLOR``\n" \
+ " - ``3D_UNIFORM_COLOR``\n" \
+ " - ``3D_POLYLINE_FLAT_COLOR``\n" \
+ " - ``3D_POLYLINE_SMOOTH_COLOR``\n" \
+ " - ``3D_POLYLINE_UNIFORM_COLOR``\n"
+
static const struct PyC_StringEnumItems pygpu_shader_builtin_items[] = {
- {GPU_SHADER_2D_UNIFORM_COLOR, "2D_UNIFORM_COLOR"},
{GPU_SHADER_2D_FLAT_COLOR, "2D_FLAT_COLOR"},
- {GPU_SHADER_2D_SMOOTH_COLOR, "2D_SMOOTH_COLOR"},
{GPU_SHADER_2D_IMAGE, "2D_IMAGE"},
- {GPU_SHADER_3D_UNIFORM_COLOR, "3D_UNIFORM_COLOR"},
+ {GPU_SHADER_2D_SMOOTH_COLOR, "2D_SMOOTH_COLOR"},
+ {GPU_SHADER_2D_UNIFORM_COLOR, "2D_UNIFORM_COLOR"},
{GPU_SHADER_3D_FLAT_COLOR, "3D_FLAT_COLOR"},
{GPU_SHADER_3D_SMOOTH_COLOR, "3D_SMOOTH_COLOR"},
+ {GPU_SHADER_3D_UNIFORM_COLOR, "3D_UNIFORM_COLOR"},
+ {GPU_SHADER_3D_POLYLINE_FLAT_COLOR, "3D_POLYLINE_FLAT_COLOR"},
+ {GPU_SHADER_3D_POLYLINE_SMOOTH_COLOR, "3D_POLYLINE_SMOOTH_COLOR"},
{GPU_SHADER_3D_POLYLINE_UNIFORM_COLOR, "3D_POLYLINE_UNIFORM_COLOR"},
{0, NULL},
};
@@ -704,14 +718,8 @@ PyDoc_STRVAR(pygpu_shader_from_builtin_doc,
" For more details, you can check the shader code with the\n"
" :func:`gpu.shader.code_from_builtin` function.\n"
"\n"
- " :param pygpu_shader_name: One of these builtin shader names:\n\n"
- " - ``2D_UNIFORM_COLOR``\n"
- " - ``2D_FLAT_COLOR``\n"
- " - ``2D_SMOOTH_COLOR``\n"
- " - ``2D_IMAGE``\n"
- " - ``3D_UNIFORM_COLOR``\n"
- " - ``3D_FLAT_COLOR``\n"
- " - ``3D_SMOOTH_COLOR``\n"
+ " :param pygpu_shader_name: One of these builtin shader names:\n"
+ "\n" PYDOC_BUILTIN_SHADER_LIST
" :type pygpu_shader_name: str\n"
" :return: Shader object corresponding to the given name.\n"
" :rtype: :class:`bpy.types.GPUShader`\n");
@@ -734,14 +742,8 @@ PyDoc_STRVAR(pygpu_shader_code_from_builtin_doc,
"\n"
" Exposes the internal shader code for query.\n"
"\n"
- " :param pygpu_shader_name: One of these builtin shader names:\n\n"
- " - ``2D_UNIFORM_COLOR``\n"
- " - ``2D_FLAT_COLOR``\n"
- " - ``2D_SMOOTH_COLOR``\n"
- " - ``2D_IMAGE``\n"
- " - ``3D_UNIFORM_COLOR``\n"
- " - ``3D_FLAT_COLOR``\n"
- " - ``3D_SMOOTH_COLOR``\n"
+ " :param pygpu_shader_name: One of these builtin shader names:\n"
+ "\n" PYDOC_BUILTIN_SHADER_LIST
" :type pygpu_shader_name: str\n"
" :return: Vertex, fragment and geometry shader codes.\n"
" :rtype: dict\n");
diff --git a/source/blender/python/intern/bpy.c b/source/blender/python/intern/bpy.c
index 30a61067c9e..0e0f431cb19 100644
--- a/source/blender/python/intern/bpy.c
+++ b/source/blender/python/intern/bpy.c
@@ -417,9 +417,6 @@ void BPy_init_modules(struct bContext *C)
PyDict_SetItemString(PyImport_GetModuleDict(), "_bpy", mod);
Py_DECREF(mod);
- /* run first, initializes rna types */
- BPY_rna_init();
-
/* needs to be first so bpy_types can run */
PyModule_AddObject(mod, "types", BPY_rna_types());
diff --git a/source/blender/python/intern/bpy_interface.c b/source/blender/python/intern/bpy_interface.c
index f91ba4d362c..1a308414bc3 100644
--- a/source/blender/python/intern/bpy_interface.c
+++ b/source/blender/python/intern/bpy_interface.c
@@ -155,7 +155,7 @@ void bpy_context_clear(bContext *UNUSED(C), const PyGILState_STATE *gilstate)
}
else if (py_call_level == 0) {
/* XXX: Calling classes currently won't store the context :\,
- * can't set NULL because of this. but this is very flakey still. */
+ * can't set NULL because of this. but this is very flaky still. */
#if 0
BPY_context_set(NULL);
#endif
@@ -502,7 +502,10 @@ void BPY_python_start(bContext *C, int argc, const char **argv)
}
#endif
- /* bpy.* and lets us import it */
+ /* Run first, initializes RNA types. */
+ BPY_rna_init();
+
+ /* Defines `bpy.*` and lets us import it. */
BPy_init_modules(C);
pyrna_alloc_types();
@@ -541,6 +544,8 @@ void BPY_python_end(void)
/* free other python data. */
pyrna_free_types();
+ BPY_rna_exit();
+
/* clear all python data from structs */
bpy_intern_string_exit();
@@ -650,7 +655,7 @@ void BPY_modules_load_user(bContext *C)
bpy_context_set(C, &gilstate);
for (text = bmain->texts.first; text; text = text->id.next) {
- if (text->flags & TXT_ISSCRIPT && BLI_path_extension_check(text->id.name + 2, ".py")) {
+ if (text->flags & TXT_ISSCRIPT) {
if (!(G.f & G_FLAG_SCRIPT_AUTOEXEC)) {
if (!(G.f & G_FLAG_SCRIPT_AUTOEXEC_FAIL_QUIET)) {
G.f |= G_FLAG_SCRIPT_AUTOEXEC_FAIL;
diff --git a/source/blender/python/intern/bpy_rna.c b/source/blender/python/intern/bpy_rna.c
index ec2e70ad262..ac1a7f68885 100644
--- a/source/blender/python/intern/bpy_rna.c
+++ b/source/blender/python/intern/bpy_rna.c
@@ -181,23 +181,13 @@ static PyMethodDef id_free_weakref_cb_def = {
/* Adds a reference to the list, remember to decref. */
static GHash *id_weakref_pool_get(ID *id)
{
- GHash *weakinfo_hash = NULL;
-
- if (id_weakref_pool) {
- weakinfo_hash = BLI_ghash_lookup(id_weakref_pool, (void *)id);
- }
- else {
- /* First time, allocate pool. */
- id_weakref_pool = BLI_ghash_ptr_new("rna_global_pool");
- weakinfo_hash = NULL;
- }
-
+ GHash *weakinfo_hash = BLI_ghash_lookup(id_weakref_pool, (void *)id);
if (weakinfo_hash == NULL) {
- /* We use a ghash as a set, we could use libHX's HXMAP_SINGULAR, but would be an extra dep. */
+ /* This could be a set, values are used to keep a reference back to the ID
+ * (all of them are the same). */
weakinfo_hash = BLI_ghash_ptr_new("rna_id");
BLI_ghash_insert(id_weakref_pool, id, weakinfo_hash);
}
-
return weakinfo_hash;
}
@@ -283,14 +273,6 @@ static void id_release_weakref_list(struct ID *id, GHash *weakinfo_hash)
BLI_ghash_remove(id_weakref_pool, (void *)id, NULL, NULL);
BLI_ghash_free(weakinfo_hash, NULL, NULL);
-
- if (BLI_ghash_len(id_weakref_pool) == 0) {
- BLI_ghash_free(id_weakref_pool, NULL, NULL);
- id_weakref_pool = NULL;
-# ifdef DEBUG_RNA_WEAKREF
- printf("id_release_weakref freeing pool\n");
-# endif
- }
}
static void id_release_weakref(struct ID *id)
@@ -310,7 +292,8 @@ void BPY_id_release(struct ID *id)
#endif
#ifdef USE_PYRNA_INVALIDATE_WEAKREF
- if (id_weakref_pool) {
+ /* Check for NULL since this may run before Python has been started. */
+ if (id_weakref_pool != NULL) {
PyGILState_STATE gilstate = PyGILState_Ensure();
id_release_weakref(id);
@@ -4492,7 +4475,7 @@ static PyObject *pyrna_struct_meta_idprop_getattro(PyObject *cls, PyObject *attr
if ((ret == NULL) /* || BPy_PropDeferred_CheckTypeExact(ret) */ ) {
StructRNA *srna = srna_from_self(cls, "StructRNA.__getattr__");
if (srna) {
- PropertyRNA *prop = RNA_struct_type_find_property(srna, PyUnicode_AsUTF8(attr));
+ PropertyRNA *prop = RNA_struct_type_find_property_no_base(srna, PyUnicode_AsUTF8(attr));
if (prop) {
PointerRNA tptr;
PyErr_Clear(); /* Clear error from tp_getattro. */
@@ -4514,7 +4497,7 @@ static int pyrna_struct_meta_idprop_setattro(PyObject *cls, PyObject *attr, PyOb
const char *attr_str = PyUnicode_AsUTF8(attr);
if (srna && !pyrna_write_check() &&
- (is_deferred_prop || RNA_struct_type_find_property(srna, attr_str))) {
+ (is_deferred_prop || RNA_struct_type_find_property_no_base(srna, attr_str))) {
PyErr_Format(PyExc_AttributeError,
"pyrna_struct_meta_idprop_setattro() "
"can't set in readonly state '%.200s.%S'",
@@ -7522,7 +7505,7 @@ static PyObject *pyrna_srna_Subtype(StructRNA *srna)
/* Newclass will now have 2 ref's, ???,
* probably 1 is internal since #Py_DECREF here segfaults. */
- /* PyC_ObSpit("new class ref", newclass); */
+ // PyC_ObSpit("new class ref", newclass);
if (newclass) {
/* srna owns one, and the other is owned by the caller. */
@@ -7776,6 +7759,32 @@ void BPY_rna_init(void)
return;
}
#endif
+
+#ifdef USE_PYRNA_INVALIDATE_WEAKREF
+ BLI_assert(id_weakref_pool == NULL);
+ id_weakref_pool = BLI_ghash_ptr_new("rna_global_pool");
+#endif
+}
+
+void BPY_rna_exit(void)
+{
+#ifdef USE_PYRNA_INVALIDATE_WEAKREF
+ /* This can help track down which kinds of data were not released.
+ * If they were in fact freed by Blender, printing their names
+ * will crash giving a useful error with address sanitizer. The likely cause
+ * for this list not being empty is a missing call to: #BKE_libblock_free_data_py. */
+ const int id_weakref_pool_len = BLI_ghash_len(id_weakref_pool);
+ if (id_weakref_pool_len != id_weakref_pool_len) {
+ printf("Found %d unreleased ID's\n", id_weakref_pool_len);
+ GHashIterator gh_iter;
+ GHASH_ITER (gh_iter, id_weakref_pool) {
+ ID *id = BLI_ghashIterator_getKey(&gh_iter);
+ printf("ID: %s\n", id->name);
+ }
+ }
+ BLI_ghash_free(id_weakref_pool, NULL, NULL);
+ id_weakref_pool = NULL;
+#endif
}
/* 'bpy.data' from Python. */
@@ -8681,6 +8690,8 @@ static int bpy_class_call(bContext *C, PointerRNA *ptr, FunctionRNA *func, Param
}
#ifdef USE_PEDANTIC_WRITE
+ /* Handle nested draw calls, see: T89253. */
+ const bool rna_disallow_writes_prev = rna_disallow_writes;
rna_disallow_writes = is_readonly ? true : false;
#endif
/* *** Main Caller *** */
@@ -8690,7 +8701,7 @@ static int bpy_class_call(bContext *C, PointerRNA *ptr, FunctionRNA *func, Param
/* *** Done Calling *** */
#ifdef USE_PEDANTIC_WRITE
- rna_disallow_writes = false;
+ rna_disallow_writes = rna_disallow_writes_prev;
#endif
RNA_parameter_list_end(&iter);
diff --git a/source/blender/python/intern/bpy_rna.h b/source/blender/python/intern/bpy_rna.h
index 24dbad53eb3..fd468bed470 100644
--- a/source/blender/python/intern/bpy_rna.h
+++ b/source/blender/python/intern/bpy_rna.h
@@ -181,6 +181,7 @@ StructRNA *srna_from_self(PyObject *self, const char *error_prefix);
StructRNA *pyrna_struct_as_srna(PyObject *self, const bool parent, const char *error_prefix);
void BPY_rna_init(void);
+void BPY_rna_exit(void);
PyObject *BPY_rna_module(void);
void BPY_update_rna_module(void);
// PyObject *BPY_rna_doc(void);
diff --git a/source/blender/python/intern/bpy_rna_array.c b/source/blender/python/intern/bpy_rna_array.c
index abbc332d89d..fcc796d4545 100644
--- a/source/blender/python/intern/bpy_rna_array.c
+++ b/source/blender/python/intern/bpy_rna_array.c
@@ -334,7 +334,7 @@ static int validate_array_length(PyObject *rvalue,
}
if (tot != len) {
- /* BLI_snprintf(error_str, error_str_size, "sequence must have length of %d", len); */
+ // BLI_snprintf(error_str, error_str_size, "sequence must have length of %d", len);
PyErr_Format(PyExc_ValueError,
"%s %.200s.%.200s, sequence must have %d items total, not %d",
error_prefix,
diff --git a/source/blender/python/intern/bpy_rna_id_collection.c b/source/blender/python/intern/bpy_rna_id_collection.c
index 1bb68babc3c..7bdb0e30410 100644
--- a/source/blender/python/intern/bpy_rna_id_collection.c
+++ b/source/blender/python/intern/bpy_rna_id_collection.c
@@ -227,7 +227,7 @@ static PyObject *bpy_user_map(PyObject *UNUSED(self), PyObject *args, PyObject *
}
if (!data_cb.is_subset &&
- /* We do not want to pre-add keys of flitered out types. */
+ /* We do not want to pre-add keys of filtered out types. */
(key_types_bitmap == NULL || id_check_type(id, key_types_bitmap)) &&
/* We do not want to pre-add keys when we have filter on value types,
* but not on key types. */
diff --git a/source/blender/python/intern/bpy_rna_operator.c b/source/blender/python/intern/bpy_rna_operator.c
index 490d9aa5212..d3ec54fc12d 100644
--- a/source/blender/python/intern/bpy_rna_operator.c
+++ b/source/blender/python/intern/bpy_rna_operator.c
@@ -91,7 +91,7 @@ static void pyop_poll_message_free_fn(bContext *UNUSED(C), void *user_data)
}
PyDoc_STRVAR(BPY_rna_operator_poll_message_set_doc,
- ".. method:: poll_message_set(message, ...)\n"
+ ".. method:: poll_message_set(message, *args)\n"
"\n"
" Set the message to show in the tool-tip when poll fails.\n"
"\n"
diff --git a/source/blender/python/mathutils/mathutils.c b/source/blender/python/mathutils/mathutils.c
index 5beca7bd71a..be7dae6871b 100644
--- a/source/blender/python/mathutils/mathutils.c
+++ b/source/blender/python/mathutils/mathutils.c
@@ -95,7 +95,11 @@ Py_hash_t mathutils_array_hash(const float *array, size_t array_len)
x = 0x345678UL;
i = 0;
while (--len >= 0) {
+#if PY_VERSION_HEX >= 0x30a0000 /* Version: 3.10. */
+ y = _Py_HashDouble(NULL, (double)(array[i++]));
+#else
y = _Py_HashDouble((double)(array[i++]));
+#endif
if (y == -1) {
return -1;
}
diff --git a/source/blender/python/mathutils/mathutils_Vector.c b/source/blender/python/mathutils/mathutils_Vector.c
index c2223b023ad..efcaa9b6a51 100644
--- a/source/blender/python/mathutils/mathutils_Vector.c
+++ b/source/blender/python/mathutils/mathutils_Vector.c
@@ -1926,7 +1926,7 @@ static PyObject *Vector_imatmul(PyObject *v1, PyObject *v2)
return NULL;
}
-/* divid: obj / obj */
+/* divide: obj / obj */
static PyObject *Vector_div(PyObject *v1, PyObject *v2)
{
float *vec = NULL, scalar;
@@ -2939,7 +2939,7 @@ static int row_vector_multiplication(float r_vec[MAX_DIMENSIONS],
memcpy(vec_cpy, vec->vec, vec_size * sizeof(float));
r_vec[3] = 1.0f;
- /* muliplication */
+ /* Multiplication. */
for (col = 0; col < mat->num_col; col++) {
double dot = 0.0;
for (row = 0; row < mat->num_row; row++) {
diff --git a/source/blender/python/mathutils/mathutils_geometry.c b/source/blender/python/mathutils/mathutils_geometry.c
index c73dea79aac..5868c76b28f 100644
--- a/source/blender/python/mathutils/mathutils_geometry.c
+++ b/source/blender/python/mathutils/mathutils_geometry.c
@@ -201,7 +201,7 @@ static PyObject *M_Geometry_intersect_line_line(PyObject *UNUSED(self), PyObject
}
if (result == 0) {
- /* collinear */
+ /* Collinear. */
Py_RETURN_NONE;
}
diff --git a/source/blender/render/intern/texture_pointdensity.c b/source/blender/render/intern/texture_pointdensity.c
index 31d5bf67f28..06dd570ce2c 100644
--- a/source/blender/render/intern/texture_pointdensity.c
+++ b/source/blender/render/intern/texture_pointdensity.c
@@ -494,10 +494,7 @@ static void free_pointdensity(PointDensity *pd)
pd->point_tree = NULL;
}
- if (pd->point_data) {
- MEM_freeN(pd->point_data);
- pd->point_data = NULL;
- }
+ MEM_SAFE_FREE(pd->point_data);
pd->totpoints = 0;
}
diff --git a/source/blender/render/intern/zbuf.c b/source/blender/render/intern/zbuf.c
index 242c8a199fb..726124871ee 100644
--- a/source/blender/render/intern/zbuf.c
+++ b/source/blender/render/intern/zbuf.c
@@ -56,13 +56,8 @@ void zbuf_alloc_span(ZSpan *zspan, int rectx, int recty)
void zbuf_free_span(ZSpan *zspan)
{
if (zspan) {
- if (zspan->span1) {
- MEM_freeN(zspan->span1);
- }
- if (zspan->span2) {
- MEM_freeN(zspan->span2);
- }
- zspan->span1 = zspan->span2 = NULL;
+ MEM_SAFE_FREE(zspan->span1);
+ MEM_SAFE_FREE(zspan->span2);
}
}
diff --git a/source/blender/sequencer/intern/effects.c b/source/blender/sequencer/intern/effects.c
index 7757271a2e5..3ca0555d9a5 100644
--- a/source/blender/sequencer/intern/effects.c
+++ b/source/blender/sequencer/intern/effects.c
@@ -2164,11 +2164,7 @@ static int num_inputs_wipe(void)
static void free_wipe_effect(Sequence *seq, const bool UNUSED(do_id_user))
{
- if (seq->effectdata) {
- MEM_freeN(seq->effectdata);
- }
-
- seq->effectdata = NULL;
+ MEM_SAFE_FREE(seq->effectdata);
}
static void copy_wipe_effect(Sequence *dst, Sequence *src, const int UNUSED(flag))
@@ -2382,10 +2378,7 @@ static int num_inputs_transform(void)
static void free_transform_effect(Sequence *seq, const bool UNUSED(do_id_user))
{
- if (seq->effectdata) {
- MEM_freeN(seq->effectdata);
- }
- seq->effectdata = NULL;
+ MEM_SAFE_FREE(seq->effectdata);
}
static void copy_transform_effect(Sequence *dst, Sequence *src, const int UNUSED(flag))
@@ -2723,11 +2716,7 @@ static int num_inputs_glow(void)
static void free_glow_effect(Sequence *seq, const bool UNUSED(do_id_user))
{
- if (seq->effectdata) {
- MEM_freeN(seq->effectdata);
- }
-
- seq->effectdata = NULL;
+ MEM_SAFE_FREE(seq->effectdata);
}
static void copy_glow_effect(Sequence *dst, Sequence *src, const int UNUSED(flag))
@@ -2853,11 +2842,7 @@ static int num_inputs_color(void)
static void free_solid_color(Sequence *seq, const bool UNUSED(do_id_user))
{
- if (seq->effectdata) {
- MEM_freeN(seq->effectdata);
- }
-
- seq->effectdata = NULL;
+ MEM_SAFE_FREE(seq->effectdata);
}
static void copy_solid_color(Sequence *dst, Sequence *src, const int UNUSED(flag))
@@ -3111,10 +3096,7 @@ static void free_speed_effect(Sequence *seq, const bool UNUSED(do_id_user))
if (v->frameMap) {
MEM_freeN(v->frameMap);
}
- if (seq->effectdata) {
- MEM_freeN(seq->effectdata);
- }
- seq->effectdata = NULL;
+ MEM_SAFE_FREE(seq->effectdata);
}
static void copy_speed_effect(Sequence *dst, Sequence *src, const int UNUSED(flag))
@@ -3394,11 +3376,7 @@ static int num_inputs_gaussian_blur(void)
static void free_gaussian_blur_effect(Sequence *seq, const bool UNUSED(do_id_user))
{
- if (seq->effectdata) {
- MEM_freeN(seq->effectdata);
- }
-
- seq->effectdata = NULL;
+ MEM_SAFE_FREE(seq->effectdata);
}
static void copy_gaussian_blur_effect(Sequence *dst, Sequence *src, const int UNUSED(flag))
@@ -4052,11 +4030,7 @@ static void copy_effect_default(Sequence *dst, Sequence *src, const int UNUSED(f
static void free_effect_default(Sequence *seq, const bool UNUSED(do_id_user))
{
- if (seq->effectdata) {
- MEM_freeN(seq->effectdata);
- }
-
- seq->effectdata = NULL;
+ MEM_SAFE_FREE(seq->effectdata);
}
static int early_out_noop(Sequence *UNUSED(seq), float UNUSED(facf0), float UNUSED(facf1))
diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h
index 02e8d42e0ff..3027df41e77 100644
--- a/source/blender/windowmanager/WM_api.h
+++ b/source/blender/windowmanager/WM_api.h
@@ -987,7 +987,7 @@ bool WM_xr_action_create(wmXrData *xr,
const char **subaction_paths,
struct wmOperatorType *ot,
struct IDProperty *op_properties,
- const char **haptic_name,
+ const char *haptic_name,
const int64_t *haptic_duration,
const float *haptic_frequency,
const float *haptic_amplitude,
@@ -1027,14 +1027,14 @@ 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 char **subaction_path,
+ const char *subaction_path,
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,
- const char **subaction_path);
+ const char *subaction_path);
/* wm_xr_actionmap.c */
XrActionMap *WM_xr_actionmap_new(struct wmXrRuntimeData *runtime,
diff --git a/source/blender/windowmanager/gizmo/intern/wm_gizmo_map.c b/source/blender/windowmanager/gizmo/intern/wm_gizmo_map.c
index 5ec26a7b208..b90e288776e 100644
--- a/source/blender/windowmanager/gizmo/intern/wm_gizmo_map.c
+++ b/source/blender/windowmanager/gizmo/intern/wm_gizmo_map.c
@@ -616,11 +616,7 @@ static int gizmo_find_intersected_3d_intern(wmGizmo **visible_gizmos,
const int viewport[4] = {0, 0, region->winx, region->winy};
float co_3d_origin[3];
- /* Avoid multiple calculations. */
- struct GPUMatrixUnproject_Precalc unproj_precalc;
- GPU_matrix_unproject_precalc(&unproj_precalc, rv3d->viewmat, rv3d->winmat, viewport);
-
- GPU_matrix_unproject_3fv_with_precalc(&unproj_precalc, co_screen, co_3d_origin);
+ GPU_matrix_unproject_3fv(co_screen, rv3d->viewinv, rv3d->winmat, viewport, co_3d_origin);
uint *buf_iter = buffer;
int hit_found = -1;
@@ -631,7 +627,7 @@ static int gizmo_find_intersected_3d_intern(wmGizmo **visible_gizmos,
wmGizmo *gz = visible_gizmos[buf_iter[3] >> 8];
float co_3d[3];
co_screen[2] = int_as_float(buf_iter[1]);
- GPU_matrix_unproject_3fv_with_precalc(&unproj_precalc, co_screen, co_3d);
+ GPU_matrix_unproject_3fv(co_screen, rv3d->viewinv, rv3d->winmat, viewport, co_3d_origin);
float select_bias = gz->select_bias;
if ((gz->flag & WM_GIZMO_DRAW_NO_SCALE) == 0) {
select_bias *= gz->scale_final;
diff --git a/source/blender/windowmanager/intern/wm.c b/source/blender/windowmanager/intern/wm.c
index 9657f8aa03c..e11ef52eb84 100644
--- a/source/blender/windowmanager/intern/wm.c
+++ b/source/blender/windowmanager/intern/wm.c
@@ -628,6 +628,7 @@ void wm_close_and_free_all(bContext *C, ListBase *wmlist)
wm_close_and_free(C, wm);
BLI_remlink(wmlist, wm);
BKE_libblock_free_data(&wm->id, true);
+ BKE_libblock_free_data_py(&wm->id);
MEM_freeN(wm);
}
}
diff --git a/source/blender/windowmanager/intern/wm_files.c b/source/blender/windowmanager/intern/wm_files.c
index 92f3eb67783..b53ad0ee927 100644
--- a/source/blender/windowmanager/intern/wm_files.c
+++ b/source/blender/windowmanager/intern/wm_files.c
@@ -596,19 +596,33 @@ static void wm_file_read_pre(bContext *C, bool use_data, bool UNUSED(use_userdef
}
/**
+ * Parameters for #wm_file_read_post, also used for deferred initialization.
+ */
+struct wmFileReadPost_Params {
+ uint use_data : 1;
+ uint use_userdef : 1;
+
+ uint is_startup_file : 1;
+ uint is_factory_startup : 1;
+ uint reset_app_template : 1;
+};
+
+/**
* Logic shared between #WM_file_read & #wm_homefile_read,
* updates to make after reading a file.
*/
-static void wm_file_read_post(bContext *C,
- const bool is_startup_file,
- const bool is_factory_startup,
- const bool use_data,
- const bool use_userdef,
- const bool reset_app_template)
+static void wm_file_read_post(bContext *C, const struct wmFileReadPost_Params *params)
{
- bool addons_loaded = false;
wmWindowManager *wm = CTX_wm_manager(C);
+ const bool use_data = params->use_data;
+ const bool use_userdef = params->use_userdef;
+ const bool is_startup_file = params->is_startup_file;
+ const bool is_factory_startup = params->is_factory_startup;
+ const bool reset_app_template = params->reset_app_template;
+
+ bool addons_loaded = false;
+
if (use_data) {
if (!G.background) {
/* remove windows which failed to be added via WM_check */
@@ -803,7 +817,7 @@ static void file_read_reports_finalize(BlendFileReadReport *bf_reports)
node_lib = node_lib->next) {
Library *library = node_lib->link;
BKE_reportf(
- bf_reports->reports, RPT_INFO, "Library %s needs overrides resync.", library->filepath);
+ bf_reports->reports, RPT_INFO, "Library %s needs overrides resync", library->filepath);
}
}
@@ -910,7 +924,14 @@ bool WM_file_read(bContext *C, const char *filepath, ReportList *reports)
wm_history_file_update();
}
- wm_file_read_post(C, false, false, use_data, use_userdef, false);
+ wm_file_read_post(C,
+ &(const struct wmFileReadPost_Params){
+ .use_data = use_data,
+ .use_userdef = use_userdef,
+ .is_startup_file = false,
+ .is_factory_startup = false,
+ .reset_app_template = false,
+ });
bf_reports.duration.whole = PIL_check_seconds_timer() - bf_reports.duration.whole;
file_read_reports_finalize(&bf_reports);
@@ -993,31 +1014,18 @@ const char *WM_init_state_app_template_get(void)
/**
* Called on startup, (context entirely filled with NULLs)
- * or called for 'New File' both startup.blend and userpref.blend are checked.
- *
- * \param use_factory_settings:
- * Ignore on-disk startup file, use bundled `datatoc_startup_blend` instead.
- * Used for "Restore Factory Settings".
- *
- * \param use_userdef: Load factory settings as well as startup file.
- * Disabled for "File New" we don't want to reload preferences.
- *
- * \param filepath_startup_override:
- * Optional path pointing to an alternative blend file (may be NULL).
+ * or called for 'New File' both `startup.blend` and `userpref.blend` are checked.
*
- * \param app_template_override:
- * Template to use instead of the template defined in user-preferences.
- * When not-null, this is written into the user preferences.
+ * \param r_params_file_read_post: Support postponed initialization,
+ * needed for initial startup when only some sub-systems have been initialized.
+ * When non-null, #wm_file_read_post doesn't run, instead it's arguments are stored
+ * in this return argument.
+ * The caller is responsible for calling #wm_homefile_read_post with this return argument.
*/
-void wm_homefile_read(bContext *C,
- ReportList *reports,
- bool use_factory_settings,
- bool use_empty_data,
- bool use_data,
- bool use_userdef,
- const char *filepath_startup_override,
- const char *app_template_override,
- bool *r_is_factory_startup)
+void wm_homefile_read_ex(bContext *C,
+ const struct wmHomeFileRead_Params *params_homefile,
+ ReportList *reports,
+ struct wmFileReadPost_Params **r_params_file_read_post)
{
#if 0 /* UNUSED, keep as this may be needed later & the comment below isn't self evident. */
/* Context does not always have valid main pointer here. */
@@ -1026,6 +1034,14 @@ void wm_homefile_read(bContext *C,
ListBase wmbase;
bool success = false;
+ /* May be enabled, when the user configuration doesn't exist. */
+ const bool use_data = params_homefile->use_data;
+ const bool use_userdef = params_homefile->use_userdef;
+ bool use_factory_settings = params_homefile->use_factory_settings;
+ const bool use_empty_data = params_homefile->use_empty_data;
+ const char *filepath_startup_override = params_homefile->filepath_startup_override;
+ const char *app_template_override = params_homefile->app_template_override;
+
bool filepath_startup_is_factory = true;
char filepath_startup[FILE_MAX];
char filepath_userdef[FILE_MAX];
@@ -1313,13 +1329,45 @@ void wm_homefile_read(bContext *C,
G.save_over = 0;
}
- wm_file_read_post(C, true, is_factory_startup, use_data, use_userdef, reset_app_template);
+ {
+ const struct wmFileReadPost_Params params_file_read_post = {
+ .use_data = use_data,
+ .use_userdef = use_userdef,
+ .is_startup_file = true,
+ .is_factory_startup = is_factory_startup,
+ .reset_app_template = reset_app_template,
+ };
+ if (r_params_file_read_post == NULL) {
+ wm_file_read_post(C, &params_file_read_post);
+ }
+ else {
+ *r_params_file_read_post = MEM_mallocN(sizeof(struct wmFileReadPost_Params), __func__);
+ **r_params_file_read_post = params_file_read_post;
- if (r_is_factory_startup) {
- *r_is_factory_startup = is_factory_startup;
+ /* Match #wm_file_read_post which leaves the window cleared too. */
+ CTX_wm_window_set(C, NULL);
+ }
}
}
+void wm_homefile_read(bContext *C,
+ const struct wmHomeFileRead_Params *params_homefile,
+ ReportList *reports)
+{
+ wm_homefile_read_ex(C, params_homefile, reports, NULL);
+}
+
+/**
+ * Special case, support deferred execution of #wm_file_read_post,
+ * Needed when loading for the first time to workaround order of initialization bug, see T89046.
+ */
+void wm_homefile_read_post(struct bContext *C,
+ const struct wmFileReadPost_Params *params_file_read_post)
+{
+ wm_file_read_post(C, params_file_read_post);
+ MEM_freeN((void *)params_file_read_post);
+}
+
/* -------------------------------------------------------------------- */
/** \name Blend-File History API
* \{ */
@@ -2087,14 +2135,15 @@ static int wm_userpref_read_exec(bContext *C, wmOperator *op)
UserDef U_backup = U;
wm_homefile_read(C,
- op->reports,
- use_factory_settings,
- false,
- use_data,
- use_userdef,
- NULL,
- WM_init_state_app_template_get(),
- NULL);
+ &(const struct wmHomeFileRead_Params){
+ .use_data = use_data,
+ .use_userdef = use_userdef,
+ .use_factory_settings = use_factory_settings,
+ .use_empty_data = false,
+ .filepath_startup_override = NULL,
+ .app_template_override = WM_init_state_app_template_get(),
+ },
+ op->reports);
wm_userpref_read_exceptions(&U, &U_backup);
SET_FLAG_FROM_TEST(G.f, use_factory_settings, G_FLAG_USERPREF_NO_SAVE_ON_EXIT);
@@ -2233,16 +2282,17 @@ static int wm_homefile_read_exec(bContext *C, wmOperator *op)
app_template = WM_init_state_app_template_get();
}
- bool use_data = true;
wm_homefile_read(C,
- op->reports,
- use_factory_settings,
- use_empty_data,
- use_data,
- use_userdef,
- filepath,
- app_template,
- NULL);
+ &(const struct wmHomeFileRead_Params){
+ .use_data = true,
+ .use_userdef = use_userdef,
+ .use_factory_settings = use_factory_settings,
+ .use_empty_data = use_empty_data,
+ .filepath_startup_override = filepath,
+ .app_template_override = app_template,
+ },
+ op->reports);
+
if (use_splash) {
WM_init_splash(C);
}
@@ -3443,7 +3493,7 @@ static uiBlock *block_create__close_file_dialog(struct bContext *C,
BLI_split_file_part(blendfile_pathpath, filename, sizeof(filename));
}
else {
- STRNCPY(filename, IFACE_("untitled.blend"));
+ STRNCPY(filename, "untitled.blend");
}
uiItemL(layout, filename, ICON_NONE);
diff --git a/source/blender/windowmanager/intern/wm_files_link.c b/source/blender/windowmanager/intern/wm_files_link.c
index fec5a516688..cdcb6c5163f 100644
--- a/source/blender/windowmanager/intern/wm_files_link.c
+++ b/source/blender/windowmanager/intern/wm_files_link.c
@@ -485,11 +485,11 @@ static int wm_link_append_exec(bContext *C, wmOperator *op)
}
/* XXX We'd need re-entrant locking on Main for this to work... */
- /* BKE_main_lock(bmain); */
+ // BKE_main_lock(bmain);
wm_link_do(lapp_data, op->reports, bmain, scene, view_layer, CTX_wm_view3d(C));
- /* BKE_main_unlock(bmain); */
+ // BKE_main_unlock(bmain);
/* mark all library linked objects to be updated */
BKE_main_lib_objects_recalc_all(bmain);
@@ -831,7 +831,7 @@ static void lib_relocate_do_remap(Main *bmain,
}
}
-static void lib_relocate_do(Main *bmain,
+static void lib_relocate_do(bContext *C,
Library *library,
WMLinkAppendData *lapp_data,
ReportList *reports,
@@ -843,6 +843,10 @@ static void lib_relocate_do(Main *bmain,
LinkNode *itemlink;
int item_idx;
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+
/* Remove all IDs to be reloaded from Main. */
lba_idx = set_listbasepointers(bmain, lbarray);
while (lba_idx--) {
@@ -990,21 +994,31 @@ static void lib_relocate_do(Main *bmain,
}
}
- /* Update overrides of reloaded linked data-blocks.
- * Note that this will not necessarily fully update the override, it might need to be manually
- * 're-generated' depending on changes in linked data. */
+ /* Update overrides of reloaded linked data-blocks. */
ID *id;
FOREACH_MAIN_ID_BEGIN (bmain, id) {
if (ID_IS_LINKED(id) || !ID_IS_OVERRIDE_LIBRARY_REAL(id) ||
(id->tag & LIB_TAG_PRE_EXISTING) == 0) {
continue;
}
- if (id->override_library->reference->lib == library) {
+ if ((id->override_library->reference->tag & LIB_TAG_PRE_EXISTING) == 0) {
BKE_lib_override_library_update(bmain, id);
}
}
FOREACH_MAIN_ID_END;
+ /* Resync overrides if needed. */
+ if (!USER_EXPERIMENTAL_TEST(&U, no_override_auto_resync)) {
+ BKE_lib_override_library_main_resync(bmain,
+ scene,
+ view_layer,
+ &(struct BlendFileReadReport){
+ .reports = reports,
+ });
+ /* We need to rebuild some of the deleted override rules (for UI feedback purpose). */
+ BKE_lib_override_library_main_operations_create(bmain, true);
+ }
+
BKE_main_collection_sync(bmain);
BKE_main_lib_objects_recalc_all(bmain);
@@ -1039,7 +1053,7 @@ void WM_lib_reload(Library *lib, bContext *C, ReportList *reports)
wm_link_append_data_library_add(lapp_data, lib->filepath_abs);
- lib_relocate_do(CTX_data_main(C), lib, lapp_data, reports, true);
+ lib_relocate_do(C, lib, lapp_data, reports, true);
wm_link_append_data_free(lapp_data);
@@ -1162,7 +1176,7 @@ static int wm_lib_relocate_exec_do(bContext *C, wmOperator *op, bool do_reload)
lapp_data->flag |= BLO_LIBLINK_USE_PLACEHOLDERS | BLO_LIBLINK_FORCE_INDIRECT;
}
- lib_relocate_do(bmain, lib, lapp_data, op->reports, do_reload);
+ lib_relocate_do(C, lib, lapp_data, op->reports, do_reload);
wm_link_append_data_free(lapp_data);
diff --git a/source/blender/windowmanager/intern/wm_init_exit.c b/source/blender/windowmanager/intern/wm_init_exit.c
index d7ea47fc625..a8d2e000108 100644
--- a/source/blender/windowmanager/intern/wm_init_exit.c
+++ b/source/blender/windowmanager/intern/wm_init_exit.c
@@ -222,7 +222,10 @@ static void sound_jack_sync_callback(Main *bmain, int mode, double time)
}
}
-/* only called once, for startup */
+/**
+ * Initialize Blender and load the startup file & preferences
+ * (only called once).
+ */
void WM_init(bContext *C, int argc, const char **argv)
{
@@ -248,24 +251,22 @@ void WM_init(bContext *C, int argc, const char **argv)
ED_undosys_type_init();
- BKE_library_callback_free_notifier_reference_set(
- WM_main_remove_notifier_reference); /* lib_id.c */
- BKE_region_callback_free_gizmomap_set(wm_gizmomap_remove); /* screen.c */
+ BKE_library_callback_free_notifier_reference_set(WM_main_remove_notifier_reference);
+ BKE_region_callback_free_gizmomap_set(wm_gizmomap_remove);
BKE_region_callback_refresh_tag_gizmomap_set(WM_gizmomap_tag_refresh);
- BKE_library_callback_remap_editor_id_reference_set(
- WM_main_remap_editor_id_reference); /* lib_id.c */
- BKE_spacedata_callback_id_remap_set(ED_spacedata_id_remap); /* screen.c */
+ BKE_library_callback_remap_editor_id_reference_set(WM_main_remap_editor_id_reference);
+ BKE_spacedata_callback_id_remap_set(ED_spacedata_id_remap);
DEG_editors_set_update_cb(ED_render_id_flush_update, ED_render_scene_update);
- ED_spacetypes_init(); /* editors/space_api/spacetype.c */
+ ED_spacetypes_init();
ED_node_init_butfuncs();
BLF_init();
BLT_lang_init();
- /* Must call first before doing any '.blend' file reading,
- * since versioning code may create new IDs... See T57066. */
+ /* Must call first before doing any `.blend` file reading,
+ * since versioning code may create new IDs. See T57066. */
BLT_lang_set(NULL);
/* Init icons before reading .blend files for preview icons, which can
@@ -273,37 +274,57 @@ void WM_init(bContext *C, int argc, const char **argv)
* for scripts that do background processing with preview icons. */
BKE_icons_init(BIFICONID_LAST);
- /* reports can't be initialized before the wm,
+ /* Reports can't be initialized before the window-manager,
* but keep before file reading, since that may report errors */
wm_init_reports(C);
WM_msgbus_types_init();
- /* get the default database, plus a wm */
- bool is_factory_startup = true;
- const bool use_data = true;
- const bool use_userdef = true;
-
/* Studio-lights needs to be init before we read the home-file,
* otherwise the versioning cannot find the default studio-light. */
BKE_studiolight_init();
BLI_assert((G.fileflags & G_FILE_NO_UI) == 0);
- wm_homefile_read(C,
- NULL,
- G.factory_startup,
- false,
- use_data,
- use_userdef,
- NULL,
- WM_init_state_app_template_get(),
- &is_factory_startup);
-
- /* Call again to set from userpreferences... */
+ /**
+ * NOTE(@campbellbarton): Startup file and order of initialization.
+ *
+ * Loading #BLENDER_STARTUP_FILE, #BLENDER_USERPREF_FILE, starting Python and other sub-systems,
+ * have inter-dependencies, for example.
+ *
+ * - Some sub-systems depend on the preferences (initializing icons depend on the theme).
+ * - Add-ons depends on the preferences to know what has been enabled.
+ * - Add-ons depends on the window-manger to register their key-maps.
+ * - Evaluating the startup file depends on Python for animation-drivers (see T89046).
+ * - Starting Python depends on the startup file so key-maps can be added in the window-manger.
+ *
+ * Loading preferences early, then application subsystems and finally the startup data would
+ * simplify things if it weren't for key-maps being part of the window-manager
+ * which is blend file data.
+ * Creating a dummy window-manager early, or moving the key-maps into the preferences
+ * would resolve this and may be worth looking into long-term, see: D12184 for details.
+ */
+ struct wmFileReadPost_Params *params_file_read_post = NULL;
+ wm_homefile_read_ex(C,
+ &(const struct wmHomeFileRead_Params){
+ .use_data = true,
+ .use_userdef = true,
+ .use_factory_settings = G.factory_startup,
+ .use_empty_data = false,
+ .filepath_startup_override = NULL,
+ .app_template_override = WM_init_state_app_template_get(),
+ },
+ NULL,
+ &params_file_read_post);
+
+ /* NOTE: leave `G_MAIN->name` set to an empty string since this
+ * matches behavior after loading a new file. */
+ BLI_assert(G_MAIN->name[0] == '\0');
+
+ /* Call again to set from preferences. */
BLT_lang_set(NULL);
- /* For fsMenu. Called here so can include user preference paths if needed. */
+ /* For file-system. Called here so can include user preference paths if needed. */
ED_file_init();
/* That one is generated on demand, we need to be sure it's clear on init. */
@@ -312,12 +333,13 @@ void WM_init(bContext *C, int argc, const char **argv)
if (!G.background) {
#ifdef WITH_INPUT_NDOF
- /* sets 3D mouse deadzone */
+ /* Sets 3D mouse dead-zone. */
WM_ndof_deadzone_set(U.ndof_deadzone);
#endif
WM_init_opengl();
if (!WM_platform_support_perform_checks()) {
+ /* No attempt to avoid memory leaks here. */
exit(-1);
}
@@ -328,20 +350,11 @@ void WM_init(bContext *C, int argc, const char **argv)
ED_spacemacros_init();
- /* 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. */
-
#ifdef WITH_PYTHON
BPY_python_start(C, argc, argv);
BPY_python_reset(C);
#else
- (void)argc; /* unused */
- (void)argv; /* unused */
+ UNUSED_VARS(argc, argv);
#endif
if (!G.background) {
@@ -358,14 +371,6 @@ void WM_init(bContext *C, int argc, const char **argv)
wm_history_file_read();
- /* allow a path of "", this is what happens when making a new file */
-#if 0
- if (BKE_main_blendfile_path_from_global()[0] == '\0') {
- BLI_join_dirfile(
- G_MAIN->name, sizeof(G_MAIN->name), BKE_appdir_folder_default(), "untitled.blend");
- }
-#endif
-
BLI_strncpy(G.lib, BKE_main_blendfile_path_from_global(), sizeof(G.lib));
#ifdef WITH_COMPOSITOR
@@ -375,30 +380,7 @@ void WM_init(bContext *C, int argc, const char **argv)
}
#endif
- {
- Main *bmain = CTX_data_main(C);
- /* NOTE: logic here is from wm_file_read_post,
- * call functions that depend on Python being initialized. */
-
- /* normally 'wm_homefile_read' will do this,
- * however python is not initialized when called from this function.
- *
- * unlikely any handlers are set but its possible,
- * note that recovering the last session does its own callbacks. */
- CTX_wm_window_set(C, CTX_wm_manager(C)->windows.first);
-
- BKE_callback_exec_null(bmain, BKE_CB_EVT_VERSION_UPDATE);
- BKE_callback_exec_null(bmain, BKE_CB_EVT_LOAD_POST);
- if (is_factory_startup) {
- BKE_callback_exec_null(bmain, BKE_CB_EVT_LOAD_FACTORY_STARTUP_POST);
- }
-
- wm_file_read_report(C, bmain);
-
- if (!G.background) {
- CTX_wm_window_set(C, NULL);
- }
- }
+ wm_homefile_read_post(C, params_file_read_post);
}
void WM_init_splash(bContext *C)
diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c
index 8a8ea18cc43..50db8e73844 100644
--- a/source/blender/windowmanager/intern/wm_operators.c
+++ b/source/blender/windowmanager/intern/wm_operators.c
@@ -2766,10 +2766,7 @@ static void radial_control_cancel(bContext *C, wmOperator *op)
wmWindowManager *wm = CTX_wm_manager(C);
ScrArea *area = CTX_wm_area(C);
- if (rc->dial) {
- MEM_freeN(rc->dial);
- rc->dial = NULL;
- }
+ MEM_SAFE_FREE(rc->dial);
ED_area_status_text(area, NULL);
@@ -2959,10 +2956,7 @@ static int radial_control_modal(bContext *C, wmOperator *op, const wmEvent *even
if (event->val == KM_RELEASE) {
rc->slow_mode = false;
handled = true;
- if (rc->dial) {
- MEM_freeN(rc->dial);
- rc->dial = NULL;
- }
+ MEM_SAFE_FREE(rc->dial);
}
break;
}
diff --git a/source/blender/windowmanager/wm_files.h b/source/blender/windowmanager/wm_files.h
index c7fe07cad7f..2fa5a68829e 100644
--- a/source/blender/windowmanager/wm_files.h
+++ b/source/blender/windowmanager/wm_files.h
@@ -24,6 +24,7 @@
#pragma once
struct Main;
+struct wmFileReadPost_Params;
struct wmGenericCallback;
struct wmOperatorType;
@@ -33,15 +34,45 @@ extern "C" {
/* wm_files.c */
void wm_history_file_read(void);
+
+struct wmHomeFileRead_Params {
+ /** Load data, disable when only loading user preferences. */
+ unsigned int use_data : 1;
+ /** Load factory settings as well as startup file (disabled for "File New"). */
+ unsigned int use_userdef : 1;
+
+ /**
+ * Ignore on-disk startup file, use bundled `datatoc_startup_blend` instead.
+ * Used for "Restore Factory Settings".
+ */
+ unsigned int use_factory_settings : 1;
+ /**
+ * Load the startup file without any data-blocks.
+ * Useful for automated content generation, so the file starts without data.
+ */
+ unsigned int use_empty_data : 1;
+ /**
+ * Optional path pointing to an alternative blend file (may be NULL).
+ */
+ const char *filepath_startup_override;
+ /**
+ * Template to use instead of the template defined in user-preferences.
+ * When not-null, this is written into the user preferences.
+ */
+ const char *app_template_override;
+};
+
+void wm_homefile_read_ex(struct bContext *C,
+ const struct wmHomeFileRead_Params *params_homefile,
+ struct ReportList *reports,
+ struct wmFileReadPost_Params **r_params_file_read_post);
void wm_homefile_read(struct bContext *C,
- struct ReportList *reports,
- bool use_factory_settings,
- bool use_empty_data,
- bool use_data,
- bool use_userdef,
- const char *filepath_startup_override,
- const char *app_template_override,
- bool *r_is_factory_startup);
+ const struct wmHomeFileRead_Params *params_homefile,
+ struct ReportList *reports);
+
+void wm_homefile_read_post(struct bContext *C,
+ const struct wmFileReadPost_Params *params_file_read_post);
+
void wm_file_read_report(bContext *C, struct Main *bmain);
void wm_close_file_dialog(bContext *C, struct wmGenericCallback *post_action);
diff --git a/source/blender/windowmanager/xr/intern/wm_xr.c b/source/blender/windowmanager/xr/intern/wm_xr.c
index 716a0936a24..3091a3a19f1 100644
--- a/source/blender/windowmanager/xr/intern/wm_xr.c
+++ b/source/blender/windowmanager/xr/intern/wm_xr.c
@@ -149,6 +149,7 @@ bool wm_xr_events_handle(wmWindowManager *wm)
wmXrRuntimeData *wm_xr_runtime_data_create(void)
{
wmXrRuntimeData *runtime = MEM_callocN(sizeof(*runtime), __func__);
+ runtime->actactionmap = runtime->selactionmap = -1;
return runtime;
}
diff --git a/source/blender/windowmanager/xr/intern/wm_xr_action.c b/source/blender/windowmanager/xr/intern/wm_xr_action.c
index 2712fde51a8..ba347c537ec 100644
--- a/source/blender/windowmanager/xr/intern/wm_xr_action.c
+++ b/source/blender/windowmanager/xr/intern/wm_xr_action.c
@@ -74,7 +74,7 @@ static wmXrAction *action_create(const char *action_name,
const char **subaction_paths,
wmOperatorType *ot,
IDProperty *op_properties,
- const char **haptic_name,
+ const char *haptic_name,
const int64_t *haptic_duration,
const float *haptic_frequency,
const float *haptic_amplitude,
@@ -134,8 +134,8 @@ static wmXrAction *action_create(const char *action_name,
if (haptic_name) {
BLI_assert(is_button_action);
- action->haptic_name = MEM_mallocN(strlen(*haptic_name) + 1, "XrAction_HapticName");
- strcpy(action->haptic_name, *haptic_name);
+ action->haptic_name = MEM_mallocN(strlen(haptic_name) + 1, "XrAction_HapticName");
+ strcpy(action->haptic_name, haptic_name);
action->haptic_duration = *haptic_duration;
action->haptic_frequency = *haptic_frequency;
action->haptic_amplitude = *haptic_amplitude;
@@ -232,7 +232,7 @@ bool WM_xr_action_create(wmXrData *xr,
const char **subaction_paths,
wmOperatorType *ot,
IDProperty *op_properties,
- const char **haptic_name,
+ const char *haptic_name,
const int64_t *haptic_duration,
const float *haptic_frequency,
const float *haptic_amplitude,
@@ -502,7 +502,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 char **subaction_path,
+ const char *subaction_path,
const int64_t *duration,
const float *frequency,
const float *amplitude)
@@ -521,7 +521,7 @@ bool WM_xr_haptic_action_apply(wmXrData *xr,
void WM_xr_haptic_action_stop(wmXrData *xr,
const char *action_set_name,
const char *action_name,
- const char **subaction_path)
+ const char *subaction_path)
{
GHOST_XrStopHapticAction(xr->runtime->context, action_set_name, action_name, subaction_path);
}
diff --git a/source/blender/windowmanager/xr/intern/wm_xr_actionmap.c b/source/blender/windowmanager/xr/intern/wm_xr_actionmap.c
index 7673f2aa212..f9ad34b5a9b 100644
--- a/source/blender/windowmanager/xr/intern/wm_xr_actionmap.c
+++ b/source/blender/windowmanager/xr/intern/wm_xr_actionmap.c
@@ -256,6 +256,7 @@ XrActionMapItem *WM_xr_actionmap_item_new(XrActionMap *actionmap,
if (ami_prev) {
WM_xr_actionmap_item_ensure_unique(actionmap, ami);
}
+ ami->selbinding = -1;
BLI_addtail(&actionmap->items, ami);
@@ -398,6 +399,7 @@ XrActionMap *WM_xr_actionmap_new(wmXrRuntimeData *runtime, const char *name, boo
if (am_prev) {
WM_xr_actionmap_ensure_unique(runtime, am);
}
+ am->selitem = -1;
BLI_addtail(&runtime->actionmaps, am);
diff --git a/source/blender/windowmanager/xr/intern/wm_xr_intern.h b/source/blender/windowmanager/xr/intern/wm_xr_intern.h
index 4b1605d0f68..4d4df43f796 100644
--- a/source/blender/windowmanager/xr/intern/wm_xr_intern.h
+++ b/source/blender/windowmanager/xr/intern/wm_xr_intern.h
@@ -134,7 +134,7 @@ typedef struct wmXrAction {
eXrAxisFlag *axis_flags;
/** The currently active subaction path (if any) for modal actions. */
- char **active_modal_path;
+ const char *active_modal_path;
/** Operator to be called on XR events. */
struct wmOperatorType *ot;
@@ -155,7 +155,7 @@ typedef struct wmXrAction {
typedef struct wmXrHapticAction {
struct wmXrHapticAction *next, *prev;
wmXrAction *action;
- const char **subaction_path;
+ const char *subaction_path;
int64_t time_start;
} wmXrHapticAction;
diff --git a/source/creator/CMakeLists.txt b/source/creator/CMakeLists.txt
index e928be571a2..47fb2642da1 100644
--- a/source/creator/CMakeLists.txt
+++ b/source/creator/CMakeLists.txt
@@ -345,13 +345,10 @@ elseif(APPLE)
set(TARGETDIR_VER "${PYTHON_LIBPATH}/Resources/${BLENDER_VERSION}")
set(INSTALL_BPY_TO_SITE_PACKAGES ON)
endif()
- # Dylibs folder for bpy.so.
- set(MAC_BLENDER_TARGET_DYLIBS_DIR "${TARGETDIR_VER}/lib")
else()
set(TARGETDIR_VER Blender.app/Contents/Resources/${BLENDER_VERSION})
- # Dylibs folder for Blender executable. @executable_path is an rpath.
- set(MAC_BLENDER_TARGET_DYLIBS_DIR "$<TARGET_FILE_DIR:blender>")
endif()
+ set(MAC_BLENDER_TARGET_DYLIBS_DIR "${TARGETDIR_VER}/lib")
# Skip relinking on cpack / install
set_target_properties(blender PROPERTIES BUILD_WITH_INSTALL_RPATH true)
endif()
diff --git a/source/creator/creator_args.c b/source/creator/creator_args.c
index 0f450624691..85ba4eca307 100644
--- a/source/creator/creator_args.c
+++ b/source/creator/creator_args.c
@@ -994,6 +994,9 @@ static const char arg_handle_debug_mode_generic_set_doc_depsgraph_no_threads[] =
static const char arg_handle_debug_mode_generic_set_doc_depsgraph_pretty[] =
"\n\t"
"Enable colors for dependency graph debug messages.";
+static const char arg_handle_debug_mode_generic_set_doc_depsgraph_uuid[] =
+ "\n\t"
+ "Verify validness of session-wide identifiers assigned to ID datablocks.";
static const char arg_handle_debug_mode_generic_set_doc_gpu_force_workarounds[] =
"\n\t"
"Enable workarounds for typical GPU issues and disable all GPU extensions.";
@@ -2197,7 +2200,7 @@ void main_args_setup(bContext *C, bArgs *ba)
BLI_args_add(ba,
NULL,
"--debug-depsgraph-uuid",
- CB_EX(arg_handle_debug_mode_generic_set, depsgraph_build),
+ CB_EX(arg_handle_debug_mode_generic_set, depsgraph_uuid),
(void *)G_DEBUG_DEPSGRAPH_UUID);
BLI_args_add(ba,
NULL,