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:
authorKévin Dietrich <kevin.dietrich@mailoo.org>2022-03-13 20:05:40 +0300
committerKévin Dietrich <kevin.dietrich@mailoo.org>2022-03-13 20:05:40 +0300
commit5a0efc9c8b5ad991109c97d52d476d8c071a78ac (patch)
treee5c8290bc613ef8eea923d0983cb51512c4b1ce7
parent1ca7821b15f3883121552495436142814c73fbb7 (diff)
parent91dbc28363e5450f241eb9696aaca29075c01d20 (diff)
Merge branch 'master' into temp-abc-features
-rw-r--r--CMakeLists.txt2
-rw-r--r--GNUmakefile2
-rw-r--r--build_files/cmake/platform/platform_unix.cmake2
-rw-r--r--build_files/windows/find_dependencies.cmd2
-rw-r--r--intern/cycles/blender/addon/ui.py9
-rw-r--r--intern/cycles/blender/object.cpp4
-rw-r--r--intern/cycles/device/optix/device_impl.cpp213
-rw-r--r--intern/cycles/device/queue.h2
-rw-r--r--intern/cycles/integrator/denoiser.cpp3
-rw-r--r--intern/cycles/kernel/bvh/shadow_all.h73
-rw-r--r--intern/cycles/kernel/device/gpu/image.h8
-rw-r--r--intern/cycles/kernel/geom/object.h10
-rw-r--r--intern/cycles/kernel/osl/services.cpp5
-rw-r--r--intern/cycles/kernel/osl/services.h1
-rw-r--r--intern/cycles/kernel/osl/shaders/node_object_info.osl2
-rw-r--r--intern/cycles/kernel/svm/geometry.h3
-rw-r--r--intern/cycles/kernel/svm/types.h1
-rw-r--r--intern/cycles/kernel/types.h2
-rw-r--r--intern/cycles/scene/alembic_read.cpp10
-rw-r--r--intern/cycles/scene/mesh.cpp2
-rw-r--r--intern/cycles/scene/object.cpp2
-rw-r--r--intern/cycles/scene/object.h1
-rw-r--r--intern/cycles/scene/shader_nodes.cpp6
-rw-r--r--intern/ghost/intern/GHOST_Wintab.cpp4
-rw-r--r--intern/iksolver/intern/IK_QJacobian.cpp2
-rw-r--r--intern/itasc/Cache.hpp2
-rw-r--r--release/freedesktop/org.blender.Blender.appdata.xml21
-rw-r--r--release/license/THIRD-PARTY-LICENSES.txt12
-rw-r--r--release/scripts/modules/bpy_types.py9
-rw-r--r--release/scripts/presets/keyconfig/keymap_data/blender_default.py55
-rw-r--r--release/scripts/presets/keyconfig/keymap_data/industry_compatible_data.py2
-rw-r--r--release/scripts/startup/bl_operators/clip.py4
-rw-r--r--release/scripts/startup/bl_ui/properties_data_curve.py13
-rw-r--r--release/scripts/startup/bl_ui/properties_data_curves.py2
-rw-r--r--release/scripts/startup/bl_ui/properties_render.py22
-rw-r--r--release/scripts/startup/bl_ui/space_image.py2
-rw-r--r--release/scripts/startup/bl_ui/space_node.py2
-rw-r--r--source/blender/blenkernel/BKE_blender_version.h2
-rw-r--r--source/blender/blenkernel/BKE_callbacks.h2
-rw-r--r--source/blender/blenkernel/BKE_curve.h8
-rw-r--r--source/blender/blenkernel/BKE_curves.hh5
-rw-r--r--source/blender/blenkernel/BKE_customdata.h2
-rw-r--r--source/blender/blenkernel/BKE_geometry_set.hh6
-rw-r--r--source/blender/blenkernel/BKE_image.h4
-rw-r--r--source/blender/blenkernel/BKE_image_partial_update.hh2
-rw-r--r--source/blender/blenkernel/BKE_lib_id.h14
-rw-r--r--source/blender/blenkernel/BKE_spline.hh6
-rw-r--r--source/blender/blenkernel/BKE_text.h10
-rw-r--r--source/blender/blenkernel/CMakeLists.txt3
-rw-r--r--source/blender/blenkernel/intern/DerivedMesh.cc2
-rw-r--r--source/blender/blenkernel/intern/armature_test.cc2
-rw-r--r--source/blender/blenkernel/intern/blendfile_link_append.c2
-rw-r--r--source/blender/blenkernel/intern/constraint.c2
-rw-r--r--source/blender/blenkernel/intern/curve.cc110
-rw-r--r--source/blender/blenkernel/intern/curve_eval.cc17
-rw-r--r--source/blender/blenkernel/intern/curves_geometry.cc253
-rw-r--r--source/blender/blenkernel/intern/curves_geometry_test.cc66
-rw-r--r--source/blender/blenkernel/intern/customdata.cc17
-rw-r--r--source/blender/blenkernel/intern/data_transfer.c4
-rw-r--r--source/blender/blenkernel/intern/displist.cc2
-rw-r--r--source/blender/blenkernel/intern/dynamicpaint.c2
-rw-r--r--source/blender/blenkernel/intern/fluid.c13
-rw-r--r--source/blender/blenkernel/intern/geometry_component_curves.cc13
-rw-r--r--source/blender/blenkernel/intern/geometry_component_mesh.cc5
-rw-r--r--source/blender/blenkernel/intern/geometry_set.cc2
-rw-r--r--source/blender/blenkernel/intern/gpencil.c21
-rw-r--r--source/blender/blenkernel/intern/gpencil_curve.c2
-rw-r--r--source/blender/blenkernel/intern/gpencil_modifier.c114
-rw-r--r--source/blender/blenkernel/intern/idprop.c3
-rw-r--r--source/blender/blenkernel/intern/image.cc (renamed from source/blender/blenkernel/intern/image.c)1116
-rw-r--r--source/blender/blenkernel/intern/image_gpu.cc2
-rw-r--r--source/blender/blenkernel/intern/key.c2
-rw-r--r--source/blender/blenkernel/intern/lib_id.c6
-rw-r--r--source/blender/blenkernel/intern/lib_override.c11
-rw-r--r--source/blender/blenkernel/intern/linestyle.c18
-rw-r--r--source/blender/blenkernel/intern/mask.c6
-rw-r--r--source/blender/blenkernel/intern/mesh.cc11
-rw-r--r--source/blender/blenkernel/intern/movieclip.c2
-rw-r--r--source/blender/blenkernel/intern/node.cc4
-rw-r--r--source/blender/blenkernel/intern/paint.c2
-rw-r--r--source/blender/blenkernel/intern/particle_child.c2
-rw-r--r--source/blender/blenkernel/intern/pointcache.c3
-rw-r--r--source/blender/blenkernel/intern/screen.c2
-rw-r--r--source/blender/blenkernel/intern/sound.c17
-rw-r--r--source/blender/blenkernel/intern/spline_bezier.cc2
-rw-r--r--source/blender/blenkernel/intern/spline_nurbs.cc50
-rw-r--r--source/blender/blenkernel/intern/text.c82
-rw-r--r--source/blender/blenkernel/intern/tracking.c2
-rw-r--r--source/blender/blenkernel/intern/writeffmpeg.c3
-rw-r--r--source/blender/blenlib/BLI_fileops.h6
-rw-r--r--source/blender/blenlib/BLI_memiter.h7
-rw-r--r--source/blender/blenlib/intern/math_base_inline.c8
-rw-r--r--source/blender/blenlib/intern/math_vector.c4
-rw-r--r--source/blender/blenlib/intern/path_util.c4
-rw-r--r--source/blender/blenlib/tests/BLI_task_test.cc2
-rw-r--r--source/blender/blenloader/BLO_read_write.h4
-rw-r--r--source/blender/blenloader/intern/readfile.c16
-rw-r--r--source/blender/blenloader/intern/versioning_260.c2
-rw-r--r--source/blender/blenloader/intern/versioning_280.c8
-rw-r--r--source/blender/blenloader/intern/versioning_290.c6
-rw-r--r--source/blender/blenloader/intern/versioning_300.c58
-rw-r--r--source/blender/blenloader/intern/versioning_cycles.c12
-rw-r--r--source/blender/blenloader/intern/versioning_legacy.c7
-rw-r--r--source/blender/bmesh/intern/bmesh_mesh_convert.cc28
-rw-r--r--source/blender/bmesh/intern/bmesh_mesh_convert.h5
-rw-r--r--source/blender/bmesh/operators/bmo_fill_edgeloop.c2
-rw-r--r--source/blender/bmesh/tools/bmesh_bevel.c6
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_nodes.cc2
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_relations.cc8
-rw-r--r--source/blender/depsgraph/intern/depsgraph_tag.cc4
-rw-r--r--source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc11
-rw-r--r--source/blender/draw/engines/eevee/eevee_depth_of_field.c2
-rw-r--r--source/blender/draw/engines/eevee/eevee_lightprobes.c2
-rw-r--r--source/blender/draw/engines/eevee/eevee_lookdev.c2
-rw-r--r--source/blender/draw/engines/eevee/shaders/effect_dof_bokeh_frag.glsl2
-rw-r--r--source/blender/draw/engines/eevee/shaders/effect_dof_gather_frag.glsl2
-rw-r--r--source/blender/draw/engines/eevee/shaders/effect_dof_scatter_vert.glsl2
-rw-r--r--source/blender/draw/engines/eevee/shaders/effect_minmaxz_frag.glsl2
-rw-r--r--source/blender/draw/engines/eevee/shaders/effect_translucency_frag.glsl2
-rw-r--r--source/blender/draw/engines/eevee/shaders/lookdev_world_frag.glsl4
-rw-r--r--source/blender/draw/engines/gpencil/gpencil_draw_data.c2
-rw-r--r--source/blender/draw/engines/gpencil/shaders/gpencil_common_lib.glsl2
-rw-r--r--source/blender/draw/engines/image/image_buffer_cache.hh19
-rw-r--r--source/blender/draw/engines/overlay/overlay_wireframe.c6
-rw-r--r--source/blender/draw/engines/workbench/workbench_data.c2
-rw-r--r--source/blender/draw/engines/workbench/workbench_effect_dof.c8
-rw-r--r--source/blender/draw/intern/draw_cache_extract_mesh.cc1
-rw-r--r--source/blender/draw/intern/draw_cache_impl_curves.cc2
-rw-r--r--source/blender/draw/intern/draw_common.c2
-rw-r--r--source/blender/draw/intern/shaders/common_math_lib.glsl3
-rw-r--r--source/blender/editors/animation/anim_channels_defines.c223
-rw-r--r--source/blender/editors/animation/anim_channels_edit.c4
-rw-r--r--source/blender/editors/animation/anim_intern.h61
-rw-r--r--source/blender/editors/animation/anim_ops.c2
-rw-r--r--source/blender/editors/animation/drivers.c2
-rw-r--r--source/blender/editors/animation/fmodifier_ui.c2
-rw-r--r--source/blender/editors/animation/keyframes_keylist.cc7
-rw-r--r--source/blender/editors/animation/keyframing.c47
-rw-r--r--source/blender/editors/animation/keyingsets.c67
-rw-r--r--source/blender/editors/asset/intern/asset_ops.cc2
-rw-r--r--source/blender/editors/curve/editcurve.c10
-rw-r--r--source/blender/editors/curve/editcurve_add.c4
-rw-r--r--source/blender/editors/gpencil/annotate_paint.c9
-rw-r--r--source/blender/editors/gpencil/gpencil_edit.c11
-rw-r--r--source/blender/editors/gpencil/gpencil_vertex_ops.c2
-rw-r--r--source/blender/editors/include/ED_anim_api.h119
-rw-r--r--source/blender/editors/include/ED_screen_types.h6
-rw-r--r--source/blender/editors/include/ED_uvedit.h14
-rw-r--r--source/blender/editors/include/ED_view3d.h6
-rw-r--r--source/blender/editors/interface/interface_anim.c8
-rw-r--r--source/blender/editors/interface/interface_context_menu.c2
-rw-r--r--source/blender/editors/interface/interface_draw.c2
-rw-r--r--source/blender/editors/interface/interface_handlers.c13
-rw-r--r--source/blender/editors/interface/interface_ops.c2
-rw-r--r--source/blender/editors/interface/interface_region_popup.c2
-rw-r--r--source/blender/editors/interface/interface_template_search_menu.cc2
-rw-r--r--source/blender/editors/interface/interface_template_search_operator.c2
-rw-r--r--source/blender/editors/interface/interface_templates.c8
-rw-r--r--source/blender/editors/interface/interface_widgets.c15
-rw-r--r--source/blender/editors/interface/view2d_ops.c2
-rw-r--r--source/blender/editors/mask/mask_edit.c2
-rw-r--r--source/blender/editors/mask/mask_editaction.c4
-rw-r--r--source/blender/editors/mesh/editmesh_extrude_spin_gizmo.c2
-rw-r--r--source/blender/editors/mesh/editmesh_rip.c2
-rw-r--r--source/blender/editors/mesh/editmesh_tools.c4
-rw-r--r--source/blender/editors/mesh/editmesh_undo.c4
-rw-r--r--source/blender/editors/mesh/meshtools.c38
-rw-r--r--source/blender/editors/object/object_add.cc3
-rw-r--r--source/blender/editors/object/object_modes.c4
-rw-r--r--source/blender/editors/screen/screen_ops.c2
-rw-r--r--source/blender/editors/sculpt_paint/curves_sculpt_ops.cc362
-rw-r--r--source/blender/editors/sculpt_paint/paint_curve.c2
-rw-r--r--source/blender/editors/sculpt_paint/paint_stroke.c4
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_cloth.c2
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_detail.c2
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_filter_color.c2
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_filter_mesh.c2
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_undo.c3
-rw-r--r--source/blender/editors/space_action/action_select.c8
-rw-r--r--source/blender/editors/space_buttons/buttons_ops.c2
-rw-r--r--source/blender/editors/space_console/console_ops.c6
-rw-r--r--source/blender/editors/space_console/space_console.c2
-rw-r--r--source/blender/editors/space_file/file_ops.c4
-rw-r--r--source/blender/editors/space_file/filelist.c17
-rw-r--r--source/blender/editors/space_file/filesel.c22
-rw-r--r--source/blender/editors/space_file/fsmenu.c28
-rw-r--r--source/blender/editors/space_graph/graph_select.c4
-rw-r--r--source/blender/editors/space_graph/space_graph.c12
-rw-r--r--source/blender/editors/space_image/image_buttons.c18
-rw-r--r--source/blender/editors/space_image/image_draw.c3
-rw-r--r--source/blender/editors/space_image/image_ops.c4
-rw-r--r--source/blender/editors/space_image/image_undo.c3
-rw-r--r--source/blender/editors/space_info/info_report.c2
-rw-r--r--source/blender/editors/space_nla/nla_edit.c4
-rw-r--r--source/blender/editors/space_nla/nla_select.c4
-rw-r--r--source/blender/editors/space_node/drawnode.cc17
-rw-r--r--source/blender/editors/space_node/link_drag_search.cc2
-rw-r--r--source/blender/editors/space_node/node_draw.cc4
-rw-r--r--source/blender/editors/space_node/node_edit.cc10
-rw-r--r--source/blender/editors/space_node/node_relationships.cc5
-rw-r--r--source/blender/editors/space_node/node_select.cc6
-rw-r--r--source/blender/editors/space_outliner/outliner_collections.cc64
-rw-r--r--source/blender/editors/space_outliner/outliner_dragdrop.cc73
-rw-r--r--source/blender/editors/space_outliner/outliner_draw.cc13
-rw-r--r--source/blender/editors/space_outliner/outliner_edit.cc13
-rw-r--r--source/blender/editors/space_outliner/outliner_intern.hh16
-rw-r--r--source/blender/editors/space_outliner/outliner_ops.cc6
-rw-r--r--source/blender/editors/space_outliner/outliner_select.cc38
-rw-r--r--source/blender/editors/space_outliner/outliner_tools.cc20
-rw-r--r--source/blender/editors/space_outliner/outliner_tree.cc33
-rw-r--r--source/blender/editors/space_outliner/outliner_utils.cc5
-rw-r--r--source/blender/editors/space_sequencer/sequencer_draw.c9
-rw-r--r--source/blender/editors/space_text/text_draw.c68
-rw-r--r--source/blender/editors/space_text/text_ops.c8
-rw-r--r--source/blender/editors/space_view3d/space_view3d.c2
-rw-r--r--source/blender/editors/space_view3d/view3d_edit.c8
-rw-r--r--source/blender/editors/space_view3d/view3d_gizmo_ruler.c33
-rw-r--r--source/blender/editors/space_view3d/view3d_navigate.c8
-rw-r--r--source/blender/editors/space_view3d/view3d_navigate_dolly.c4
-rw-r--r--source/blender/editors/space_view3d/view3d_navigate_move.c4
-rw-r--r--source/blender/editors/space_view3d/view3d_navigate_roll.c4
-rw-r--r--source/blender/editors/space_view3d/view3d_navigate_rotate.c4
-rw-r--r--source/blender/editors/space_view3d/view3d_navigate_zoom.c4
-rw-r--r--source/blender/editors/space_view3d/view3d_placement.c9
-rw-r--r--source/blender/editors/space_view3d/view3d_select.c4
-rw-r--r--source/blender/editors/space_view3d/view3d_snap.c4
-rw-r--r--source/blender/editors/transform/transform.c46
-rw-r--r--source/blender/editors/transform/transform.h6
-rw-r--r--source/blender/editors/transform/transform_convert.c3
-rw-r--r--source/blender/editors/transform/transform_convert_mesh.c2
-rw-r--r--source/blender/editors/transform/transform_generics.c13
-rw-r--r--source/blender/editors/transform/transform_gizmo_3d.c5
-rw-r--r--source/blender/editors/transform/transform_mode.c4
-rw-r--r--source/blender/editors/transform/transform_ops.c6
-rw-r--r--source/blender/editors/transform/transform_snap.c43
-rw-r--r--source/blender/editors/uvedit/uvedit_intern.h4
-rw-r--r--source/blender/editors/uvedit/uvedit_ops.c13
-rw-r--r--source/blender/editors/uvedit/uvedit_parametrizer.c12
-rw-r--r--source/blender/editors/uvedit/uvedit_select.c104
-rw-r--r--source/blender/freestyle/intern/geometry/matrix_util.cpp2
-rw-r--r--source/blender/freestyle/intern/view_map/ViewMap.h2
-rw-r--r--source/blender/freestyle/intern/winged_edge/Curvature.cpp4
-rw-r--r--source/blender/freestyle/intern/winged_edge/WEdge.h4
-rw-r--r--source/blender/freestyle/intern/winged_edge/WXEdge.cpp2
-rw-r--r--source/blender/geometry/GEO_mesh_to_curve.hh6
-rw-r--r--source/blender/geometry/intern/mesh_to_curve_convert.cc152
-rw-r--r--source/blender/geometry/intern/realize_instances.cc586
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencil_ui_common.c2
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencil_ui_common.h4
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencilbuild.c57
-rw-r--r--source/blender/gpu/intern/gpu_immediate_util.c4
-rw-r--r--source/blender/gpu/intern/gpu_shader_create_info.hh2
-rw-r--r--source/blender/gpu/intern/gpu_vertex_format.cc4
-rw-r--r--source/blender/gpu/opengl/gl_backend.cc5
-rw-r--r--source/blender/gpu/opengl/gl_shader.cc2
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_object_info.glsl2
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_tex_environment.glsl4
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_texture_coordinates.glsl8
-rw-r--r--source/blender/ikplugin/intern/iksolver_plugin.c6
-rw-r--r--source/blender/imbuf/IMB_thumbs.h2
-rw-r--r--source/blender/imbuf/intern/anim_movie.c2
-rw-r--r--source/blender/imbuf/intern/dds/DirectDrawSurface.cpp29
-rw-r--r--source/blender/io/collada/AnimationImporter.cpp4
-rw-r--r--source/blender/io/collada/DocumentImporter.cpp3
-rw-r--r--source/blender/io/collada/SceneExporter.cpp2
-rw-r--r--source/blender/io/collada/collada_internal.cpp4
-rw-r--r--source/blender/io/usd/intern/usd_capi_import.cc2
-rw-r--r--source/blender/makesdna/DNA_ID.h10
-rw-r--r--source/blender/makesdna/DNA_action_types.h18
-rw-r--r--source/blender/makesdna/DNA_brush_enums.h8
-rw-r--r--source/blender/makesdna/DNA_curves_types.h12
-rw-r--r--source/blender/makesdna/DNA_gpencil_modifier_types.h2
-rw-r--r--source/blender/makesdna/DNA_modifier_defaults.h2
-rw-r--r--source/blender/makesdna/DNA_scene_defaults.h4
-rw-r--r--source/blender/makesdna/DNA_scene_types.h16
-rw-r--r--source/blender/makesdna/DNA_windowmanager_types.h2
-rw-r--r--source/blender/makesrna/RNA_types.h2
-rw-r--r--source/blender/makesrna/intern/makesrna.c47
-rw-r--r--source/blender/makesrna/intern/rna_ID.c5
-rw-r--r--source/blender/makesrna/intern/rna_access.c4
-rw-r--r--source/blender/makesrna/intern/rna_brush.c6
-rw-r--r--source/blender/makesrna/intern/rna_camera.c6
-rw-r--r--source/blender/makesrna/intern/rna_cloth.c2
-rw-r--r--source/blender/makesrna/intern/rna_constraint.c6
-rw-r--r--source/blender/makesrna/intern/rna_curve.c19
-rw-r--r--source/blender/makesrna/intern/rna_curve_api.c49
-rw-r--r--source/blender/makesrna/intern/rna_define.c3
-rw-r--r--source/blender/makesrna/intern/rna_dynamicpaint.c3
-rw-r--r--source/blender/makesrna/intern/rna_gpencil_modifier.c5
-rw-r--r--source/blender/makesrna/intern/rna_key.c4
-rw-r--r--source/blender/makesrna/intern/rna_nodetree.c20
-rw-r--r--source/blender/makesrna/intern/rna_particle.c7
-rw-r--r--source/blender/makesrna/intern/rna_rna.c2
-rw-r--r--source/blender/makesrna/intern/rna_scene.c28
-rw-r--r--source/blender/makesrna/intern/rna_text_api.c21
-rw-r--r--source/blender/makesrna/intern/rna_ui.c4
-rw-r--r--source/blender/makesrna/intern/rna_userdef.c2
-rw-r--r--source/blender/makesrna/intern/rna_wm.c18
-rw-r--r--source/blender/makesrna/intern/rna_xr.c6
-rw-r--r--source/blender/modifiers/intern/MOD_edgesplit.c3
-rw-r--r--source/blender/modifiers/intern/MOD_ui_common.c2
-rw-r--r--source/blender/modifiers/intern/MOD_ui_common.h4
-rw-r--r--source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_curve_reverse.cc2
-rw-r--r--source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_curve_set_handles.cc2
-rw-r--r--source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_curve_spline_type.cc4
-rw-r--r--source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_mesh_to_curve.cc6
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_curve_fill.cc4
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_curve_fillet.cc4
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_curve_handle_type_selection.cc1
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_curve_primitive_circle.cc2
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_curve_resample.cc2
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_curve_spline_type.cc29
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_curve_subdivide.cc6
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_curve_trim.cc2
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_delete_geometry.cc4
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_duplicate_elements.cc2
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_image_texture.cc4
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_input_spline_length.cc9
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_cone.cc8
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_uv_sphere.cc2
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_mesh_to_curve.cc3
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_transform.cc4
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_bsdf_principled.cc2
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_object_info.cc1
-rw-r--r--source/blender/python/generic/idprop_py_api.c11
-rw-r--r--source/blender/python/gpu/gpu_py_texture.c4
-rw-r--r--source/blender/python/intern/bpy_app_handlers.c4
-rw-r--r--source/blender/python/intern/bpy_driver.c73
-rw-r--r--source/blender/python/intern/bpy_interface_run.c3
-rw-r--r--source/blender/python/intern/bpy_intern_string.c4
-rw-r--r--source/blender/python/intern/bpy_intern_string.h1
-rw-r--r--source/blender/python/intern/bpy_operator.c2
-rw-r--r--source/blender/python/intern/bpy_rna.c33
-rw-r--r--source/blender/render/RE_pipeline.h10
-rw-r--r--source/blender/render/intern/pipeline.c68
-rw-r--r--source/blender/render/intern/texture_procedural.c12
-rw-r--r--source/blender/sequencer/intern/effects.c155
-rw-r--r--source/blender/sequencer/intern/effects.h7
-rw-r--r--source/blender/shader_fx/intern/FX_ui_common.c2
-rw-r--r--source/blender/windowmanager/WM_api.h30
-rw-r--r--source/blender/windowmanager/WM_types.h111
-rw-r--r--source/blender/windowmanager/gizmo/WM_gizmo_api.h5
-rw-r--r--source/blender/windowmanager/gizmo/intern/wm_gizmo.c6
-rw-r--r--source/blender/windowmanager/gizmo/intern/wm_gizmo_group.c4
-rw-r--r--source/blender/windowmanager/gizmo/intern/wm_gizmo_map.c14
-rw-r--r--source/blender/windowmanager/intern/wm.c3
-rw-r--r--source/blender/windowmanager/intern/wm_event_query.c27
-rw-r--r--source/blender/windowmanager/intern/wm_event_system.c407
-rw-r--r--source/blender/windowmanager/intern/wm_files.c24
-rw-r--r--source/blender/windowmanager/intern/wm_gesture.c15
-rw-r--r--source/blender/windowmanager/intern/wm_init_exit.c2
-rw-r--r--source/blender/windowmanager/intern/wm_operators.c18
-rw-r--r--source/blender/windowmanager/intern/wm_toolsystem.c4
-rw-r--r--source/blender/windowmanager/intern/wm_window.c5
-rw-r--r--source/blender/windowmanager/wm_event_types.h24
-rw-r--r--source/blender/windowmanager/xr/intern/wm_xr_operators.c2
-rw-r--r--source/creator/creator_args.c2
-rw-r--r--tests/python/bl_pyapi_idprop.py8
358 files changed, 4670 insertions, 2646 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 9f8800fe303..f7d85969ba2 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -502,7 +502,7 @@ else()
set(WITH_EXPERIMENTAL_FEATURES OFF)
endif()
-# Unit testsing
+# Unit testing
option(WITH_GTESTS "Enable GTest unit testing" OFF)
option(WITH_OPENGL_RENDER_TESTS "Enable OpenGL render related unit testing (Experimental)" OFF)
option(WITH_OPENGL_DRAW_TESTS "Enable OpenGL UI drawing related unit testing (Experimental)" OFF)
diff --git a/GNUmakefile b/GNUmakefile
index 575f3e904df..8dc2a2e2a9a 100644
--- a/GNUmakefile
+++ b/GNUmakefile
@@ -32,7 +32,7 @@ Other Convenience Targets
* config: Run cmake configuration tool to set build options.
* deps: Build library dependencies (intended only for platform maintainers).
- The existance of locally build dependencies overrides the pre-built dependencies from subversion.
+ The existence of locally build dependencies overrides the pre-built dependencies from subversion.
These must be manually removed from '../lib/' to go back to using the pre-compiled libraries.
Project Files
diff --git a/build_files/cmake/platform/platform_unix.cmake b/build_files/cmake/platform/platform_unix.cmake
index 77d1db97997..0a7119802c8 100644
--- a/build_files/cmake/platform/platform_unix.cmake
+++ b/build_files/cmake/platform/platform_unix.cmake
@@ -858,7 +858,7 @@ endif()
# If atomic operations are possible without libatomic then linker flags are left as-is.
function(CONFIGURE_ATOMIC_LIB_IF_NEEDED)
# Source which is used to enforce situation when software emulation of atomics is required.
- # Assume that using 64bit integer gives a definitive asnwer (as in, if 64bit atomic operations
+ # Assume that using 64bit integer gives a definitive answer (as in, if 64bit atomic operations
# are possible using assembly/intrinsics 8, 16, and 32 bit operations will also be possible.
set(_source
"#include <atomic>
diff --git a/build_files/windows/find_dependencies.cmd b/build_files/windows/find_dependencies.cmd
index fec2bd2e752..fa893c949cf 100644
--- a/build_files/windows/find_dependencies.cmd
+++ b/build_files/windows/find_dependencies.cmd
@@ -5,7 +5,7 @@ for %%X in (ctest.exe) do (set CTEST=%%~$PATH:X)
for %%X in (git.exe) do (set GIT=%%~$PATH:X)
REM For python, default on 39 but if that does not exist also check
REM the 310,311 and 312 folders to see if those are there, it checks
-REM this far ahead to ensure good lib folder compatiblity in the future.
+REM this far ahead to ensure good lib folder compatibility in the future.
set PYTHON=%BLENDER_DIR%\..\lib\win64_vc15\python\39\bin\python.exe
if EXIST %PYTHON% (
goto detect_python_done
diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py
index 10a72c598e2..2b74a1b7ccf 100644
--- a/intern/cycles/blender/addon/ui.py
+++ b/intern/cycles/blender/addon/ui.py
@@ -11,6 +11,7 @@ from bl_ui.utils import PresetPanel
from bpy.types import Panel
from bl_ui.properties_grease_pencil_common import GreasePencilSimplifyPanel
+from bl_ui.properties_render import draw_hair_settings
from bl_ui.properties_view_layer import ViewLayerCryptomattePanel, ViewLayerAOVPanel
class CyclesPresetPanel(PresetPanel, Panel):
@@ -355,6 +356,13 @@ class CYCLES_RENDER_PT_hair(CyclesButtonsPanel, Panel):
if ccscene.shape == 'RIBBONS':
col.prop(ccscene, "subdivisions", text="Curve Subdivisions")
+class CYCLES_RENDER_PT_hair_viewport_display(CyclesButtonsPanel, Panel):
+ bl_label = "Viewport Display"
+ bl_parent_id = "CYCLES_RENDER_PT_hair"
+ bl_options = {'DEFAULT_CLOSED'}
+
+ def draw(self, context):
+ draw_hair_settings(self, context)
class CYCLES_RENDER_PT_volumes(CyclesButtonsPanel, Panel):
bl_label = "Volumes"
@@ -2153,6 +2161,7 @@ classes = (
CYCLES_RENDER_PT_volumes,
CYCLES_RENDER_PT_subdivision,
CYCLES_RENDER_PT_hair,
+ CYCLES_RENDER_PT_hair_viewport_display,
CYCLES_RENDER_PT_simplify,
CYCLES_RENDER_PT_simplify_viewport,
CYCLES_RENDER_PT_simplify_render,
diff --git a/intern/cycles/blender/object.cpp b/intern/cycles/blender/object.cpp
index 559b0d42a29..054142a9ca4 100644
--- a/intern/cycles/blender/object.cpp
+++ b/intern/cycles/blender/object.cpp
@@ -319,7 +319,9 @@ Object *BlenderSync::sync_object(BL::Depsgraph &b_depsgraph,
(object->get_geometry() && object->get_geometry()->is_modified())) {
object->name = b_ob.name().c_str();
object->set_pass_id(b_ob.pass_index());
- object->set_color(get_float3(b_ob.color()));
+ const BL::Array<float, 4> object_color = b_ob.color();
+ object->set_color(get_float3(object_color));
+ object->set_alpha(object_color[3]);
object->set_tfm(tfm);
/* dupli texture coordinates and random_id */
diff --git a/intern/cycles/device/optix/device_impl.cpp b/intern/cycles/device/optix/device_impl.cpp
index cbe823c26ad..8830d8c44ac 100644
--- a/intern/cycles/device/optix/device_impl.cpp
+++ b/intern/cycles/device/optix/device_impl.cpp
@@ -33,6 +33,191 @@
CCL_NAMESPACE_BEGIN
+// A minimal copy of functionality `optix_denoiser_tiling.h` which allows to fix integer overflow
+// issues without bumping SDK or driver requirement.
+//
+// The original code is Copyright NVIDIA Corporation, BSD-3-Clause.
+namespace {
+
+static OptixResult optixUtilDenoiserSplitImage(const OptixImage2D &input,
+ const OptixImage2D &output,
+ unsigned int overlapWindowSizeInPixels,
+ unsigned int tileWidth,
+ unsigned int tileHeight,
+ std::vector<OptixUtilDenoiserImageTile> &tiles)
+{
+ if (tileWidth == 0 || tileHeight == 0)
+ return OPTIX_ERROR_INVALID_VALUE;
+
+ unsigned int inPixelStride = optixUtilGetPixelStride(input);
+ unsigned int outPixelStride = optixUtilGetPixelStride(output);
+
+ int inp_w = std::min(tileWidth + 2 * overlapWindowSizeInPixels, input.width);
+ int inp_h = std::min(tileHeight + 2 * overlapWindowSizeInPixels, input.height);
+ int inp_y = 0, copied_y = 0;
+
+ do {
+ int inputOffsetY = inp_y == 0 ? 0 :
+ std::max((int)overlapWindowSizeInPixels,
+ inp_h - ((int)input.height - inp_y));
+ int copy_y = inp_y == 0 ? std::min(input.height, tileHeight + overlapWindowSizeInPixels) :
+ std::min(tileHeight, input.height - copied_y);
+
+ int inp_x = 0, copied_x = 0;
+ do {
+ int inputOffsetX = inp_x == 0 ? 0 :
+ std::max((int)overlapWindowSizeInPixels,
+ inp_w - ((int)input.width - inp_x));
+ int copy_x = inp_x == 0 ? std::min(input.width, tileWidth + overlapWindowSizeInPixels) :
+ std::min(tileWidth, input.width - copied_x);
+
+ OptixUtilDenoiserImageTile tile;
+ tile.input.data = input.data + (size_t)(inp_y - inputOffsetY) * input.rowStrideInBytes +
+ +(size_t)(inp_x - inputOffsetX) * inPixelStride;
+ tile.input.width = inp_w;
+ tile.input.height = inp_h;
+ tile.input.rowStrideInBytes = input.rowStrideInBytes;
+ tile.input.pixelStrideInBytes = input.pixelStrideInBytes;
+ tile.input.format = input.format;
+
+ tile.output.data = output.data + (size_t)inp_y * output.rowStrideInBytes +
+ (size_t)inp_x * outPixelStride;
+ tile.output.width = copy_x;
+ tile.output.height = copy_y;
+ tile.output.rowStrideInBytes = output.rowStrideInBytes;
+ tile.output.pixelStrideInBytes = output.pixelStrideInBytes;
+ tile.output.format = output.format;
+
+ tile.inputOffsetX = inputOffsetX;
+ tile.inputOffsetY = inputOffsetY;
+ tiles.push_back(tile);
+
+ inp_x += inp_x == 0 ? tileWidth + overlapWindowSizeInPixels : tileWidth;
+ copied_x += copy_x;
+ } while (inp_x < static_cast<int>(input.width));
+
+ inp_y += inp_y == 0 ? tileHeight + overlapWindowSizeInPixels : tileHeight;
+ copied_y += copy_y;
+ } while (inp_y < static_cast<int>(input.height));
+
+ return OPTIX_SUCCESS;
+}
+
+static OptixResult optixUtilDenoiserInvokeTiled(OptixDenoiser denoiser,
+ CUstream stream,
+ const OptixDenoiserParams *params,
+ CUdeviceptr denoiserState,
+ size_t denoiserStateSizeInBytes,
+ const OptixDenoiserGuideLayer *guideLayer,
+ const OptixDenoiserLayer *layers,
+ unsigned int numLayers,
+ CUdeviceptr scratch,
+ size_t scratchSizeInBytes,
+ unsigned int overlapWindowSizeInPixels,
+ unsigned int tileWidth,
+ unsigned int tileHeight)
+{
+ if (!guideLayer || !layers)
+ return OPTIX_ERROR_INVALID_VALUE;
+
+ std::vector<std::vector<OptixUtilDenoiserImageTile>> tiles(numLayers);
+ std::vector<std::vector<OptixUtilDenoiserImageTile>> prevTiles(numLayers);
+ for (unsigned int l = 0; l < numLayers; l++) {
+ if (const OptixResult res = ccl::optixUtilDenoiserSplitImage(layers[l].input,
+ layers[l].output,
+ overlapWindowSizeInPixels,
+ tileWidth,
+ tileHeight,
+ tiles[l]))
+ return res;
+
+ if (layers[l].previousOutput.data) {
+ OptixImage2D dummyOutput = layers[l].previousOutput;
+ if (const OptixResult res = ccl::optixUtilDenoiserSplitImage(layers[l].previousOutput,
+ dummyOutput,
+ overlapWindowSizeInPixels,
+ tileWidth,
+ tileHeight,
+ prevTiles[l]))
+ return res;
+ }
+ }
+
+ std::vector<OptixUtilDenoiserImageTile> albedoTiles;
+ if (guideLayer->albedo.data) {
+ OptixImage2D dummyOutput = guideLayer->albedo;
+ if (const OptixResult res = ccl::optixUtilDenoiserSplitImage(guideLayer->albedo,
+ dummyOutput,
+ overlapWindowSizeInPixels,
+ tileWidth,
+ tileHeight,
+ albedoTiles))
+ return res;
+ }
+
+ std::vector<OptixUtilDenoiserImageTile> normalTiles;
+ if (guideLayer->normal.data) {
+ OptixImage2D dummyOutput = guideLayer->normal;
+ if (const OptixResult res = ccl::optixUtilDenoiserSplitImage(guideLayer->normal,
+ dummyOutput,
+ overlapWindowSizeInPixels,
+ tileWidth,
+ tileHeight,
+ normalTiles))
+ return res;
+ }
+ std::vector<OptixUtilDenoiserImageTile> flowTiles;
+ if (guideLayer->flow.data) {
+ OptixImage2D dummyOutput = guideLayer->flow;
+ if (const OptixResult res = ccl::optixUtilDenoiserSplitImage(guideLayer->flow,
+ dummyOutput,
+ overlapWindowSizeInPixels,
+ tileWidth,
+ tileHeight,
+ flowTiles))
+ return res;
+ }
+
+ for (size_t t = 0; t < tiles[0].size(); t++) {
+ std::vector<OptixDenoiserLayer> tlayers;
+ for (unsigned int l = 0; l < numLayers; l++) {
+ OptixDenoiserLayer layer = {};
+ layer.input = (tiles[l])[t].input;
+ layer.output = (tiles[l])[t].output;
+ if (layers[l].previousOutput.data)
+ layer.previousOutput = (prevTiles[l])[t].input;
+ tlayers.push_back(layer);
+ }
+
+ OptixDenoiserGuideLayer gl = {};
+ if (guideLayer->albedo.data)
+ gl.albedo = albedoTiles[t].input;
+
+ if (guideLayer->normal.data)
+ gl.normal = normalTiles[t].input;
+
+ if (guideLayer->flow.data)
+ gl.flow = flowTiles[t].input;
+
+ if (const OptixResult res = optixDenoiserInvoke(denoiser,
+ stream,
+ params,
+ denoiserState,
+ denoiserStateSizeInBytes,
+ &gl,
+ &tlayers[0],
+ numLayers,
+ (tiles[0])[t].inputOffsetX,
+ (tiles[0])[t].inputOffsetY,
+ scratch,
+ scratchSizeInBytes))
+ return res;
+ }
+ return OPTIX_SUCCESS;
+}
+
+} // namespace
+
OptiXDevice::Denoiser::Denoiser(OptiXDevice *device)
: device(device), queue(device), state(device, "__denoiser_state", true)
{
@@ -1075,20 +1260,20 @@ bool OptiXDevice::denoise_run(DenoiseContext &context, const DenoisePass &pass)
/* Finally run denoising. */
OptixDenoiserParams params = {}; /* All parameters are disabled/zero. */
- optix_assert(optixUtilDenoiserInvokeTiled(denoiser_.optix_denoiser,
- denoiser_.queue.stream(),
- &params,
- denoiser_.state.device_pointer,
- denoiser_.sizes.stateSizeInBytes,
- &guide_layers,
- &image_layers,
- 1,
- denoiser_.state.device_pointer +
- denoiser_.sizes.stateSizeInBytes,
- denoiser_.sizes.withOverlapScratchSizeInBytes,
- denoiser_.sizes.overlapWindowSizeInPixels,
- denoiser_.configured_size.x,
- denoiser_.configured_size.y));
+ optix_assert(ccl::optixUtilDenoiserInvokeTiled(denoiser_.optix_denoiser,
+ denoiser_.queue.stream(),
+ &params,
+ denoiser_.state.device_pointer,
+ denoiser_.sizes.stateSizeInBytes,
+ &guide_layers,
+ &image_layers,
+ 1,
+ denoiser_.state.device_pointer +
+ denoiser_.sizes.stateSizeInBytes,
+ denoiser_.sizes.withOverlapScratchSizeInBytes,
+ denoiser_.sizes.overlapWindowSizeInPixels,
+ denoiser_.configured_size.x,
+ denoiser_.configured_size.y));
return true;
}
diff --git a/intern/cycles/device/queue.h b/intern/cycles/device/queue.h
index 183ac1728a4..2bd6e7ae460 100644
--- a/intern/cycles/device/queue.h
+++ b/intern/cycles/device/queue.h
@@ -100,7 +100,7 @@ class DeviceQueue {
* based on number of cores and/or available memory. */
virtual int num_concurrent_states(const size_t state_size) const = 0;
- /* Number of states which keeps the device occupied with work without loosing performance.
+ /* Number of states which keeps the device occupied with work without losing performance.
* The renderer will add more work (when available) when number of active paths falls below this
* value. */
virtual int num_concurrent_busy_states() const = 0;
diff --git a/intern/cycles/integrator/denoiser.cpp b/intern/cycles/integrator/denoiser.cpp
index 0d3e49b7f21..23ab825a4d2 100644
--- a/intern/cycles/integrator/denoiser.cpp
+++ b/intern/cycles/integrator/denoiser.cpp
@@ -80,7 +80,8 @@ static bool is_single_supported_device(Device *device, DenoiserType type)
if (!device->info.multi_devices.empty()) {
/* Some configurations will use multi_devices, but keep the type of an individual device.
- * This does simplify checks for homogenous setups, but here we really need a single device. */
+ * This does simplify checks for homogeneous setups, but here we really need a single device.
+ */
return false;
}
diff --git a/intern/cycles/kernel/bvh/shadow_all.h b/intern/cycles/kernel/bvh/shadow_all.h
index a5769e91a28..2f58929c1e5 100644
--- a/intern/cycles/kernel/bvh/shadow_all.h
+++ b/intern/cycles/kernel/bvh/shadow_all.h
@@ -29,8 +29,8 @@ ccl_device_inline
IntegratorShadowState state,
const uint visibility,
const uint max_hits,
- ccl_private uint *num_recorded_hits,
- ccl_private float *throughput)
+ ccl_private uint *r_num_recorded_hits,
+ ccl_private float *r_throughput)
{
/* todo:
* - likely and unlikely for if() statements
@@ -60,15 +60,18 @@ ccl_device_inline
* recorded hits is exceeded and we no longer need to find hits beyond the max
* distance found. */
float t_max_world = ray->t;
- /* Equal to t_max_world when traversing top level BVH, transformed into local
- * space when entering instances. */
- float t_max_current = t_max_world;
+
+ /* Current maximum distance to the intersection.
+ * Is calculated as a ray length, transformed to an object space when entering
+ * instance node. */
+ float t_max_current = ray->t;
+
/* Conversion from world to local space for the current instance if any, 1.0
* otherwise. */
float t_world_to_instance = 1.0f;
- *num_recorded_hits = 0;
- *throughput = 1.0f;
+ *r_num_recorded_hits = 0;
+ *r_throughput = 1.0f;
/* traversal loop */
do {
@@ -237,10 +240,10 @@ ccl_device_inline
/* Always use baked shadow transparency for curves. */
if (isect.type & PRIMITIVE_CURVE) {
- *throughput *= intersection_curve_shadow_transparency(
+ *r_throughput *= intersection_curve_shadow_transparency(
kg, isect.object, isect.prim, isect.u);
- if (*throughput < CURVE_SHADOW_TRANSPARENCY_CUTOFF) {
+ if (*r_throughput < CURVE_SHADOW_TRANSPARENCY_CUTOFF) {
return true;
}
else {
@@ -249,37 +252,39 @@ ccl_device_inline
}
if (record_intersection) {
- /* Increase the number of hits, possibly beyond max_hits, we will
- * simply not record those and only keep the max_hits closest. */
- uint record_index = (*num_recorded_hits)++;
-
+ /* Test if we need to record this transparent intersection. */
const uint max_record_hits = min(max_hits, INTEGRATOR_SHADOW_ISECT_SIZE);
- if (record_index >= max_record_hits - 1) {
- /* If maximum number of hits reached, find the intersection with
- * the largest distance to potentially replace when another hit
- * is found. */
- const int num_recorded_hits = min(max_record_hits, record_index);
- float max_recorded_t = INTEGRATOR_STATE_ARRAY(state, shadow_isect, 0, t);
- int max_recorded_hit = 0;
-
- for (int i = 1; i < num_recorded_hits; i++) {
- const float isect_t = INTEGRATOR_STATE_ARRAY(state, shadow_isect, i, t);
- if (isect_t > max_recorded_t) {
- max_recorded_t = isect_t;
- max_recorded_hit = i;
+ if (*r_num_recorded_hits < max_record_hits || isect.t < t_max_world) {
+ /* If maximum number of hits was reached, replace the intersection with the
+ * highest distance. We want to find the N closest intersections. */
+ const uint num_recorded_hits = min(*r_num_recorded_hits, max_record_hits);
+ uint isect_index = num_recorded_hits;
+ if (num_recorded_hits + 1 >= max_record_hits) {
+ float max_t = INTEGRATOR_STATE_ARRAY(state, shadow_isect, 0, t);
+ uint max_recorded_hit = 0;
+
+ for (uint i = 1; i < num_recorded_hits; ++i) {
+ const float isect_t = INTEGRATOR_STATE_ARRAY(state, shadow_isect, i, t);
+ if (isect_t > max_t) {
+ max_recorded_hit = i;
+ max_t = isect_t;
+ }
+ }
+
+ if (num_recorded_hits >= max_record_hits) {
+ isect_index = max_recorded_hit;
}
- }
- if (record_index >= max_record_hits) {
- record_index = max_recorded_hit;
+ /* Limit the ray distance and stop counting hits beyond this. */
+ t_max_world = max(isect.t, max_t);
}
- /* Limit the ray distance and stop counting hits beyond this. */
- t_max_world = max(max_recorded_t, isect.t);
- t_max_current = t_max_world * t_world_to_instance;
+ integrator_state_write_shadow_isect(state, &isect, isect_index);
}
- integrator_state_write_shadow_isect(state, &isect, record_index);
+ /* Always increase the number of recorded hits, even beyond the maximum,
+ * so that we can detect this and trace another ray if needed. */
+ ++(*r_num_recorded_hits);
}
}
}
@@ -318,7 +323,7 @@ ccl_device_inline
#endif
/* Restore world space ray length. */
- t_max_current = t_max_world;
+ t_max_current = ray->t;
object = OBJECT_NONE;
t_world_to_instance = 1.0f;
diff --git a/intern/cycles/kernel/device/gpu/image.h b/intern/cycles/kernel/device/gpu/image.h
index 9c92f6a693c..83e7aa869c1 100644
--- a/intern/cycles/kernel/device/gpu/image.h
+++ b/intern/cycles/kernel/device/gpu/image.h
@@ -186,7 +186,7 @@ ccl_device float4 kernel_tex_image_interp(KernelGlobals kg, int id, float x, flo
const int texture_type = info.data_type;
if (texture_type == IMAGE_DATA_TYPE_FLOAT4 || texture_type == IMAGE_DATA_TYPE_BYTE4 ||
texture_type == IMAGE_DATA_TYPE_HALF4 || texture_type == IMAGE_DATA_TYPE_USHORT4) {
- if (info.interpolation == INTERPOLATION_CUBIC) {
+ if (info.interpolation == INTERPOLATION_CUBIC || info.interpolation == INTERPOLATION_SMART) {
return kernel_tex_image_interp_bicubic<float4>(info, x, y);
}
else {
@@ -198,7 +198,7 @@ ccl_device float4 kernel_tex_image_interp(KernelGlobals kg, int id, float x, flo
else {
float f;
- if (info.interpolation == INTERPOLATION_CUBIC) {
+ if (info.interpolation == INTERPOLATION_CUBIC || info.interpolation == INTERPOLATION_SMART) {
f = kernel_tex_image_interp_bicubic<float>(info, x, y);
}
else {
@@ -241,7 +241,7 @@ ccl_device float4 kernel_tex_image_interp_3d(KernelGlobals kg,
#endif
if (texture_type == IMAGE_DATA_TYPE_FLOAT4 || texture_type == IMAGE_DATA_TYPE_BYTE4 ||
texture_type == IMAGE_DATA_TYPE_HALF4 || texture_type == IMAGE_DATA_TYPE_USHORT4) {
- if (interpolation == INTERPOLATION_CUBIC) {
+ if (interpolation == INTERPOLATION_CUBIC || interpolation == INTERPOLATION_SMART) {
return kernel_tex_image_interp_tricubic<float4>(info, x, y, z);
}
else {
@@ -252,7 +252,7 @@ ccl_device float4 kernel_tex_image_interp_3d(KernelGlobals kg,
else {
float f;
- if (interpolation == INTERPOLATION_CUBIC) {
+ if (interpolation == INTERPOLATION_CUBIC || interpolation == INTERPOLATION_SMART) {
f = kernel_tex_image_interp_tricubic<float>(info, x, y, z);
}
else {
diff --git a/intern/cycles/kernel/geom/object.h b/intern/cycles/kernel/geom/object.h
index e8f5dfcc529..86c57c84b47 100644
--- a/intern/cycles/kernel/geom/object.h
+++ b/intern/cycles/kernel/geom/object.h
@@ -263,6 +263,16 @@ ccl_device_inline float3 object_color(KernelGlobals kg, int object)
return make_float3(kobject->color[0], kobject->color[1], kobject->color[2]);
}
+/* Alpha of the object */
+
+ccl_device_inline float object_alpha(KernelGlobals kg, int object)
+{
+ if (object == OBJECT_NONE)
+ return 0.0f;
+
+ return kernel_tex_fetch(__objects, object).alpha;
+}
+
/* Pass ID number of object */
ccl_device_inline float object_pass_id(KernelGlobals kg, int object)
diff --git a/intern/cycles/kernel/osl/services.cpp b/intern/cycles/kernel/osl/services.cpp
index 85bdb47600e..79547872c68 100644
--- a/intern/cycles/kernel/osl/services.cpp
+++ b/intern/cycles/kernel/osl/services.cpp
@@ -76,6 +76,7 @@ ustring OSLRenderServices::u_raster("raster");
ustring OSLRenderServices::u_ndc("NDC");
ustring OSLRenderServices::u_object_location("object:location");
ustring OSLRenderServices::u_object_color("object:color");
+ustring OSLRenderServices::u_object_alpha("object:alpha");
ustring OSLRenderServices::u_object_index("object:index");
ustring OSLRenderServices::u_geom_dupli_generated("geom:dupli_generated");
ustring OSLRenderServices::u_geom_dupli_uv("geom:dupli_uv");
@@ -873,6 +874,10 @@ bool OSLRenderServices::get_object_standard_attribute(const KernelGlobalsCPU *kg
float3 f = object_color(kg, sd->object);
return set_attribute_float3(f, type, derivatives, val);
}
+ else if (name == u_object_alpha) {
+ float f = object_alpha(kg, sd->object);
+ return set_attribute_float(f, type, derivatives, val);
+ }
else if (name == u_object_index) {
float f = object_pass_id(kg, sd->object);
return set_attribute_float(f, type, derivatives, val);
diff --git a/intern/cycles/kernel/osl/services.h b/intern/cycles/kernel/osl/services.h
index 0685003ca5c..653fa017140 100644
--- a/intern/cycles/kernel/osl/services.h
+++ b/intern/cycles/kernel/osl/services.h
@@ -259,6 +259,7 @@ class OSLRenderServices : public OSL::RendererServices {
static ustring u_ndc;
static ustring u_object_location;
static ustring u_object_color;
+ static ustring u_object_alpha;
static ustring u_object_index;
static ustring u_geom_dupli_generated;
static ustring u_geom_dupli_uv;
diff --git a/intern/cycles/kernel/osl/shaders/node_object_info.osl b/intern/cycles/kernel/osl/shaders/node_object_info.osl
index 37e545f9988..8ed73231213 100644
--- a/intern/cycles/kernel/osl/shaders/node_object_info.osl
+++ b/intern/cycles/kernel/osl/shaders/node_object_info.osl
@@ -5,12 +5,14 @@
shader node_object_info(output point Location = point(0.0, 0.0, 0.0),
output color Color = color(1.0, 1.0, 1.0),
+ output float Alpha = 1.0,
output float ObjectIndex = 0.0,
output float MaterialIndex = 0.0,
output float Random = 0.0)
{
getattribute("object:location", Location);
getattribute("object:color", Color);
+ getattribute("object:alpha", Alpha);
getattribute("object:index", ObjectIndex);
getattribute("material:index", MaterialIndex);
getattribute("object:random", Random);
diff --git a/intern/cycles/kernel/svm/geometry.h b/intern/cycles/kernel/svm/geometry.h
index c1a5fdb8ca4..4b5368dd765 100644
--- a/intern/cycles/kernel/svm/geometry.h
+++ b/intern/cycles/kernel/svm/geometry.h
@@ -116,6 +116,9 @@ ccl_device_noinline void svm_node_object_info(KernelGlobals kg,
stack_store_float3(stack, out_offset, object_color(kg, sd->object));
return;
}
+ case NODE_INFO_OB_ALPHA:
+ data = object_alpha(kg, sd->object);
+ break;
case NODE_INFO_OB_INDEX:
data = object_pass_id(kg, sd->object);
break;
diff --git a/intern/cycles/kernel/svm/types.h b/intern/cycles/kernel/svm/types.h
index 777a27b8716..bede58f7a54 100644
--- a/intern/cycles/kernel/svm/types.h
+++ b/intern/cycles/kernel/svm/types.h
@@ -142,6 +142,7 @@ typedef enum NodeGeometry {
typedef enum NodeObjectInfo {
NODE_INFO_OB_LOCATION,
NODE_INFO_OB_COLOR,
+ NODE_INFO_OB_ALPHA,
NODE_INFO_OB_INDEX,
NODE_INFO_MAT_INDEX,
NODE_INFO_OB_RANDOM
diff --git a/intern/cycles/kernel/types.h b/intern/cycles/kernel/types.h
index 24eb783daf9..07d4a95780b 100644
--- a/intern/cycles/kernel/types.h
+++ b/intern/cycles/kernel/types.h
@@ -1307,6 +1307,7 @@ typedef struct KernelObject {
float pass_id;
float random_number;
float color[3];
+ float alpha;
int particle_index;
float dupli_generated[3];
@@ -1330,6 +1331,7 @@ typedef struct KernelObject {
uint visibility;
int primitive_type;
+ int pad[2];
} KernelObject;
static_assert_align(KernelObject, 16);
diff --git a/intern/cycles/scene/alembic_read.cpp b/intern/cycles/scene/alembic_read.cpp
index 0ad3782360d..26a4153a825 100644
--- a/intern/cycles/scene/alembic_read.cpp
+++ b/intern/cycles/scene/alembic_read.cpp
@@ -469,7 +469,7 @@ static void add_subd_edge_creases(CachedData &cached_data,
const SubDSchemaData &data,
chrono_t time)
{
- if (!(data.crease_indices.valid() && data.crease_indices.valid() &&
+ if (!(data.crease_indices.valid() && data.crease_lengths.valid() &&
data.crease_sharpnesses.valid())) {
return;
}
@@ -543,7 +543,7 @@ static void read_subd_geometry(CachedData &cached_data, const SubDSchemaData &da
add_positions(data.positions.getValue(iss), time, cached_data);
- if (data.topology_variance != kHomogenousTopology || cached_data.shader.size() == 0) {
+ if (data.topology_variance != kHomogeneousTopology || cached_data.shader.size() == 0) {
add_subd_polygons(cached_data, data, time);
add_subd_edge_creases(cached_data, data, time);
add_subd_vertex_creases(cached_data, data, time);
@@ -582,7 +582,7 @@ static void read_curves_data(CachedData &cached_data, const CurvesSchemaData &da
array<int> curve_first_key;
array<int> curve_shader;
- const bool is_homogenous = data.topology_variance == kHomogenousTopology;
+ const bool is_homogeneous = data.topology_variance == kHomogeneousTopology;
curve_keys.reserve(position->size());
curve_radius.reserve(position->size());
@@ -605,7 +605,7 @@ static void read_curves_data(CachedData &cached_data, const CurvesSchemaData &da
curve_radius.push_back_slow(radius * data.radius_scale);
}
- if (!is_homogenous || cached_data.curve_first_key.size() == 0) {
+ if (!is_homogeneous || cached_data.curve_first_key.size() == 0) {
curve_first_key.push_back_reserved(offset);
curve_shader.push_back_reserved(0);
}
@@ -616,7 +616,7 @@ static void read_curves_data(CachedData &cached_data, const CurvesSchemaData &da
cached_data.curve_keys.add_data(curve_keys, time);
cached_data.curve_radius.add_data(curve_radius, time);
- if (!is_homogenous || cached_data.curve_first_key.size() == 0) {
+ if (!is_homogeneous || cached_data.curve_first_key.size() == 0) {
cached_data.curve_first_key.add_data(curve_first_key, time);
cached_data.curve_shader.add_data(curve_shader, time);
}
diff --git a/intern/cycles/scene/mesh.cpp b/intern/cycles/scene/mesh.cpp
index ebf1c3999b6..a459195efee 100644
--- a/intern/cycles/scene/mesh.cpp
+++ b/intern/cycles/scene/mesh.cpp
@@ -68,7 +68,7 @@ void Mesh::Triangle::verts_for_step(const float3 *verts,
r_verts[2] = verts[v[2]];
}
else {
- /* Center step not stored in the attribute array array. */
+ /* Center step not stored in the attribute array. */
if (step > center_step) {
step--;
}
diff --git a/intern/cycles/scene/object.cpp b/intern/cycles/scene/object.cpp
index 97c86804507..fda9a211e60 100644
--- a/intern/cycles/scene/object.cpp
+++ b/intern/cycles/scene/object.cpp
@@ -76,6 +76,7 @@ NODE_DEFINE(Object)
SOCKET_TRANSFORM(tfm, "Transform", transform_identity());
SOCKET_UINT(visibility, "Visibility", ~0);
SOCKET_COLOR(color, "Color", zero_float3());
+ SOCKET_FLOAT(alpha, "Alpha", 0.0f);
SOCKET_UINT(random_id, "Random ID", 0);
SOCKET_INT(pass_id, "Pass ID", 0);
SOCKET_BOOLEAN(use_holdout, "Use Holdout", false);
@@ -414,6 +415,7 @@ void ObjectManager::device_update_object_transform(UpdateObjectTransformState *s
kobject.color[0] = color.x;
kobject.color[1] = color.y;
kobject.color[2] = color.z;
+ kobject.alpha = ob->alpha;
kobject.pass_id = pass_id;
kobject.random_number = random_number;
kobject.particle_index = particle_index;
diff --git a/intern/cycles/scene/object.h b/intern/cycles/scene/object.h
index e18968bc0ed..55689ccfa58 100644
--- a/intern/cycles/scene/object.h
+++ b/intern/cycles/scene/object.h
@@ -44,6 +44,7 @@ class Object : public Node {
NODE_SOCKET_API(uint, random_id)
NODE_SOCKET_API(int, pass_id)
NODE_SOCKET_API(float3, color)
+ NODE_SOCKET_API(float, alpha)
NODE_SOCKET_API(ustring, asset_name)
vector<ParamValue> attributes;
NODE_SOCKET_API(uint, visibility)
diff --git a/intern/cycles/scene/shader_nodes.cpp b/intern/cycles/scene/shader_nodes.cpp
index ba85cbde1d0..272a0dde7d8 100644
--- a/intern/cycles/scene/shader_nodes.cpp
+++ b/intern/cycles/scene/shader_nodes.cpp
@@ -4216,6 +4216,7 @@ NODE_DEFINE(ObjectInfoNode)
SOCKET_OUT_VECTOR(location, "Location");
SOCKET_OUT_COLOR(color, "Color");
+ SOCKET_OUT_FLOAT(alpha, "Alpha");
SOCKET_OUT_FLOAT(object_index, "Object Index");
SOCKET_OUT_FLOAT(material_index, "Material Index");
SOCKET_OUT_FLOAT(random, "Random");
@@ -4239,6 +4240,11 @@ void ObjectInfoNode::compile(SVMCompiler &compiler)
compiler.add_node(NODE_OBJECT_INFO, NODE_INFO_OB_COLOR, compiler.stack_assign(out));
}
+ out = output("Alpha");
+ if (!out->links.empty()) {
+ compiler.add_node(NODE_OBJECT_INFO, NODE_INFO_OB_ALPHA, compiler.stack_assign(out));
+ }
+
out = output("Object Index");
if (!out->links.empty()) {
compiler.add_node(NODE_OBJECT_INFO, NODE_INFO_OB_INDEX, compiler.stack_assign(out));
diff --git a/intern/ghost/intern/GHOST_Wintab.cpp b/intern/ghost/intern/GHOST_Wintab.cpp
index aaf9503b294..2547a38c0d1 100644
--- a/intern/ghost/intern/GHOST_Wintab.cpp
+++ b/intern/ghost/intern/GHOST_Wintab.cpp
@@ -326,7 +326,7 @@ void GHOST_Wintab::getInput(std::vector<GHOST_WintabInfoWin32> &outWintabInfo)
ORIENTATION ort = pkt.pkOrientation;
/* Convert raw fixed point data to radians. */
- float altRad = (float)((fabs((float)ort.orAltitude) / (float)m_maxAltitude) * M_PI / 2.0);
+ float altRad = (float)((fabs((float)ort.orAltitude) / (float)m_maxAltitude) * M_PI_2);
float azmRad = (float)(((float)ort.orAzimuth / (float)m_maxAzimuth) * M_PI * 2.0);
/* Find length of the stylus' projected vector on the XY plane. */
@@ -334,7 +334,7 @@ void GHOST_Wintab::getInput(std::vector<GHOST_WintabInfoWin32> &outWintabInfo)
/* From there calculate X and Y components based on azimuth. */
out.tabletData.Xtilt = sin(azmRad) * vecLen;
- out.tabletData.Ytilt = (float)(sin(M_PI / 2.0 - azmRad) * vecLen);
+ out.tabletData.Ytilt = (float)(sin(M_PI_2 - azmRad) * vecLen);
}
out.time = pkt.pkTime;
diff --git a/intern/iksolver/intern/IK_QJacobian.cpp b/intern/iksolver/intern/IK_QJacobian.cpp
index 39c0e6eb348..ea659414b73 100644
--- a/intern/iksolver/intern/IK_QJacobian.cpp
+++ b/intern/iksolver/intern/IK_QJacobian.cpp
@@ -193,7 +193,7 @@ void IK_QJacobian::InvertSDLS()
// DLS. The SDLS damps individual singular values, instead of using a single
// damping term.
- double max_angle_change = M_PI / 4.0;
+ double max_angle_change = M_PI_4;
double epsilon = 1e-10;
int i, j;
diff --git a/intern/itasc/Cache.hpp b/intern/itasc/Cache.hpp
index a533d75b53a..d461bb32fa8 100644
--- a/intern/itasc/Cache.hpp
+++ b/intern/itasc/Cache.hpp
@@ -17,7 +17,7 @@ namespace iTaSC {
#define CACHE_CHANNEL_EXTEND_SIZE 10
#define CACHE_MAX_ITEM_SIZE 0x3FFF0
-/* macro to get the alignement gap after an item header */
+/* macro to get the alignment gap after an item header */
#define CACHE_ITEM_GAPB(item) (unsigned int)(((size_t)item+sizeof(CacheItem))&(sizeof(void*)-1))
/* macro to get item data position, item=CacheItem pointer */
#define CACHE_ITEM_DATA_POINTER(item) (void*)((unsigned char*)item+sizeof(CacheItem)+CACHE_ITEM_GAPB(item))
diff --git a/release/freedesktop/org.blender.Blender.appdata.xml b/release/freedesktop/org.blender.Blender.appdata.xml
index 4b413f6b38d..12291860050 100644
--- a/release/freedesktop/org.blender.Blender.appdata.xml
+++ b/release/freedesktop/org.blender.Blender.appdata.xml
@@ -40,6 +40,27 @@
</screenshot>
</screenshots>
<releases>
+ <release version="3.1" date="2022-03-09">
+ <description>
+ <p>New features:</p>
+ <ul>
+ <li>GPU acceleration for the Subdivision modifier</li>
+ <li>Cycles Metal GPU backend, contributed by Apple</li>
+ <li>Point Cloud rendering</li>
+ <li>More Geometry Nodes, including extrude mesh</li>
+ </ul>
+ <p>Enhancements:</p>
+ <ul>
+ <li>Faster and less memory usage in geometry nodes</li>
+ <li>Grease Pencil Dilate/Contract fill</li>
+ <li>Vertex Creasing support</li>
+ <li>Faster .obj and .fbx export</li>
+ <li>Image editor is able to handle large images</li>
+ <li>Python 3.10</li>
+ <li>User Interface updates</li>
+ </ul>
+ </description>
+ </release>
<release version="3.0" date="2021-12-03">
<description>
<p>New features:</p>
diff --git a/release/license/THIRD-PARTY-LICENSES.txt b/release/license/THIRD-PARTY-LICENSES.txt
index 2bd4ac23d6d..933f03b5564 100644
--- a/release/license/THIRD-PARTY-LICENSES.txt
+++ b/release/license/THIRD-PARTY-LICENSES.txt
@@ -318,7 +318,7 @@ Copyright (c) 2006, Google Inc.
All rights reserved.
** ISPC; version 1.16.0 -- https://github.com/ispc/ispc
Copyright Intel Corporation
-** NumPy; version 1.21.2 -- https://numpy.org/
+** NumPy; version 1.22.0 -- https://numpy.org/
Copyright (c) 2005-2021, NumPy Developers.
** Open Shading Language; version 1.11.14.1 --
https://github.com/imageworks/OpenShadingLanguage
@@ -822,7 +822,7 @@ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
** FFTW; version 3.3.8 -- http://www.fftw.org/
Copyright (c) 2003, 2007-14 Matteo Frigo
Copyright (c) 2003, 2007-14 Massachusetts Institute of Technology
-** GMP; version 6.2.0 -- https://gmplib.org/
+** GMP; version 6.2.1 -- https://gmplib.org/
Copyright 1996-2020 Free Software Foundation, Inc.
** OpenAL; version 1.20.1 -- http://openal-soft.org
Copyright (c) 2015, Archontis Politis
@@ -1162,7 +1162,7 @@ Copyright (C) 2003-2021 x264 project
** miniLZO; version 2.08 -- http://www.oberhumer.com/opensource/lzo/
LZO and miniLZO are Copyright (C) 1996-2014 Markus Franz Xaver Oberhumer
All Rights Reserved.
-** The FreeType Project; version 2.10.2 --
+** The FreeType Project; version 2.11.1 --
https://sourceforge.net/projects/freetype
Copyright (C) 1996-2020 by David Turner, Robert Wilhelm, and Werner Lemberg.
** X Drag and Drop; version 2000-08-08 --
@@ -1174,7 +1174,7 @@ Project initiators:
Christoph Lampert <gruel@web.de>
Michael Militzer <isibaar@xvid.org>
Peter Ross <pross@xvid.org>
-** Zstandard; version 1.5.0 -- https://github.com/facebook/zstd
+** Zstandard; version 1.6.0 -- https://github.com/facebook/zstd
Copyright (c) 2016-present, Facebook, Inc. All rights reserved.
GNU GENERAL PUBLIC LICENSE
@@ -2956,6 +2956,8 @@ December 9, 2010
------
+** Brotli; version 1.0.9 -- https://github.com/google/brotli
+Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors.
** Expat; version 2.2.10 -- https://github.com/libexpat/libexpat/
Copyright (c) 1998-2000 Thai Open Source Software Center Ltd and Clark Cooper
Copyright (c) 2001-2019 Expat maintainers
@@ -3627,7 +3629,7 @@ disclaims all warranties with regard to this software.
------
-** Python; version 3.9.7 -- https://www.python.org
+** Python; version 3.10.2 -- https://www.python.org
Copyright (c) 2001-2021 Python Software Foundation. All rights reserved.
A. HISTORY OF THE SOFTWARE
diff --git a/release/scripts/modules/bpy_types.py b/release/scripts/modules/bpy_types.py
index 54fcc8faf46..e0e20d0f8c9 100644
--- a/release/scripts/modules/bpy_types.py
+++ b/release/scripts/modules/bpy_types.py
@@ -580,15 +580,6 @@ class MeshPolygon(StructRNA):
class Text(bpy_types.ID):
__slots__ = ()
- def as_string(self):
- """Return the text as a string."""
- return "\n".join(line.body for line in self.lines)
-
- def from_string(self, string):
- """Replace text with this string."""
- self.clear()
- self.write(string)
-
def as_module(self):
import bpy
from os.path import splitext, join
diff --git a/release/scripts/presets/keyconfig/keymap_data/blender_default.py b/release/scripts/presets/keyconfig/keymap_data/blender_default.py
index 83946fbf68f..5a12d5c79f9 100644
--- a/release/scripts/presets/keyconfig/keymap_data/blender_default.py
+++ b/release/scripts/presets/keyconfig/keymap_data/blender_default.py
@@ -1,5 +1,10 @@
# SPDX-License-Identifier: GPL-2.0-or-later
+__all__ = (
+ "generate_keymaps",
+ "Params",
+)
+
# ------------------------------------------------------------------------------
# Developer Notes
#
@@ -361,12 +366,12 @@ def _template_items_editmode_mesh_select_mode(params):
return [
(
"mesh.select_mode",
- {"type": k, "value": 'PRESS', **key_expand, **key_extend},
+ {"type": NUMBERS_1[i], "value": 'PRESS', **key_expand, **key_extend},
{"properties": [*prop_extend, *prop_expand, ("type", e)]}
)
for key_expand, prop_expand in (({}, ()), ({"ctrl": True}, (("use_expand", True),)))
for key_extend, prop_extend in (({}, ()), ({"shift": True}, (("use_extend", True),)))
- for k, e in (('ONE', 'VERT'), ('TWO', 'EDGE'), ('THREE', 'FACE'))
+ for i, e in enumerate(('VERT', 'EDGE', 'FACE'))
]
@@ -385,9 +390,9 @@ def _template_items_uv_select_mode(params):
*_template_items_editmode_mesh_select_mode(params),
# Hack to prevent fall-through, when sync select isn't enabled (and the island button isn't visible).
("mesh.select_mode", {"type": 'FOUR', "value": 'PRESS'}, None),
- *(("uv.select_mode", {"type": k, "value": 'PRESS'},
+ *(("uv.select_mode", {"type": NUMBERS_1[i], "value": 'PRESS'},
{"properties": [("type", e)]})
- for k, e in (('ONE', 'VERTEX'), ('TWO', 'EDGE'), ('THREE', 'FACE'), ('FOUR', 'ISLAND')))
+ for i, e in enumerate(('VERTEX', 'EDGE', 'FACE', 'ISLAND')))
]
@@ -421,13 +426,18 @@ def _template_items_change_frame(params):
# Tool System Templates
-def _template_items_tool_select(params, operator, cursor_operator, *, extend):
+def _template_items_tool_select(params, operator, cursor_operator, fallback, *, extend):
if params.select_mouse == 'LEFTMOUSE':
- # Immediate select without quick delay.
+ # By default use 'PRESS' for immediate select without quick delay.
+ # Fallback key-maps 'CLICK' since 'PRESS' events passes through (allowing either click or drag).
+ #
+ # NOTE: When the active (non-fallback) tool uses a key-map that activates it's primary tool on drag,
+ # it's important that this key-map uses click and not press. Otherwise it becomes impossible to use
+ # the tool without selecting elements under the cursor.
return [
- (operator, {"type": 'LEFTMOUSE', "value": 'PRESS'},
+ (operator, {"type": 'LEFTMOUSE', "value": 'CLICK' if fallback else 'PRESS'},
{"properties": [("deselect_all", True)]}),
- (operator, {"type": 'LEFTMOUSE', "value": 'PRESS', "shift": True},
+ (operator, {"type": 'LEFTMOUSE', "value": 'CLICK' if fallback else 'PRESS', "shift": True},
{"properties": [(extend, True)]}),
]
else:
@@ -1214,7 +1224,7 @@ def km_uv_editor(params):
("transform.shear", {"type": 'S', "value": 'PRESS', "shift": True, "ctrl": True, "alt": True}, None),
("transform.mirror", {"type": 'M', "value": 'PRESS', "ctrl": True}, None),
("wm.context_toggle", {"type": 'TAB', "value": 'PRESS', "shift": True},
- {"properties": [("data_path", 'tool_settings.use_snap')]}),
+ {"properties": [("data_path", 'tool_settings.use_snap_uv')]}),
("wm.context_menu_enum", {"type": 'TAB', "value": 'PRESS', "shift": True, "ctrl": True},
{"properties": [("data_path", 'tool_settings.snap_uv_element')]}),
*_template_items_context_menu("IMAGE_MT_uvs_context_menu", params.context_menu_event),
@@ -2079,7 +2089,7 @@ def km_node_editor(params):
{"type": params.select_mouse, "value": 'CLICK_DRAG', "alt": True},
{"properties": [("TRANSFORM_OT_translate", [("view2d_edge_pan", True)])]}),
("wm.context_toggle", {"type": 'TAB', "value": 'PRESS', "shift": True},
- {"properties": [("data_path", 'tool_settings.use_snap')]}),
+ {"properties": [("data_path", 'tool_settings.use_snap_node')]}),
("wm.context_menu_enum", {"type": 'TAB', "value": 'PRESS', "shift": True, "ctrl": True},
{"properties": [("data_path", 'tool_settings.snap_node_element')]}),
("wm.context_toggle", {"type": 'Z', "value": 'PRESS', "alt": True, "shift": True},
@@ -3627,12 +3637,9 @@ def km_grease_pencil_stroke_edit_mode(params):
# Vertex group menu
op_menu("GPENCIL_MT_gpencil_vertex_group", {"type": 'G', "value": 'PRESS', "ctrl": True}),
# Select mode
- ("gpencil.selectmode_toggle", {"type": 'ONE', "value": 'PRESS'},
- {"properties": [("mode", 0)]}),
- ("gpencil.selectmode_toggle", {"type": 'TWO', "value": 'PRESS'},
- {"properties": [("mode", 1)]}),
- ("gpencil.selectmode_toggle", {"type": 'THREE', "value": 'PRESS'},
- {"properties": [("mode", 2)]}),
+ *(("gpencil.selectmode_toggle", {"type": NUMBERS_1[i], "value": 'PRESS'},
+ {"properties": [("mode", i)]})
+ for i in range(3)),
# Active layer
op_menu("GPENCIL_MT_layer_active", {"type": 'Y', "value": 'PRESS'}),
# Keyframe menu
@@ -6082,10 +6089,8 @@ def km_sculpt_expand_modal(_params):
("RECURSION_STEP_GEODESIC", {"type": 'R', "value": 'PRESS'}, None),
("RECURSION_STEP_TOPOLOGY", {"type": 'R', "value": 'PRESS', "alt": True}, None),
("MOVE_TOGGLE", {"type": 'SPACE', "value": 'ANY', "any": True}, None),
- ("FALLOFF_GEODESICS", {"type": 'ONE', "value": 'PRESS', "any": True}, None),
- ("FALLOFF_TOPOLOGY", {"type": 'TWO', "value": 'PRESS', "any": True}, None),
- ("FALLOFF_TOPOLOGY_DIAGONALS", {"type": 'THREE', "value": 'PRESS', "any": True}, None),
- ("FALLOFF_SPHERICAL", {"type": 'FOUR', "value": 'PRESS', "any": True}, None),
+ *((e, {"type": NUMBERS_1[i], "value": 'PRESS', "any": True}, None) for i, e in enumerate(
+ ("FALLOFF_GEODESICS", "FALLOFF_TOPOLOGY", "FALLOFF_TOPOLOGY_DIAGONALS", "FALLOFF_SPHERICAL"))),
("SNAP_TOGGLE", {"type": 'LEFT_CTRL', "value": 'ANY'}, None),
("LOOP_COUNT_INCREASE", {"type": 'W', "value": 'PRESS', "any": True, "repeat": True}, None),
("LOOP_COUNT_DECREASE", {"type": 'Q', "value": 'PRESS', "any": True, "repeat": True}, None),
@@ -6280,7 +6285,7 @@ def km_image_editor_tool_uv_select(params, *, fallback):
{"space_type": 'IMAGE_EDITOR', "region_type": 'WINDOW'},
{"items": [
*([] if (fallback and (params.select_mouse == 'RIGHTMOUSE')) else _template_items_tool_select(
- params, "uv.select", "uv.cursor_set", extend="extend")),
+ params, "uv.select", "uv.cursor_set", fallback, extend="extend")),
*([] if (not params.use_fallback_tool_rmb) else _template_uv_select(
type=params.select_mouse, value=params.select_mouse_value, legacy=params.legacy)),
]},
@@ -6487,7 +6492,7 @@ def km_3d_view_tool_select(params, *, fallback):
{"space_type": 'VIEW_3D', "region_type": 'WINDOW'},
{"items": [
*([] if (fallback and (params.select_mouse == 'RIGHTMOUSE')) else _template_items_tool_select(
- params, "view3d.select", "view3d.cursor3d", extend="toggle")),
+ params, "view3d.select", "view3d.cursor3d", fallback, extend="toggle")),
*([] if (not params.use_fallback_tool_rmb) else _template_view3d_select(
type=params.select_mouse, value=params.select_mouse_value, legacy=params.legacy, exclude_mod="ctrl")),
]},
@@ -7399,7 +7404,7 @@ def km_3d_view_tool_edit_gpencil_select(params, *, fallback):
{"space_type": 'VIEW_3D', "region_type": 'WINDOW'},
{"items": [
*([] if (fallback and (params.select_mouse == 'RIGHTMOUSE')) else _template_items_tool_select(
- params, "gpencil.select", "view3d.cursor3d", extend="toggle")),
+ params, "gpencil.select", "view3d.cursor3d", fallback, extend="toggle")),
*([] if (not params.use_fallback_tool_rmb) else _template_view3d_gpencil_select(
type=params.select_mouse, value=params.select_mouse_value, legacy=params.legacy)),
]},
@@ -7537,7 +7542,7 @@ def km_3d_view_tool_sculpt_gpencil_select(params):
return (
"3D View Tool: Sculpt Gpencil, Tweak",
{"space_type": 'VIEW_3D', "region_type": 'WINDOW'},
- {"items": _template_items_tool_select(params, "gpencil.select", "view3d.cursor3d", extend="toggle")},
+ {"items": _template_items_tool_select(params, "gpencil.select", "view3d.cursor3d", False, extend="toggle")},
)
@@ -7577,7 +7582,7 @@ def km_sequencer_editor_tool_generic_select(params, *, fallback):
{"space_type": 'SEQUENCE_EDITOR', "region_type": 'WINDOW'},
{"items": [
*([] if (fallback and (params.select_mouse == 'RIGHTMOUSE')) else _template_items_tool_select(
- params, "sequencer.select", "sequencer.cursor_set", extend="toggle")),
+ params, "sequencer.select", "sequencer.cursor_set", fallback, extend="toggle")),
*([] if (not params.use_fallback_tool_rmb) else _template_sequencer_preview_select(
type=params.select_mouse, value=params.select_mouse_value, legacy=params.legacy)),
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 3469dbdc175..55ee91af7cd 100644
--- a/release/scripts/presets/keyconfig/keymap_data/industry_compatible_data.py
+++ b/release/scripts/presets/keyconfig/keymap_data/industry_compatible_data.py
@@ -1152,7 +1152,7 @@ def km_node_editor(params):
("node.move_detach_links_release", {"type": params.action_mouse, "value": 'CLICK_DRAG', "alt": True}, None),
("node.move_detach_links", {"type": 'LEFTMOUSE', "value": 'CLICK_DRAG', "alt": True}, None),
("wm.context_toggle", {"type": 'X', "value": 'PRESS'},
- {"properties": [("data_path", 'tool_settings.use_snap')]}),
+ {"properties": [("data_path", 'tool_settings.use_snap_node')]}),
])
return keymap
diff --git a/release/scripts/startup/bl_operators/clip.py b/release/scripts/startup/bl_operators/clip.py
index d83781b2ed8..23bf8a5cb60 100644
--- a/release/scripts/startup/bl_operators/clip.py
+++ b/release/scripts/startup/bl_operators/clip.py
@@ -107,8 +107,8 @@ def CLIP_default_settings_from_track(clip, track, framenr):
search[1] = search[1] * height
settings.default_correlation_min = track.correlation_min
- settings.default_pattern_size = max(pattern[0], pattern[1])
- settings.default_search_size = max(search[0], search[1])
+ settings.default_pattern_size = int(max(pattern[0], pattern[1]))
+ settings.default_search_size = int(max(search[0], search[1]))
settings.default_frames_limit = track.frames_limit
settings.default_pattern_match = track.pattern_match
settings.default_margin = track.margin
diff --git a/release/scripts/startup/bl_ui/properties_data_curve.py b/release/scripts/startup/bl_ui/properties_data_curve.py
index 26e5cfaae60..d6e21053e3b 100644
--- a/release/scripts/startup/bl_ui/properties_data_curve.py
+++ b/release/scripts/startup/bl_ui/properties_data_curve.py
@@ -289,7 +289,6 @@ class DATA_PT_active_spline(CurveButtonsPanelActive, Panel):
if is_surf:
subsub = sub.column()
- subsub.active = (not act_spline.use_cyclic_v)
subsub.prop(act_spline, "use_bezier_v", text="V")
sub = col.column(heading="Endpoint", align=True)
@@ -297,7 +296,6 @@ class DATA_PT_active_spline(CurveButtonsPanelActive, Panel):
if is_surf:
subsub = sub.column()
- subsub.active = (not act_spline.use_cyclic_v)
subsub.prop(act_spline, "use_endpoint_v", text="V")
sub = col.column(align=True)
@@ -322,6 +320,17 @@ class DATA_PT_active_spline(CurveButtonsPanelActive, Panel):
col.prop(act_spline, "radius_interpolation", text="Radius")
layout.prop(act_spline, "use_smooth")
+ if act_spline.type == 'NURBS':
+ col = None
+ for direction in range(2):
+ message = act_spline.valid_message(direction)
+ if not message:
+ continue
+ if col is None:
+ layout.separator()
+ col = layout.column(align=True)
+ col.label(text=message, icon='INFO')
+ del col
class DATA_PT_font(CurveButtonsPanelText, Panel):
diff --git a/release/scripts/startup/bl_ui/properties_data_curves.py b/release/scripts/startup/bl_ui/properties_data_curves.py
index 1bb5fc9afbe..4eefd5a0e0c 100644
--- a/release/scripts/startup/bl_ui/properties_data_curves.py
+++ b/release/scripts/startup/bl_ui/properties_data_curves.py
@@ -43,6 +43,8 @@ class DATA_PT_curves_surface(DataButtonsPanel, Panel):
layout = self.layout
ob = context.object
+ layout.use_property_split = True
+
layout.prop(ob.data, "surface")
diff --git a/release/scripts/startup/bl_ui/properties_render.py b/release/scripts/startup/bl_ui/properties_render.py
index b7522cbb04e..2a7af8357e7 100644
--- a/release/scripts/startup/bl_ui/properties_render.py
+++ b/release/scripts/startup/bl_ui/properties_render.py
@@ -484,6 +484,18 @@ class RENDER_PT_eevee_film(RenderButtonsPanel, Panel):
sub.prop(props, "overscan_size", text="")
+def draw_hair_settings(self, context):
+ layout = self.layout
+ scene = context.scene
+ rd = scene.render
+
+ layout.use_property_split = True
+ layout.use_property_decorate = False # No animation.
+
+ layout.prop(rd, "hair_type", text="Shape", expand=True)
+ layout.prop(rd, "hair_subdiv")
+
+
class RENDER_PT_eevee_hair(RenderButtonsPanel, Panel):
bl_label = "Hair"
bl_options = {'DEFAULT_CLOSED'}
@@ -494,14 +506,7 @@ class RENDER_PT_eevee_hair(RenderButtonsPanel, Panel):
return (context.engine in cls.COMPAT_ENGINES)
def draw(self, context):
- layout = self.layout
- scene = context.scene
- rd = scene.render
-
- layout.use_property_split = True
-
- layout.prop(rd, "hair_type", expand=True)
- layout.prop(rd, "hair_subdiv")
+ draw_hair_settings(self, context)
class RENDER_PT_eevee_performance(RenderButtonsPanel, Panel):
@@ -519,6 +524,7 @@ class RENDER_PT_eevee_performance(RenderButtonsPanel, Panel):
rd = scene.render
layout.use_property_split = True
+ layout.use_property_decorate = False # No animation.
layout.prop(rd, "use_high_quality_normals")
diff --git a/release/scripts/startup/bl_ui/space_image.py b/release/scripts/startup/bl_ui/space_image.py
index 65d624a253d..785a841a0e6 100644
--- a/release/scripts/startup/bl_ui/space_image.py
+++ b/release/scripts/startup/bl_ui/space_image.py
@@ -724,7 +724,7 @@ class IMAGE_HT_header(Header):
act_snap_uv_element = tool_settings.bl_rna.properties['snap_uv_element'].enum_items[snap_uv_element]
row = layout.row(align=True)
- row.prop(tool_settings, "use_snap", text="")
+ row.prop(tool_settings, "use_snap_uv", text="")
sub = row.row(align=True)
sub.popover(
diff --git a/release/scripts/startup/bl_ui/space_node.py b/release/scripts/startup/bl_ui/space_node.py
index a89b201d648..7c88006a4d6 100644
--- a/release/scripts/startup/bl_ui/space_node.py
+++ b/release/scripts/startup/bl_ui/space_node.py
@@ -185,7 +185,7 @@ class NODE_HT_header(Header):
# Snap
row = layout.row(align=True)
- row.prop(tool_settings, "use_snap", text="")
+ row.prop(tool_settings, "use_snap_node", text="")
row.prop(tool_settings, "snap_node_element", icon_only=True)
if tool_settings.snap_node_element != 'GRID':
row.prop(tool_settings, "snap_target", text="")
diff --git a/source/blender/blenkernel/BKE_blender_version.h b/source/blender/blenkernel/BKE_blender_version.h
index a8a851bb228..1639a564508 100644
--- a/source/blender/blenkernel/BKE_blender_version.h
+++ b/source/blender/blenkernel/BKE_blender_version.h
@@ -25,7 +25,7 @@ extern "C" {
/* Blender file format version. */
#define BLENDER_FILE_VERSION BLENDER_VERSION
-#define BLENDER_FILE_SUBVERSION 5
+#define BLENDER_FILE_SUBVERSION 6
/* 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_callbacks.h b/source/blender/blenkernel/BKE_callbacks.h
index 66089d29c45..2cd28c4dfa5 100644
--- a/source/blender/blenkernel/BKE_callbacks.h
+++ b/source/blender/blenkernel/BKE_callbacks.h
@@ -95,6 +95,8 @@ typedef enum {
BKE_CB_EVT_LOAD_FACTORY_USERDEF_POST,
BKE_CB_EVT_LOAD_FACTORY_STARTUP_POST,
BKE_CB_EVT_XR_SESSION_START_PRE,
+ BKE_CB_EVT_ANNOTATION_PRE,
+ BKE_CB_EVT_ANNOTATION_POST,
BKE_CB_EVT_TOT,
} eCbEvent;
diff --git a/source/blender/blenkernel/BKE_curve.h b/source/blender/blenkernel/BKE_curve.h
index 3f65ce83b3f..394d97223e3 100644
--- a/source/blender/blenkernel/BKE_curve.h
+++ b/source/blender/blenkernel/BKE_curve.h
@@ -269,6 +269,14 @@ void BKE_nurb_knot_calc_v(struct Nurb *nu);
bool BKE_nurb_check_valid_u(const struct Nurb *nu);
bool BKE_nurb_check_valid_v(const struct Nurb *nu);
bool BKE_nurb_check_valid_uv(const struct Nurb *nu);
+bool BKE_nurb_valid_message(int pnts,
+ short order,
+ short flag,
+ short type,
+ bool is_surf,
+ const char *dir,
+ char *message_dst,
+ size_t maxncpy);
bool BKE_nurb_order_clamp_u(struct Nurb *nu);
bool BKE_nurb_order_clamp_v(struct Nurb *nu);
diff --git a/source/blender/blenkernel/BKE_curves.hh b/source/blender/blenkernel/BKE_curves.hh
index f3d9090d16b..875cf48ed43 100644
--- a/source/blender/blenkernel/BKE_curves.hh
+++ b/source/blender/blenkernel/BKE_curves.hh
@@ -62,7 +62,9 @@ class CurvesGeometry : public ::CurvesGeometry {
*/
CurvesGeometry(int point_size, int curve_size);
CurvesGeometry(const CurvesGeometry &other);
+ CurvesGeometry(CurvesGeometry &&other);
CurvesGeometry &operator=(const CurvesGeometry &other);
+ CurvesGeometry &operator=(CurvesGeometry &&other);
~CurvesGeometry();
static CurvesGeometry &wrap(::CurvesGeometry &dna_struct)
@@ -95,6 +97,7 @@ class CurvesGeometry : public ::CurvesGeometry {
* Access a range of indices of point data for a specific curve.
*/
IndexRange range_for_curve(int index) const;
+ IndexRange range_for_curves(IndexRange curves) const;
/** The type (#CurveType) of each curve, or potentially a single if all are the same type. */
VArray<int8_t> curve_types() const;
@@ -147,6 +150,8 @@ class CurvesGeometry : public ::CurvesGeometry {
void update_customdata_pointers();
+ void remove_curves(IndexMask curves_to_delete);
+
/* --------------------------------------------------------------------
* Attributes.
*/
diff --git a/source/blender/blenkernel/BKE_customdata.h b/source/blender/blenkernel/BKE_customdata.h
index ea21fa9b404..940dc3c4f6c 100644
--- a/source/blender/blenkernel/BKE_customdata.h
+++ b/source/blender/blenkernel/BKE_customdata.h
@@ -716,7 +716,7 @@ void CustomData_data_transfer(const struct MeshPairRemap *me_remap,
* \param write_layers_buff: An optional buffer for r_write_layers (to avoid allocating it).
* \param write_layers_size: The size of pre-allocated \a write_layer_buff.
*
- * \warning After this funcion has ran, given custom data is no more valid from Blender POV
+ * \warning After this function has ran, given custom data is no more valid from Blender POV
* (its `totlayer` is invalid). This function shall always be called with localized data
* (as it is in write_meshes()).
*
diff --git a/source/blender/blenkernel/BKE_geometry_set.hh b/source/blender/blenkernel/BKE_geometry_set.hh
index f7767cc2a60..0e121068cbc 100644
--- a/source/blender/blenkernel/BKE_geometry_set.hh
+++ b/source/blender/blenkernel/BKE_geometry_set.hh
@@ -500,8 +500,8 @@ struct GeometrySet {
/**
* Clear the existing curves data-block and replace it with the given one.
*/
- void replace_curve(Curves *curves,
- GeometryOwnershipType ownership = GeometryOwnershipType::Owned);
+ void replace_curves(Curves *curves,
+ GeometryOwnershipType ownership = GeometryOwnershipType::Owned);
private:
/**
@@ -678,7 +678,7 @@ class CurveComponentLegacy : public GeometryComponent {
};
/**
- * A geometry component that stores a group of curves, corresponding the the #Curves and
+ * A geometry component that stores a group of curves, corresponding the #Curves and
* #CurvesGeometry types.
*/
class CurveComponent : public GeometryComponent {
diff --git a/source/blender/blenkernel/BKE_image.h b/source/blender/blenkernel/BKE_image.h
index b3001ecc880..ea0202e3b5f 100644
--- a/source/blender/blenkernel/BKE_image.h
+++ b/source/blender/blenkernel/BKE_image.h
@@ -371,7 +371,7 @@ void BKE_image_merge(struct Main *bmain, struct Image *dest, struct Image *sourc
bool BKE_image_scale(struct Image *image, int width, int height);
/**
- * Check if texture has alpha (depth=32).
+ * Check if texture has alpha (planes == 32 || planes == 16).
*/
bool BKE_image_has_alpha(struct Image *image);
@@ -486,7 +486,7 @@ bool BKE_image_is_dirty(struct Image *image);
void BKE_image_mark_dirty(struct Image *image, struct ImBuf *ibuf);
bool BKE_image_buffer_format_writable(struct ImBuf *ibuf);
-bool BKE_image_is_dirty_writable(struct Image *image, bool *is_format_writable);
+bool BKE_image_is_dirty_writable(struct Image *image, bool *r_is_writable);
/**
* Guess offset for the first frame in the sequence.
diff --git a/source/blender/blenkernel/BKE_image_partial_update.hh b/source/blender/blenkernel/BKE_image_partial_update.hh
index 45b08e17920..8cbb8819551 100644
--- a/source/blender/blenkernel/BKE_image_partial_update.hh
+++ b/source/blender/blenkernel/BKE_image_partial_update.hh
@@ -212,7 +212,7 @@ template<typename TileData = NoTileData> struct PartialUpdateChecker {
ePartialUpdateCollectResult result_code;
private:
- TileNumber last_tile_number;
+ TileNumber last_tile_number = 0;
public:
CollectResult(PartialUpdateChecker<TileData> *checker, ePartialUpdateCollectResult result_code)
diff --git a/source/blender/blenkernel/BKE_lib_id.h b/source/blender/blenkernel/BKE_lib_id.h
index c56cb616a9a..040be8d1280 100644
--- a/source/blender/blenkernel/BKE_lib_id.h
+++ b/source/blender/blenkernel/BKE_lib_id.h
@@ -150,11 +150,11 @@ enum {
LIB_ID_COPY_NO_PREVIEW = 1 << 17,
/** Copy runtime data caches. */
LIB_ID_COPY_CACHES = 1 << 18,
- /** Don't copy id->adt, used by ID datablock localization routines. */
+ /** Don't copy id->adt, used by ID data-block localization routines. */
LIB_ID_COPY_NO_ANIMDATA = 1 << 19,
/** Mesh: Reference CD data layers instead of doing real copy - USE WITH CAUTION! */
LIB_ID_COPY_CD_REFERENCE = 1 << 20,
- /** Do not copy id->override_library, used by ID datablock override routines. */
+ /** Do not copy id->override_library, used by ID data-block override routines. */
LIB_ID_COPY_NO_LIB_OVERRIDE = 1 << 21,
/** When copying local sub-data (like constraints or modifiers), do not set their "library
* override local data" flag. */
@@ -162,11 +162,11 @@ enum {
/* *** XXX Hackish/not-so-nice specific behaviors needed for some corner cases. *** */
/* *** Ideally we should not have those, but we need them for now... *** */
- /** EXCEPTION! Deep-copy actions used by animdata of copied ID. */
+ /** EXCEPTION! Deep-copy actions used by animation-data of copied ID. */
LIB_ID_COPY_ACTIONS = 1 << 24,
- /** Keep the library pointer when copying datablock outside of bmain. */
+ /** Keep the library pointer when copying data-block outside of bmain. */
LIB_ID_COPY_KEEP_LIB = 1 << 25,
- /** EXCEPTION! Deep-copy shapekeys used by copied obdata ID. */
+ /** EXCEPTION! Deep-copy shape-keys used by copied obdata ID. */
LIB_ID_COPY_SHAPEKEY = 1 << 26,
/** EXCEPTION! Specific deep-copy of node trees used e.g. for rendering purposes. */
LIB_ID_COPY_NODETREE_LOCALIZE = 1 << 27,
@@ -177,7 +177,7 @@ enum {
LIB_ID_COPY_RIGID_BODY_NO_COLLECTION_HANDLING = 1 << 28,
/* *** Helper 'defines' gathering most common flag sets. *** */
- /** Shapekeys are not real ID's, more like local data to geometry IDs... */
+ /** Shape-keys are not real ID's, more like local data to geometry IDs. */
LIB_ID_COPY_DEFAULT = LIB_ID_COPY_SHAPEKEY,
/** Create a local, outside of bmain, data-block to work on. */
@@ -412,7 +412,7 @@ struct ID *BKE_id_copy(struct Main *bmain, const struct ID *id);
*
* There are exceptions though:
* - Embedded IDs (root node trees and master collections) are always copied with their owner.
- * - If #LIB_ID_COPY_ACTIONS is defined, actions used by animdata will be duplicated.
+ * - If #LIB_ID_COPY_ACTIONS is defined, actions used by anim-data will be duplicated.
* - If #LIB_ID_COPY_SHAPEKEY is defined, shape-keys will be duplicated.
* - If #LIB_ID_CREATE_LOCAL is defined, root node trees will be deep-duplicated recursively.
*
diff --git a/source/blender/blenkernel/BKE_spline.hh b/source/blender/blenkernel/BKE_spline.hh
index 42b4702ee44..1e3134020c6 100644
--- a/source/blender/blenkernel/BKE_spline.hh
+++ b/source/blender/blenkernel/BKE_spline.hh
@@ -449,12 +449,6 @@ class BezierSpline final : public Spline {
*/
class NURBSpline final : public Spline {
public:
- enum class KnotsMode {
- Normal,
- EndPoint,
- Bezier,
- };
-
/** Method used to recalculate the knots vector when points are added or removed. */
KnotsMode knots_mode;
diff --git a/source/blender/blenkernel/BKE_text.h b/source/blender/blenkernel/BKE_text.h
index e833b4a14bb..bc6df18ce25 100644
--- a/source/blender/blenkernel/BKE_text.h
+++ b/source/blender/blenkernel/BKE_text.h
@@ -14,6 +14,8 @@ struct Main;
struct Text;
struct TextLine;
+#include "BLI_compiler_attrs.h"
+
/**
* \note caller must handle `compiled` member.
*/
@@ -55,7 +57,8 @@ void BKE_text_write(struct Text *text, const char *str);
int BKE_text_file_modified_check(struct Text *text);
void BKE_text_file_modified_ignore(struct Text *text);
-char *txt_to_buf(struct Text *text, int *r_buf_strlen);
+char *txt_to_buf(struct Text *text, int *r_buf_strlen)
+ ATTR_NONNULL(1, 2) ATTR_WARN_UNUSED_RESULT ATTR_RETURNS_NONNULL;
void txt_clean_text(struct Text *text);
void txt_order_cursors(struct Text *text, bool reverse);
int txt_find_string(struct Text *text, const char *findstr, int wrap, int match_case);
@@ -135,11 +138,12 @@ enum {
/**
* Create a buffer, the only requirement is #txt_from_buf_for_undo can decode it.
*/
-char *txt_to_buf_for_undo(struct Text *text, int *r_buf_len);
+char *txt_to_buf_for_undo(struct Text *text, int *r_buf_len)
+ ATTR_NONNULL(1, 2) ATTR_WARN_UNUSED_RESULT ATTR_RETURNS_NONNULL;
/**
* Decode a buffer from #txt_to_buf_for_undo.
*/
-void txt_from_buf_for_undo(struct Text *text, const char *buf, int buf_len);
+void txt_from_buf_for_undo(struct Text *text, const char *buf, int buf_len) ATTR_NONNULL(1, 2);
#ifdef __cplusplus
}
diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt
index a12a956cbf5..bd632380ada 100644
--- a/source/blender/blenkernel/CMakeLists.txt
+++ b/source/blender/blenkernel/CMakeLists.txt
@@ -150,7 +150,7 @@ set(SRC
intern/idprop_serialize.cc
intern/idprop_utils.c
intern/idtype.c
- intern/image.c
+ intern/image.cc
intern/image_partial_update.cc
intern/image_gen.c
intern/image_gpu.cc
@@ -807,6 +807,7 @@ if(WITH_GTESTS)
intern/asset_test.cc
intern/bpath_test.cc
intern/cryptomatte_test.cc
+ intern/curves_geometry_test.cc
intern/fcurve_test.cc
intern/idprop_serialize_test.cc
intern/image_partial_update_test.cc
diff --git a/source/blender/blenkernel/intern/DerivedMesh.cc b/source/blender/blenkernel/intern/DerivedMesh.cc
index 39074a5c75f..904a43a7c28 100644
--- a/source/blender/blenkernel/intern/DerivedMesh.cc
+++ b/source/blender/blenkernel/intern/DerivedMesh.cc
@@ -1468,7 +1468,7 @@ static void editbmesh_calc_modifiers(struct Depsgraph *depsgraph,
/* set the DerivedMesh to only copy needed data */
CustomData_MeshMasks_update(&mask, &append_mask);
- /* XXX WHAT? ovewrites mask ??? */
+ /* XXX WHAT? overwrites mask ??? */
/* CD_MASK_ORCO may have been cleared above */
mask = md_datamask->mask;
mask.vmask |= CD_MASK_ORIGINDEX;
diff --git a/source/blender/blenkernel/intern/armature_test.cc b/source/blender/blenkernel/intern/armature_test.cc
index 7475e6f36d4..4d266c8493a 100644
--- a/source/blender/blenkernel/intern/armature_test.cc
+++ b/source/blender/blenkernel/intern/armature_test.cc
@@ -285,7 +285,7 @@ TEST(vec_roll_to_mat3_normalized, Roll1)
const float expected_roll_mat[3][3] = {{0.211324856f, 0.577350259f, -0.788675129f},
{0.577350259f, 0.577350259f, 0.577350259f},
{0.788675129f, -0.577350259f, -0.211324856f}};
- test_vec_roll_to_mat3_normalized(input, float(M_PI * 0.5), expected_roll_mat);
+ test_vec_roll_to_mat3_normalized(input, float(M_PI_2), expected_roll_mat);
}
/** Test that the matrix is orthogonal for an input close to -Y. */
diff --git a/source/blender/blenkernel/intern/blendfile_link_append.c b/source/blender/blenkernel/intern/blendfile_link_append.c
index ce36bfe81be..294fe57c923 100644
--- a/source/blender/blenkernel/intern/blendfile_link_append.c
+++ b/source/blender/blenkernel/intern/blendfile_link_append.c
@@ -926,7 +926,7 @@ static int foreach_libblock_link_append_callback(LibraryIDLinkCallbackData *cb_d
* unfortunately they can use fully linkable valid IDs too, like actions. Those need to be
* processed, so we need to recursively deal with them here. */
/* NOTE: Since we are by-passing checks in `BKE_library_foreach_ID_link` by manually calling it
- * recursively, we need to take care of potential recursion cases ourselves (e.g.animdata of
+ * recursively, we need to take care of potential recursion cases ourselves (e.g.anim-data of
* shape-key referencing the shape-key itself).
* NOTE: in case both IDs (owner and 'used' ones) are non-linkable, we can assume we can break
* the dependency here. Indeed, either they are both linked in another way (through their own
diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c
index 2afe4dda35c..7a97139748f 100644
--- a/source/blender/blenkernel/intern/constraint.c
+++ b/source/blender/blenkernel/intern/constraint.c
@@ -5515,7 +5515,7 @@ static void constraints_init_typeinfo(void)
constraintsTypeInfo[12] = &CTI_ACTION; /* Action Constraint */
constraintsTypeInfo[13] = &CTI_LOCKTRACK; /* Locked-Track Constraint */
constraintsTypeInfo[14] = &CTI_DISTLIMIT; /* Limit Distance Constraint */
- constraintsTypeInfo[15] = &CTI_STRETCHTO; /* StretchTo Constaint */
+ constraintsTypeInfo[15] = &CTI_STRETCHTO; /* StretchTo Constraint */
constraintsTypeInfo[16] = &CTI_MINMAX; /* Floor Constraint */
/* constraintsTypeInfo[17] = &CTI_RIGIDBODYJOINT; */ /* RigidBody Constraint - Deprecated */
constraintsTypeInfo[18] = &CTI_CLAMPTO; /* ClampTo Constraint */
diff --git a/source/blender/blenkernel/intern/curve.cc b/source/blender/blenkernel/intern/curve.cc
index 6b7f7af44e8..0b619c1a969 100644
--- a/source/blender/blenkernel/intern/curve.cc
+++ b/source/blender/blenkernel/intern/curve.cc
@@ -17,8 +17,8 @@
#include "BLI_index_range.hh"
#include "BLI_math.h"
#include "BLI_math_vec_types.hh"
+#include "BLI_string.h"
#include "BLI_utildefines.h"
-
#include "BLT_translation.h"
/* Allow using deprecated functionality for .blend file I/O. */
@@ -1156,12 +1156,13 @@ void BKE_nurb_bpoint_calc_plane(struct Nurb *nu, BPoint *bp, float r_plane[3])
static void calcknots(float *knots, const int pnts, const short order, const short flag)
{
const bool is_cyclic = flag & CU_NURB_CYCLIC;
- const bool is_bezier = flag & CU_NURB_BEZIER && !(flag & CU_NURB_ENDPOINT);
- const bool is_end_point = flag & CU_NURB_ENDPOINT && !(flag & CU_NURB_BEZIER);
+ const bool is_bezier = flag & CU_NURB_BEZIER;
+ const bool is_end_point = flag & CU_NURB_ENDPOINT;
/* Inner knots are always repeated once except on Bezier case. */
const int repeat_inner = is_bezier ? order - 1 : 1;
/* How many times to repeat 0.0 at the beginning of knot. */
- const int head = is_end_point && !is_cyclic ? order : (is_bezier ? order / 2 : 1);
+ const int head = is_end_point ? (order - (is_cyclic ? 1 : 0)) :
+ (is_bezier ? min_ii(2, repeat_inner) : 1);
/* Number of knots replicating widths of the starting knots.
* Covers both Cyclic and EndPoint cases. */
const int tail = is_cyclic ? 2 * order - 1 : (is_end_point ? order : 0);
@@ -1171,11 +1172,17 @@ static void calcknots(float *knots, const int pnts, const short order, const sho
int r = head;
float current = 0.0f;
- for (const int i : IndexRange(knot_count - tail)) {
+ const int offset = is_end_point && is_cyclic ? 1 : 0;
+ if (offset) {
+ knots[0] = current;
+ current += 1.0f;
+ }
+
+ for (const int i : IndexRange(offset, knot_count - offset - tail)) {
knots[i] = current;
r--;
if (r == 0) {
- current += 1.0;
+ current += 1.0f;
r = repeat_inner;
}
}
@@ -4693,59 +4700,56 @@ void BKE_curve_nurbs_key_vert_tilts_apply(ListBase *lb, const float *key)
}
}
-bool BKE_nurb_check_valid_u(const Nurb *nu)
+bool BKE_nurb_valid_message(const int pnts,
+ const short order,
+ const short flag,
+ const short type,
+ const bool is_surf,
+ const char *dir,
+ char *message_dst,
+ const size_t maxncpy)
{
- if (nu->pntsu <= 1) {
- return false;
- }
- if (nu->type != CU_NURBS) {
- return true; /* not a nurb, lets assume its valid */
- }
+ const char *msg_template = "";
+ uint16_t points_needed = 0;
- if (nu->pntsu < nu->orderu) {
- return false;
+ if (pnts <= 1) {
+ msg_template = TIP_("At least two points required.");
}
- if (((nu->flagu & CU_NURB_CYCLIC) == 0) && (nu->flagu & CU_NURB_BEZIER)) {
- /* Bezier U Endpoints */
- if (nu->orderu == 4) {
- if (nu->pntsu < 5) {
- return false; /* bezier with 4 orderu needs 5 points */
- }
+ else if (type == CU_NURBS) {
+ if (pnts < order) {
+ msg_template = TIP_("Must have more control points than Order");
}
- else {
- if (nu->orderu != 3) {
- return false; /* order must be 3 or 4 */
+ else if (flag & CU_NURB_BEZIER) {
+ if (flag & CU_NURB_CYCLIC) {
+ const uint16_t remainder = pnts % (order - 1);
+ points_needed = remainder > 0 ? order - 1 - remainder : 0;
+ }
+ else if (((flag & CU_NURB_ENDPOINT) == 0) && pnts <= order) {
+ points_needed = order + 1 - pnts;
+ }
+ if (points_needed) {
+ msg_template = is_surf ? TIP_("%d more %s row(s) needed for Bezier") :
+ TIP_("%d more point(s) needed for Bezier");
}
}
}
- return true;
+
+ if (message_dst) {
+ BLI_snprintf(message_dst, maxncpy, msg_template, points_needed, dir);
+ }
+ return msg_template[0];
}
-bool BKE_nurb_check_valid_v(const Nurb *nu)
+
+bool BKE_nurb_check_valid_u(const Nurb *nu)
{
- if (nu->pntsv <= 1) {
- return false;
- }
- if (nu->type != CU_NURBS) {
- return true; /* not a nurb, lets assume its valid */
- }
+ return !BKE_nurb_valid_message(
+ nu->pntsu, nu->orderu, nu->flagu, nu->type, nu->pntsv > 1, "U", nullptr, 0);
+}
- if (nu->pntsv < nu->orderv) {
- return false;
- }
- if (((nu->flagv & CU_NURB_CYCLIC) == 0) && (nu->flagv & CU_NURB_BEZIER)) {
- /* Bezier V Endpoints */
- if (nu->orderv == 4) {
- if (nu->pntsv < 5) {
- return false; /* bezier with 4 orderu needs 5 points */
- }
- }
- else {
- if (nu->orderv != 3) {
- return false; /* order must be 3 or 4 */
- }
- }
- }
- return true;
+bool BKE_nurb_check_valid_v(const Nurb *nu)
+{
+ return !BKE_nurb_valid_message(
+ nu->pntsv, nu->orderv, nu->flagv, nu->type, nu->pntsv > 1, "V", nullptr, 0);
}
bool BKE_nurb_check_valid_uv(const Nurb *nu)
@@ -4767,10 +4771,6 @@ bool BKE_nurb_order_clamp_u(struct Nurb *nu)
nu->orderu = max_ii(2, nu->pntsu);
changed = true;
}
- if (((nu->flagu & CU_NURB_CYCLIC) == 0) && (nu->flagu & CU_NURB_BEZIER)) {
- CLAMP(nu->orderu, 3, 4);
- changed = true;
- }
return changed;
}
@@ -4781,10 +4781,6 @@ bool BKE_nurb_order_clamp_v(struct Nurb *nu)
nu->orderv = max_ii(2, nu->pntsv);
changed = true;
}
- if (((nu->flagv & CU_NURB_CYCLIC) == 0) && (nu->flagv & CU_NURB_BEZIER)) {
- CLAMP(nu->orderv, 3, 4);
- changed = true;
- }
return changed;
}
diff --git a/source/blender/blenkernel/intern/curve_eval.cc b/source/blender/blenkernel/intern/curve_eval.cc
index d6525a11cff..191a510947e 100644
--- a/source/blender/blenkernel/intern/curve_eval.cc
+++ b/source/blender/blenkernel/intern/curve_eval.cc
@@ -203,19 +203,21 @@ static Spline::NormalCalculationMode normal_mode_from_dna_curve(const int twist_
return Spline::NormalCalculationMode::Minimum;
}
-static NURBSpline::KnotsMode knots_mode_from_dna_nurb(const short flag)
+static KnotsMode knots_mode_from_dna_nurb(const short flag)
{
switch (flag & (CU_NURB_ENDPOINT | CU_NURB_BEZIER)) {
case CU_NURB_ENDPOINT:
- return NURBSpline::KnotsMode::EndPoint;
+ return NURBS_KNOT_MODE_ENDPOINT;
case CU_NURB_BEZIER:
- return NURBSpline::KnotsMode::Bezier;
+ return NURBS_KNOT_MODE_BEZIER;
+ case CU_NURB_ENDPOINT | CU_NURB_BEZIER:
+ return NURBS_KNOT_MODE_ENDPOINT_BEZIER;
default:
- return NURBSpline::KnotsMode::Normal;
+ return NURBS_KNOT_MODE_NORMAL;
}
BLI_assert_unreachable();
- return NURBSpline::KnotsMode::Normal;
+ return NURBS_KNOT_MODE_NORMAL;
}
static SplinePtr spline_from_dna_bezier(const Nurb &nurb)
@@ -419,8 +421,7 @@ std::unique_ptr<CurveEval> curves_to_curve_eval(const Curves &curves)
nurb_spline->resize(point_range.size());
nurb_spline->weights().copy_from(nurbs_weights.slice(point_range));
nurb_spline->set_order(nurbs_orders[curve_index]);
- nurb_spline->knots_mode = static_cast<NURBSpline::KnotsMode>(
- nurbs_knots_modes[curve_index]);
+ nurb_spline->knots_mode = static_cast<KnotsMode>(nurbs_knots_modes[curve_index]);
spline = std::move(nurb_spline);
break;
@@ -436,6 +437,8 @@ std::unique_ptr<CurveEval> curves_to_curve_eval(const Curves &curves)
curve_eval->add_spline(std::move(spline));
}
+ curve_eval->attributes.reallocate(curve_eval->splines().size());
+
CurveComponentLegacy dst_component;
dst_component.replace(curve_eval.get(), GeometryOwnershipType::Editable);
diff --git a/source/blender/blenkernel/intern/curves_geometry.cc b/source/blender/blenkernel/intern/curves_geometry.cc
index 3eea579230a..dd91e788e5a 100644
--- a/source/blender/blenkernel/intern/curves_geometry.cc
+++ b/source/blender/blenkernel/intern/curves_geometry.cc
@@ -84,6 +84,42 @@ CurvesGeometry &CurvesGeometry::operator=(const CurvesGeometry &other)
return *this;
}
+/* The source should be empty, but in a valid state so that using it further will work. */
+static void move_curves_geometry(CurvesGeometry &dst, CurvesGeometry &src)
+{
+ dst.point_size = src.point_size;
+ std::swap(dst.point_data, src.point_data);
+ CustomData_free(&src.point_data, src.point_size);
+ src.point_size = 0;
+
+ dst.curve_size = src.curve_size;
+ std::swap(dst.curve_data, dst.curve_data);
+ CustomData_free(&src.curve_data, src.curve_size);
+ src.curve_size = 0;
+
+ std::swap(dst.curve_offsets, src.curve_offsets);
+ MEM_SAFE_FREE(src.curve_offsets);
+
+ std::swap(dst.runtime, src.runtime);
+
+ src.update_customdata_pointers();
+ dst.update_customdata_pointers();
+}
+
+CurvesGeometry::CurvesGeometry(CurvesGeometry &&other)
+ : CurvesGeometry(other.point_size, other.curve_size)
+{
+ move_curves_geometry(*this, other);
+}
+
+CurvesGeometry &CurvesGeometry::operator=(CurvesGeometry &&other)
+{
+ if (this != &other) {
+ move_curves_geometry(*this, other);
+ }
+ return *this;
+}
+
CurvesGeometry::~CurvesGeometry()
{
CustomData_free(&this->point_data, this->point_size);
@@ -124,29 +160,83 @@ int CurvesGeometry::evaluated_points_size() const
IndexRange CurvesGeometry::range_for_curve(const int index) const
{
+ BLI_assert(this->curve_size > 0);
+ BLI_assert(this->curve_offsets != nullptr);
const int offset = this->curve_offsets[index];
const int offset_next = this->curve_offsets[index + 1];
return {offset, offset_next - offset};
}
-VArray<int8_t> CurvesGeometry::curve_types() const
+IndexRange CurvesGeometry::range_for_curves(const IndexRange curves) const
+{
+ BLI_assert(this->curve_size > 0);
+ BLI_assert(this->curve_offsets != nullptr);
+ const int offset = this->curve_offsets[curves.start()];
+ const int offset_next = this->curve_offsets[curves.one_after_last()];
+ return {offset, offset_next - offset};
+}
+
+static int domain_size(const CurvesGeometry &curves, const AttributeDomain domain)
{
- if (const int8_t *data = (const int8_t *)CustomData_get_layer_named(
- &this->curve_data, CD_PROP_INT8, ATTR_CURVE_TYPE.c_str())) {
- return VArray<int8_t>::ForSpan({data, this->curve_size});
+ return domain == ATTR_DOMAIN_POINT ? curves.points_size() : curves.curves_size();
+}
+
+static CustomData &domain_custom_data(CurvesGeometry &curves, const AttributeDomain domain)
+{
+ return domain == ATTR_DOMAIN_POINT ? curves.point_data : curves.curve_data;
+}
+
+static const CustomData &domain_custom_data(const CurvesGeometry &curves,
+ const AttributeDomain domain)
+{
+ return domain == ATTR_DOMAIN_POINT ? curves.point_data : curves.curve_data;
+}
+
+template<typename T>
+static VArray<T> get_varray_attribute(const CurvesGeometry &curves,
+ const AttributeDomain domain,
+ const StringRefNull name,
+ const T default_value)
+{
+ const int size = domain_size(curves, domain);
+ const CustomDataType type = cpp_type_to_custom_data_type(CPPType::get<T>());
+ const CustomData &custom_data = domain_custom_data(curves, domain);
+
+ const T *data = (const T *)CustomData_get_layer_named(&custom_data, type, name.c_str());
+ if (data != nullptr) {
+ return VArray<T>::ForSpan(Span<T>(data, size));
+ }
+ return VArray<T>::ForSingle(default_value, size);
+}
+
+template<typename T>
+static MutableSpan<T> get_mutable_attribute(CurvesGeometry &curves,
+ const AttributeDomain domain,
+ const StringRefNull name)
+{
+ const int size = domain_size(curves, domain);
+ const CustomDataType type = cpp_type_to_custom_data_type(CPPType::get<T>());
+ CustomData &custom_data = domain_custom_data(curves, domain);
+
+ T *data = (T *)CustomData_duplicate_referenced_layer_named(
+ &custom_data, type, name.c_str(), size);
+ if (data != nullptr) {
+ return {data, size};
}
- return VArray<int8_t>::ForSingle(CURVE_TYPE_CATMULL_ROM, this->curve_size);
+ data = (T *)CustomData_add_layer_named(
+ &custom_data, type, CD_CALLOC, nullptr, size, name.c_str());
+ return {data, size};
+}
+
+VArray<int8_t> CurvesGeometry::curve_types() const
+{
+ return get_varray_attribute<int8_t>(
+ *this, ATTR_DOMAIN_CURVE, ATTR_CURVE_TYPE, CURVE_TYPE_CATMULL_ROM);
}
MutableSpan<int8_t> CurvesGeometry::curve_types()
{
- int8_t *data = (int8_t *)CustomData_add_layer_named(&this->curve_data,
- CD_PROP_INT8,
- CD_CALLOC,
- nullptr,
- this->curve_size,
- ATTR_CURVE_TYPE.c_str());
- return {data, this->curve_size};
+ return get_mutable_attribute<int8_t>(*this, ATTR_DOMAIN_CURVE, ATTR_CURVE_TYPE);
}
MutableSpan<float3> CurvesGeometry::positions()
@@ -171,19 +261,12 @@ Span<int> CurvesGeometry::offsets() const
VArray<bool> CurvesGeometry::cyclic() const
{
- const bool *data = (const bool *)CustomData_get_layer_named(
- &this->curve_data, CD_PROP_INT8, ATTR_CURVE_TYPE.c_str());
- if (data != nullptr) {
- return VArray<bool>::ForSpan(Span(data, this->curve_size));
- }
- return VArray<bool>::ForSingle(false, this->curve_size);
+ return get_varray_attribute<bool>(*this, ATTR_DOMAIN_CURVE, ATTR_CYCLIC, false);
}
MutableSpan<bool> CurvesGeometry::cyclic()
{
- bool *data = (bool *)CustomData_add_layer_named(
- &this->curve_data, CD_PROP_BOOL, CD_CALLOC, nullptr, this->curve_size, ATTR_CYCLIC.c_str());
- return {data, this->curve_size};
+ return get_mutable_attribute<bool>(*this, ATTR_DOMAIN_CURVE, ATTR_CYCLIC);
}
void CurvesGeometry::resize(const int point_size, const int curve_size)
@@ -269,6 +352,134 @@ void CurvesGeometry::update_customdata_pointers()
&this->point_data, CD_PROP_INT8, ATTR_CURVE_TYPE.c_str());
}
+static void *ensure_customdata_layer(CustomData &custom_data,
+ const StringRefNull name,
+ const CustomDataType data_type,
+ const int tot_elements)
+{
+ for (const int other_layer_i : IndexRange(custom_data.totlayer)) {
+ CustomDataLayer &new_layer = custom_data.layers[other_layer_i];
+ if (name == StringRef(new_layer.name)) {
+ return new_layer.data;
+ }
+ }
+ return CustomData_add_layer_named(
+ &custom_data, data_type, CD_DEFAULT, nullptr, tot_elements, name.c_str());
+}
+
+static CurvesGeometry copy_with_removed_curves(const CurvesGeometry &curves,
+ const IndexMask curves_to_delete)
+{
+ const Span<int> old_offsets = curves.offsets();
+ const Vector<IndexRange> old_curve_ranges = curves_to_delete.extract_ranges_invert(
+ curves.curves_range(), nullptr);
+ Vector<IndexRange> new_curve_ranges;
+ Vector<IndexRange> old_point_ranges;
+ Vector<IndexRange> new_point_ranges;
+ int new_tot_points = 0;
+ int new_tot_curves = 0;
+ for (const IndexRange &curve_range : old_curve_ranges) {
+ new_curve_ranges.append(IndexRange(new_tot_curves, curve_range.size()));
+ new_tot_curves += curve_range.size();
+
+ const IndexRange old_point_range = curves.range_for_curves(curve_range);
+ old_point_ranges.append(old_point_range);
+ new_point_ranges.append(IndexRange(new_tot_points, old_point_range.size()));
+ new_tot_points += old_point_range.size();
+ }
+
+ CurvesGeometry new_curves{new_tot_points, new_tot_curves};
+
+ threading::parallel_invoke(
+ /* Initialize curve offsets. */
+ [&]() {
+ MutableSpan<int> new_offsets = new_curves.offsets();
+ new_offsets.last() = new_tot_points;
+ threading::parallel_for(
+ old_curve_ranges.index_range(), 128, [&](const IndexRange ranges_range) {
+ for (const int range_i : ranges_range) {
+ const IndexRange old_curve_range = old_curve_ranges[range_i];
+ const IndexRange new_curve_range = new_curve_ranges[range_i];
+ const IndexRange old_point_range = old_point_ranges[range_i];
+ const IndexRange new_point_range = new_point_ranges[range_i];
+ const int offset_shift = new_point_range.start() - old_point_range.start();
+ const int curves_in_range = old_curve_range.size();
+ threading::parallel_for(
+ IndexRange(curves_in_range), 512, [&](const IndexRange range) {
+ for (const int i : range) {
+ const int old_curve_i = old_curve_range[i];
+ const int new_curve_i = new_curve_range[i];
+ const int old_offset = old_offsets[old_curve_i];
+ const int new_offset = old_offset + offset_shift;
+ new_offsets[new_curve_i] = new_offset;
+ }
+ });
+ }
+ });
+ },
+ /* Copy over point attributes. */
+ [&]() {
+ const CustomData &old_point_data = curves.point_data;
+ CustomData &new_point_data = new_curves.point_data;
+ for (const int layer_i : IndexRange(old_point_data.totlayer)) {
+ const CustomDataLayer &old_layer = old_point_data.layers[layer_i];
+ const CustomDataType data_type = static_cast<CustomDataType>(old_layer.type);
+ const CPPType &type = *bke::custom_data_type_to_cpp_type(data_type);
+
+ const void *src_buffer = old_layer.data;
+ void *dst_buffer = ensure_customdata_layer(
+ new_point_data, old_layer.name, data_type, new_tot_points);
+
+ threading::parallel_for(
+ old_curve_ranges.index_range(), 128, [&](const IndexRange ranges_range) {
+ for (const int range_i : ranges_range) {
+ const IndexRange old_point_range = old_point_ranges[range_i];
+ const IndexRange new_point_range = new_point_ranges[range_i];
+
+ type.copy_construct_n(
+ POINTER_OFFSET(src_buffer, type.size() * old_point_range.start()),
+ POINTER_OFFSET(dst_buffer, type.size() * new_point_range.start()),
+ old_point_range.size());
+ }
+ });
+ }
+ },
+ /* Copy over curve attributes. */
+ [&]() {
+ const CustomData &old_curve_data = curves.curve_data;
+ CustomData &new_curve_data = new_curves.curve_data;
+ for (const int layer_i : IndexRange(old_curve_data.totlayer)) {
+ const CustomDataLayer &old_layer = old_curve_data.layers[layer_i];
+ const CustomDataType data_type = static_cast<CustomDataType>(old_layer.type);
+ const CPPType &type = *bke::custom_data_type_to_cpp_type(data_type);
+
+ const void *src_buffer = old_layer.data;
+ void *dst_buffer = ensure_customdata_layer(
+ new_curve_data, old_layer.name, data_type, new_tot_points);
+
+ threading::parallel_for(
+ old_curve_ranges.index_range(), 128, [&](const IndexRange ranges_range) {
+ for (const int range_i : ranges_range) {
+ const IndexRange old_curve_range = old_curve_ranges[range_i];
+ const IndexRange new_curve_range = new_curve_ranges[range_i];
+
+ type.copy_construct_n(
+ POINTER_OFFSET(src_buffer, type.size() * old_curve_range.start()),
+ POINTER_OFFSET(dst_buffer, type.size() * new_curve_range.start()),
+ old_curve_range.size());
+ }
+ });
+ }
+ });
+
+ return new_curves;
+}
+
+void CurvesGeometry::remove_curves(const IndexMask curves_to_delete)
+{
+ *this = copy_with_removed_curves(*this, curves_to_delete);
+}
+
/** \} */
/* -------------------------------------------------------------------- */
diff --git a/source/blender/blenkernel/intern/curves_geometry_test.cc b/source/blender/blenkernel/intern/curves_geometry_test.cc
new file mode 100644
index 00000000000..3a43c0c8102
--- /dev/null
+++ b/source/blender/blenkernel/intern/curves_geometry_test.cc
@@ -0,0 +1,66 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+/** \file
+ * \ingroup bke
+ */
+
+#include "BKE_curves.hh"
+
+#include "testing/testing.h"
+
+namespace blender::bke::tests {
+
+static CurvesGeometry create_basic_curves(const int points_size, const int curves_size)
+{
+ CurvesGeometry curves(points_size, curves_size);
+
+ const int curve_length = points_size / curves_size;
+ for (const int i : curves.curves_range()) {
+ curves.offsets()[i] = points_size * curve_length;
+ }
+ curves.offsets().last() = points_size;
+
+ for (const int i : curves.points_range()) {
+ curves.positions()[i] = {float(i), float(i % curve_length), 0.0f};
+ }
+
+ return curves;
+}
+
+TEST(curves_geometry, Empty)
+{
+ CurvesGeometry empty(0, 0);
+ empty.cyclic();
+ float3 min;
+ float3 max;
+ EXPECT_FALSE(empty.bounds_min_max(min, max));
+}
+
+TEST(curves_geometry, Move)
+{
+ CurvesGeometry curves = create_basic_curves(100, 10);
+
+ const int *offsets_data = curves.offsets().data();
+ const float3 *positions_data = curves.positions().data();
+
+ CurvesGeometry other = std::move(curves);
+
+ /* The old curves should be empty, and the offsets are expected to be null. */
+ EXPECT_EQ(curves.points_size(), 0); /* NOLINT: bugprone-use-after-move */
+ EXPECT_EQ(curves.curve_offsets, nullptr); /* NOLINT: bugprone-use-after-move */
+
+ /* Just a basic check that the new curves work okay. */
+ float3 min;
+ float3 max;
+ EXPECT_TRUE(other.bounds_min_max(min, max));
+
+ curves = std::move(other);
+
+ CurvesGeometry second_other(std::move(curves));
+
+ /* The data should not have been reallocated ever. */
+ EXPECT_EQ(second_other.positions().data(), positions_data);
+ EXPECT_EQ(second_other.offsets().data(), offsets_data);
+}
+
+} // namespace blender::bke::tests
diff --git a/source/blender/blenkernel/intern/customdata.cc b/source/blender/blenkernel/intern/customdata.cc
index 4492f8bbc64..b348e18a6a8 100644
--- a/source/blender/blenkernel/intern/customdata.cc
+++ b/source/blender/blenkernel/intern/customdata.cc
@@ -1450,6 +1450,21 @@ static bool layerValidate_propfloat2(void *data, const uint totitems, const bool
return has_errors;
}
+static void layerInterp_propbool(const void **sources,
+ const float *weights,
+ const float *UNUSED(sub_weights),
+ int count,
+ void *dest)
+{
+ bool result = false;
+ for (int i = 0; i < count; i++) {
+ const float interp_weight = weights[i];
+ const bool src = *(const bool *)sources[i];
+ result |= src && (interp_weight > 0.0f);
+ }
+ *(bool *)dest = result;
+}
+
static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = {
/* 0: CD_MVERT */
{sizeof(MVert), "MVert", 1, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr},
@@ -1838,7 +1853,7 @@ static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = {
N_("Boolean"),
nullptr,
nullptr,
- nullptr,
+ layerInterp_propbool,
nullptr,
nullptr,
nullptr,
diff --git a/source/blender/blenkernel/intern/data_transfer.c b/source/blender/blenkernel/intern/data_transfer.c
index 1818e5a9490..5be993ca1f7 100644
--- a/source/blender/blenkernel/intern/data_transfer.c
+++ b/source/blender/blenkernel/intern/data_transfer.c
@@ -973,8 +973,8 @@ static bool data_transfer_layersmapping_generate(ListBase *r_map,
return ret;
}
if (cddata_type == CD_FAKE_SHAPEKEY) {
- /* TODO: leaving shapekeys aside for now, quite specific case,
- * since we can't access them from MVert :/ */
+ /* TODO: leaving shape-keys aside for now, quite specific case,
+ * since we can't access them from #MVert :/ */
return false;
}
}
diff --git a/source/blender/blenkernel/intern/displist.cc b/source/blender/blenkernel/intern/displist.cc
index a33bca1db57..320124498d5 100644
--- a/source/blender/blenkernel/intern/displist.cc
+++ b/source/blender/blenkernel/intern/displist.cc
@@ -865,7 +865,7 @@ static GeometrySet curve_calc_modifiers_post(Depsgraph *depsgraph,
else {
std::unique_ptr<CurveEval> curve_eval = curve_eval_from_dna_curve(
*cu, ob->runtime.curve_cache->deformed_nurbs);
- geometry_set.replace_curve(curve_eval_to_curves(*curve_eval));
+ geometry_set.replace_curves(curve_eval_to_curves(*curve_eval));
}
for (; md; md = md->next) {
diff --git a/source/blender/blenkernel/intern/dynamicpaint.c b/source/blender/blenkernel/intern/dynamicpaint.c
index 1136ec45fd4..ce07e501897 100644
--- a/source/blender/blenkernel/intern/dynamicpaint.c
+++ b/source/blender/blenkernel/intern/dynamicpaint.c
@@ -6142,7 +6142,7 @@ static bool dynamicPaint_generateBakeData(DynamicPaintSurface *surface,
/* generate surface space partitioning grid */
surfaceGenerateGrid(surface);
- /* calculate current frame adjacency point distances and global dirs */
+ /* Calculate current frame adjacency point distances and global directions. */
dynamicPaint_prepareAdjacencyData(surface, false);
/* Copy current frame vertices to check against in next frame */
diff --git a/source/blender/blenkernel/intern/fluid.c b/source/blender/blenkernel/intern/fluid.c
index 6f2760e91a6..ca9d758c692 100644
--- a/source/blender/blenkernel/intern/fluid.c
+++ b/source/blender/blenkernel/intern/fluid.c
@@ -1845,8 +1845,8 @@ static void sample_mesh(FluidFlowSettings *ffs,
const float surface_distance = 1.732;
nearest.dist_sq = surface_distance * surface_distance; /* find_nearest uses squared distance. */
- bool is_gas_flow = (ffs->type == FLUID_FLOW_TYPE_SMOKE || ffs->type == FLUID_FLOW_TYPE_FIRE ||
- ffs->type == FLUID_FLOW_TYPE_SMOKEFIRE);
+ bool is_gas_flow = ELEM(
+ ffs->type, FLUID_FLOW_TYPE_SMOKE, FLUID_FLOW_TYPE_FIRE, FLUID_FLOW_TYPE_SMOKEFIRE);
/* Emission strength for gases will be computed below.
* For liquids it's not needed. Just set to non zero value
@@ -1937,7 +1937,7 @@ static void sample_mesh(FluidFlowSettings *ffs,
interp_v2_v2v2v2(tex_co, UNPACK3(uv), weights);
- /* Map texure coord between -1.0f and 1.0f. */
+ /* Map texture coord between -1.0f and 1.0f. */
tex_co[0] = tex_co[0] * 2.0f - 1.0f;
tex_co[1] = tex_co[1] * 2.0f - 1.0f;
tex_co[2] = ffs->texture_offset;
@@ -2035,8 +2035,7 @@ static void emit_from_mesh_task_cb(void *__restrict userdata,
/* Compute emission only for flow objects that produce fluid (i.e. skip outflow objects).
* Result in bb->influence. Also computes initial velocities. Result in bb->velocity. */
- if ((data->ffs->behavior == FLUID_FLOW_BEHAVIOR_GEOMETRY) ||
- (data->ffs->behavior == FLUID_FLOW_BEHAVIOR_INFLOW)) {
+ if (ELEM(data->ffs->behavior, FLUID_FLOW_BEHAVIOR_GEOMETRY, FLUID_FLOW_BEHAVIOR_INFLOW)) {
sample_mesh(data->ffs,
data->mvert,
data->vert_normals,
@@ -2697,8 +2696,8 @@ static bool escape_flowsobject(Object *flowobj,
bool is_static = is_static_object(flowobj);
bool liquid_flow = ffs->type == FLUID_FLOW_TYPE_LIQUID;
- bool gas_flow = (ffs->type == FLUID_FLOW_TYPE_SMOKE || ffs->type == FLUID_FLOW_TYPE_FIRE ||
- ffs->type == FLUID_FLOW_TYPE_SMOKEFIRE);
+ bool gas_flow = ELEM(
+ ffs->type, FLUID_FLOW_TYPE_SMOKE, FLUID_FLOW_TYPE_FIRE, FLUID_FLOW_TYPE_SMOKEFIRE);
bool is_geometry = (ffs->behavior == FLUID_FLOW_BEHAVIOR_GEOMETRY);
bool liquid_domain = fds->type == FLUID_DOMAIN_TYPE_LIQUID;
diff --git a/source/blender/blenkernel/intern/geometry_component_curves.cc b/source/blender/blenkernel/intern/geometry_component_curves.cc
index 5723d110aa0..86cbea9a9bb 100644
--- a/source/blender/blenkernel/intern/geometry_component_curves.cc
+++ b/source/blender/blenkernel/intern/geometry_component_curves.cc
@@ -467,6 +467,18 @@ static ComponentAttributeProviders create_attribute_providers_for_curve()
make_array_write_attribute<int8_t>,
tag_component_topology_changed);
+ static BuiltinCustomDataLayerProvider curve_type("curve_type",
+ ATTR_DOMAIN_CURVE,
+ CD_PROP_INT8,
+ CD_PROP_INT8,
+ BuiltinAttributeProvider::Creatable,
+ BuiltinAttributeProvider::Writable,
+ BuiltinAttributeProvider::Deletable,
+ curve_access,
+ make_array_read_attribute<int8_t>,
+ make_array_write_attribute<int8_t>,
+ tag_component_topology_changed);
+
static BuiltinCustomDataLayerProvider resolution("resolution",
ATTR_DOMAIN_CURVE,
CD_PROP_INT32,
@@ -504,6 +516,7 @@ static ComponentAttributeProviders create_attribute_providers_for_curve()
&handle_type_left,
&nurbs_order,
&nurbs_weight,
+ &curve_type,
&resolution,
&cyclic},
{&curve_custom_data, &point_custom_data});
diff --git a/source/blender/blenkernel/intern/geometry_component_mesh.cc b/source/blender/blenkernel/intern/geometry_component_mesh.cc
index 104166df913..cbd7ec9155a 100644
--- a/source/blender/blenkernel/intern/geometry_component_mesh.cc
+++ b/source/blender/blenkernel/intern/geometry_component_mesh.cc
@@ -1049,6 +1049,11 @@ class VertexGroupsAttributeProvider final : public DynamicAttributesProvider {
if (mesh->dvert == nullptr) {
return true;
}
+
+ /* Copy the data layer if it is shared with some other mesh. */
+ mesh->dvert = (MDeformVert *)CustomData_duplicate_referenced_layer(
+ &mesh->vdata, CD_MDEFORMVERT, mesh->totvert);
+
for (MDeformVert &dvert : MutableSpan(mesh->dvert, mesh->totvert)) {
MDeformWeight *weight = BKE_defvert_find_index(&dvert, index);
BKE_defvert_remove_group(&dvert, weight);
diff --git a/source/blender/blenkernel/intern/geometry_set.cc b/source/blender/blenkernel/intern/geometry_set.cc
index ca372ba8f38..0eece6e9ad0 100644
--- a/source/blender/blenkernel/intern/geometry_set.cc
+++ b/source/blender/blenkernel/intern/geometry_set.cc
@@ -353,7 +353,7 @@ void GeometrySet::replace_mesh(Mesh *mesh, GeometryOwnershipType ownership)
component.replace(mesh, ownership);
}
-void GeometrySet::replace_curve(Curves *curves, GeometryOwnershipType ownership)
+void GeometrySet::replace_curves(Curves *curves, GeometryOwnershipType ownership)
{
if (curves == nullptr) {
this->remove<CurveComponent>();
diff --git a/source/blender/blenkernel/intern/gpencil.c b/source/blender/blenkernel/intern/gpencil.c
index 16d43d40c50..92ed273cac8 100644
--- a/source/blender/blenkernel/intern/gpencil.c
+++ b/source/blender/blenkernel/intern/gpencil.c
@@ -2568,11 +2568,13 @@ void BKE_gpencil_visible_stroke_advanced_iter(ViewLayer *view_layer,
layer_cb(gpl, gpf, NULL, thunk);
}
- LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
- if (gps->totpoints == 0) {
- continue;
+ if (stroke_cb) {
+ LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
+ if (gps->totpoints == 0) {
+ continue;
+ }
+ stroke_cb(gpl, gpf, gps, thunk);
}
- stroke_cb(gpl, gpf, gps, thunk);
}
}
/* Draw Active frame on top. */
@@ -2590,12 +2592,13 @@ void BKE_gpencil_visible_stroke_advanced_iter(ViewLayer *view_layer,
gpl->opacity = prev_opacity;
continue;
}
-
- LISTBASE_FOREACH (bGPDstroke *, gps, &act_gpf->strokes) {
- if (gps->totpoints == 0) {
- continue;
+ if (stroke_cb) {
+ LISTBASE_FOREACH (bGPDstroke *, gps, &act_gpf->strokes) {
+ if (gps->totpoints == 0) {
+ continue;
+ }
+ stroke_cb(gpl, act_gpf, gps, thunk);
}
- stroke_cb(gpl, act_gpf, gps, thunk);
}
}
diff --git a/source/blender/blenkernel/intern/gpencil_curve.c b/source/blender/blenkernel/intern/gpencil_curve.c
index ee6b77e6463..20b8342f090 100644
--- a/source/blender/blenkernel/intern/gpencil_curve.c
+++ b/source/blender/blenkernel/intern/gpencil_curve.c
@@ -50,8 +50,8 @@
static int gpencil_check_same_material_color(Object *ob_gp,
const float color_stroke[4],
const float color_fill[4],
- const bool do_fill,
const bool do_stroke,
+ const bool do_fill,
Material **r_mat)
{
int index = -1;
diff --git a/source/blender/blenkernel/intern/gpencil_modifier.c b/source/blender/blenkernel/intern/gpencil_modifier.c
index bc3aa88d096..33410b4521e 100644
--- a/source/blender/blenkernel/intern/gpencil_modifier.c
+++ b/source/blender/blenkernel/intern/gpencil_modifier.c
@@ -28,6 +28,7 @@
#include "DNA_screen_types.h"
#include "BKE_colortools.h"
+#include "BKE_deform.h"
#include "BKE_gpencil.h"
#include "BKE_gpencil_geom.h"
#include "BKE_gpencil_modifier.h"
@@ -196,9 +197,11 @@ bool BKE_gpencil_has_transform_modifiers(Object *ob)
LISTBASE_FOREACH (GpencilModifierData *, md, &ob->greasepencil_modifiers) {
/* Only if enabled in edit mode. */
if (!GPENCIL_MODIFIER_EDIT(md, true) && GPENCIL_MODIFIER_ACTIVE(md, false)) {
- if ((md->type == eGpencilModifierType_Armature) || (md->type == eGpencilModifierType_Hook) ||
- (md->type == eGpencilModifierType_Lattice) ||
- (md->type == eGpencilModifierType_Offset)) {
+ if (ELEM(md->type,
+ eGpencilModifierType_Armature,
+ eGpencilModifierType_Hook,
+ eGpencilModifierType_Lattice,
+ eGpencilModifierType_Offset)) {
return true;
}
}
@@ -618,48 +621,70 @@ static void gpencil_assign_object_eval(Object *object)
}
}
-/* Helper: Copy active frame from original datablock to evaluated datablock for modifiers. */
-static void gpencil_copy_activeframe_to_eval(
- Depsgraph *depsgraph, Scene *scene, Object *ob, bGPdata *gpd_orig, bGPdata *gpd_eval)
+static bGPdata *gpencil_copy_structure_for_eval(bGPdata *gpd)
{
+ /* Create a temporary copy gpd. */
+ ID *newid = NULL;
+ BKE_libblock_copy_ex(NULL, &gpd->id, &newid, LIB_ID_COPY_LOCALIZE);
+ bGPdata *gpd_eval = (bGPdata *)newid;
+ BLI_listbase_clear(&gpd_eval->layers);
- bGPDlayer *gpl_eval = gpd_eval->layers.first;
- LISTBASE_FOREACH (bGPDlayer *, gpl_orig, &gpd_orig->layers) {
-
- if (gpl_eval != NULL) {
- bGPDframe *gpf_orig = gpl_orig->actframe;
+ if (gpd->mat != NULL) {
+ gpd_eval->mat = MEM_dupallocN(gpd->mat);
+ }
- int remap_cfra = gpencil_remap_time_get(depsgraph, scene, ob, gpl_orig);
- if ((gpf_orig == NULL) || (gpf_orig && gpf_orig->framenum != remap_cfra)) {
- gpf_orig = BKE_gpencil_layer_frame_get(gpl_orig, remap_cfra, GP_GETFRAME_USE_PREV);
- }
+ BKE_defgroup_copy_list(&gpd_eval->vertex_group_names, &gpd->vertex_group_names);
- if (gpf_orig != NULL) {
- int gpf_index = BLI_findindex(&gpl_orig->frames, gpf_orig);
- bGPDframe *gpf_eval = BLI_findlink(&gpl_eval->frames, gpf_index);
+ /* Duplicate structure: layers and frames without strokes. */
+ LISTBASE_FOREACH (bGPDlayer *, gpl_orig, &gpd->layers) {
+ bGPDlayer *gpl_eval = BKE_gpencil_layer_duplicate(gpl_orig, true, false);
+ BLI_addtail(&gpd_eval->layers, gpl_eval);
+ gpl_eval->runtime.gpl_orig = gpl_orig;
+ /* Update frames orig pointers (helps for faster lookup in copy_frame_to_eval_cb). */
+ BKE_gpencil_layer_original_pointers_update(gpl_orig, gpl_eval);
+ }
- if (gpf_eval != NULL) {
- /* Delete old strokes. */
- BKE_gpencil_free_strokes(gpf_eval);
- /* Copy again strokes. */
- BKE_gpencil_frame_copy_strokes(gpf_orig, gpf_eval);
+ return gpd_eval;
+}
- gpf_eval->runtime.gpf_orig = (bGPDframe *)gpf_orig;
- BKE_gpencil_frame_original_pointers_update(gpf_orig, gpf_eval);
- }
- }
+static void copy_frame_to_eval_cb(bGPDlayer *UNUSED(gpl),
+ bGPDframe *gpf,
+ bGPDstroke *UNUSED(gps),
+ void *UNUSED(thunk))
+{
+ /* Early return when callback is not provided with a frame. */
+ if (gpf == NULL) {
+ return;
+ }
- gpl_eval = gpl_eval->next;
- }
+ /* Free any existing eval stroke data. This happens in case we have a single user on the data
+ * block and the strokes have not been deleted. */
+ if (!BLI_listbase_is_empty(&gpf->strokes)) {
+ BKE_gpencil_free_strokes(gpf);
}
+
+ /* Get original frame. */
+ bGPDframe *gpf_orig = gpf->runtime.gpf_orig;
+ /* Copy strokes to eval frame and update internal orig pointers. */
+ BKE_gpencil_frame_copy_strokes(gpf_orig, gpf);
+ BKE_gpencil_frame_original_pointers_update(gpf_orig, gpf);
}
-static bGPdata *gpencil_copy_for_eval(bGPdata *gpd)
+static void gpencil_copy_visible_frames_to_eval(Depsgraph *depsgraph, Scene *scene, Object *ob)
{
- const int flags = LIB_ID_COPY_LOCALIZE;
+ /* Remap layers' active frame with time modifiers applied. */
+ bGPdata *gpd_eval = ob->data;
+ LISTBASE_FOREACH (bGPDlayer *, gpl_eval, &gpd_eval->layers) {
+ bGPDframe *gpf_eval = gpl_eval->actframe;
+ int remap_cfra = gpencil_remap_time_get(depsgraph, scene, ob, gpl_eval);
+ if (gpf_eval == NULL || gpf_eval->framenum != remap_cfra) {
+ gpl_eval->actframe = BKE_gpencil_layer_frame_get(gpl_eval, remap_cfra, GP_GETFRAME_USE_PREV);
+ }
+ }
- bGPdata *result = (bGPdata *)BKE_id_copy_ex(NULL, &gpd->id, NULL, flags);
- return result;
+ /* Copy only visible frames to evaluated version. */
+ BKE_gpencil_visible_stroke_advanced_iter(
+ NULL, ob, copy_frame_to_eval_cb, NULL, NULL, true, scene->r.cfra);
}
void BKE_gpencil_prepare_eval_data(Depsgraph *depsgraph, Scene *scene, Object *ob)
@@ -688,7 +713,7 @@ void BKE_gpencil_prepare_eval_data(Depsgraph *depsgraph, Scene *scene, Object *o
if (ob->runtime.gpd_eval != NULL) {
/* Make sure to clear the pointer in case the runtime eval data points to the same data block.
* This can happen when the gpencil data block was not tagged for a depsgraph update after last
- * call to this function. */
+ * call to this function (e.g. a frame change). */
if (gpd_eval == ob->runtime.gpd_eval) {
gpd_eval = NULL;
}
@@ -707,18 +732,19 @@ void BKE_gpencil_prepare_eval_data(Depsgraph *depsgraph, Scene *scene, Object *o
return;
}
- /* If only one user, don't need a new copy, just update data of the frame. */
- if (gpd_orig->id.us == 1) {
- BLI_assert(ob->data != NULL);
- gpencil_copy_activeframe_to_eval(depsgraph, scene, ob, ob_orig->data, gpd_eval);
- return;
+ /* If datablock has only one user, we can update its eval data directly.
+ * Otherwise, we need to have distinct copies for each instance, since applied transformations
+ * may differ. */
+ if (gpd_orig->id.us > 1) {
+ /* Copy of the original datablock's structure (layers and empty frames). */
+ ob->runtime.gpd_eval = gpencil_copy_structure_for_eval(gpd_orig);
+ /* Overwrite ob->data with gpd_eval here. */
+ gpencil_assign_object_eval(ob);
}
- /* Copy full datablock to evaluated version. */
- ob->runtime.gpd_eval = gpencil_copy_for_eval(gpd_orig);
- /* Overwrite ob->data with gpd_eval here. */
- gpencil_assign_object_eval(ob);
- BKE_gpencil_update_orig_pointers(ob_orig, ob);
+ BLI_assert(ob->data != NULL);
+ /* Only copy strokes from visible frames to evaluated data.*/
+ gpencil_copy_visible_frames_to_eval(depsgraph, scene, ob);
}
void BKE_gpencil_modifiers_calc(Depsgraph *depsgraph, Scene *scene, Object *ob)
diff --git a/source/blender/blenkernel/intern/idprop.c b/source/blender/blenkernel/intern/idprop.c
index d00fc8814e0..7b8dfdc690c 100644
--- a/source/blender/blenkernel/intern/idprop.c
+++ b/source/blender/blenkernel/intern/idprop.c
@@ -903,8 +903,7 @@ IDProperty *IDP_New(const char type, const IDPropertyTemplate *val, const char *
break;
case IDP_ARRAY: {
/* for now, we only support float and int and double arrays */
- if ((val->array.type == IDP_FLOAT) || (val->array.type == IDP_INT) ||
- (val->array.type == IDP_DOUBLE) || (val->array.type == IDP_GROUP)) {
+ if (ELEM(val->array.type, IDP_FLOAT, IDP_INT, IDP_DOUBLE, IDP_GROUP)) {
prop = MEM_callocN(sizeof(IDProperty), "IDProperty array");
prop->subtype = val->array.type;
if (val->array.len) {
diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.cc
index 8a212ed0d7d..b4644b84f1e 100644
--- a/source/blender/blenkernel/intern/image.c
+++ b/source/blender/blenkernel/intern/image.cc
@@ -5,18 +5,20 @@
* \ingroup bke
*/
-#include <ctype.h>
+#include <cctype>
+#include <cmath>
+#include <cstdio>
+#include <cstring>
#include <fcntl.h>
-#include <math.h>
-#include <stdio.h>
-#include <string.h>
#ifndef WIN32
# include <unistd.h>
#else
# include <io.h>
#endif
-#include <time.h>
+#include <ctime>
+
+#include "BLI_array.hh"
#include "CLG_log.h"
@@ -99,39 +101,45 @@
#include "DNA_space_types.h"
#include "DNA_view3d_types.h"
+using blender::Array;
+
static CLG_LogRef LOG = {"bke.image"};
static void image_init(Image *ima, short source, short type);
static void image_free_packedfiles(Image *ima);
static void copy_image_packedfiles(ListBase *lb_dst, const ListBase *lb_src);
-/* Reset runtime image fields when data-block is being initialized. */
+/* -------------------------------------------------------------------- */
+/** \name Image #IDTypeInfo API
+ * \{ */
+
+/** Reset runtime image fields when data-block is being initialized. */
static void image_runtime_reset(struct Image *image)
{
memset(&image->runtime, 0, sizeof(image->runtime));
image->runtime.cache_mutex = MEM_mallocN(sizeof(ThreadMutex), "image runtime cache_mutex");
- BLI_mutex_init(image->runtime.cache_mutex);
+ BLI_mutex_init(static_cast<ThreadMutex *>(image->runtime.cache_mutex));
}
-/* Reset runtime image fields when data-block is being copied. */
+/** Reset runtime image fields when data-block is being copied. */
static void image_runtime_reset_on_copy(struct Image *image)
{
image->runtime.cache_mutex = MEM_mallocN(sizeof(ThreadMutex), "image runtime cache_mutex");
- BLI_mutex_init(image->runtime.cache_mutex);
+ BLI_mutex_init(static_cast<ThreadMutex *>(image->runtime.cache_mutex));
- image->runtime.partial_update_register = NULL;
- image->runtime.partial_update_user = NULL;
+ image->runtime.partial_update_register = nullptr;
+ image->runtime.partial_update_user = nullptr;
}
static void image_runtime_free_data(struct Image *image)
{
- BLI_mutex_end(image->runtime.cache_mutex);
+ BLI_mutex_end(static_cast<ThreadMutex *>(image->runtime.cache_mutex));
MEM_freeN(image->runtime.cache_mutex);
- image->runtime.cache_mutex = NULL;
+ image->runtime.cache_mutex = nullptr;
- if (image->runtime.partial_update_user != NULL) {
+ if (image->runtime.partial_update_user != nullptr) {
BKE_image_partial_update_free(image->runtime.partial_update_user);
- image->runtime.partial_update_user = NULL;
+ image->runtime.partial_update_user = nullptr;
}
BKE_image_partial_update_register_free(image);
}
@@ -140,7 +148,7 @@ static void image_init_data(ID *id)
{
Image *image = (Image *)id;
- if (image != NULL) {
+ if (image != nullptr) {
image_init(image, IMA_SRC_GENERATED, IMA_TYPE_UV_TEST);
}
}
@@ -155,16 +163,17 @@ static void image_copy_data(Main *UNUSED(bmain), ID *id_dst, const ID *id_src, c
copy_image_packedfiles(&image_dst->packedfiles, &image_src->packedfiles);
- image_dst->stereo3d_format = MEM_dupallocN(image_src->stereo3d_format);
+ image_dst->stereo3d_format = static_cast<Stereo3dFormat *>(
+ MEM_dupallocN(image_src->stereo3d_format));
BLI_duplicatelist(&image_dst->views, &image_src->views);
/* Cleanup stuff that cannot be copied. */
- image_dst->cache = NULL;
- image_dst->rr = NULL;
+ image_dst->cache = nullptr;
+ image_dst->rr = nullptr;
BLI_duplicatelist(&image_dst->renderslots, &image_src->renderslots);
LISTBASE_FOREACH (RenderSlot *, slot, &image_dst->renderslots) {
- slot->render = NULL;
+ slot->render = nullptr;
}
BLI_listbase_clear(&image_dst->anims);
@@ -174,7 +183,7 @@ static void image_copy_data(Main *UNUSED(bmain), ID *id_dst, const ID *id_src, c
for (int eye = 0; eye < 2; eye++) {
for (int i = 0; i < TEXTARGET_COUNT; i++) {
for (int resolution = 0; resolution < IMA_TEXTURE_RESOLUTION_LEN; resolution++) {
- image_dst->gputexture[i][eye][resolution] = NULL;
+ image_dst->gputexture[i][eye][resolution] = nullptr;
}
}
}
@@ -183,7 +192,7 @@ static void image_copy_data(Main *UNUSED(bmain), ID *id_dst, const ID *id_src, c
BKE_previewimg_id_copy(&image_dst->id, &image_src->id);
}
else {
- image_dst->preview = NULL;
+ image_dst->preview = nullptr;
}
image_runtime_reset_on_copy(image_dst);
@@ -193,7 +202,7 @@ static void image_free_data(ID *id)
{
Image *image = (Image *)id;
- /* Also frees animdata. */
+ /* Also frees animations (#Image.anims list). */
BKE_image_free_buffers(image);
image_free_packedfiles(image);
@@ -201,7 +210,7 @@ static void image_free_data(ID *id)
LISTBASE_FOREACH (RenderSlot *, slot, &image->renderslots) {
if (slot->render) {
RE_FreeRenderResult(slot->render);
- slot->render = NULL;
+ slot->render = nullptr;
}
}
BLI_freelistN(&image->renderslots);
@@ -222,21 +231,28 @@ static void image_foreach_cache(ID *id,
void *user_data)
{
Image *image = (Image *)id;
- IDCacheKey key = {
- .id_session_uuid = id->session_uuid,
- .offset_in_ID = offsetof(Image, cache),
- .cache_v = image->cache,
- };
+ IDCacheKey key;
+ key.id_session_uuid = id->session_uuid;
+ key.offset_in_ID = offsetof(Image, cache);
+ key.cache_v = image->cache;
function_callback(id, &key, (void **)&image->cache, 0, user_data);
+ auto gputexture_offset = [image](int target, int eye, int resolution) {
+ constexpr size_t base_offset = offsetof(Image, gputexture);
+ const auto first = &image->gputexture[0][0][0];
+ const size_t array_offset = sizeof(*first) *
+ (&image->gputexture[target][eye][resolution] - first);
+ return base_offset + array_offset;
+ };
+
for (int eye = 0; eye < 2; eye++) {
for (int a = 0; a < TEXTARGET_COUNT; a++) {
for (int resolution = 0; resolution < IMA_TEXTURE_RESOLUTION_LEN; resolution++) {
GPUTexture *texture = image->gputexture[a][eye][resolution];
- if (texture == NULL) {
+ if (texture == nullptr) {
continue;
}
- key.offset_in_ID = offsetof(Image, gputexture[a][eye][resolution]);
+ key.offset_in_ID = gputexture_offset(a, eye, resolution);
key.cache_v = texture;
function_callback(id, &key, (void **)&image->gputexture[a][eye][resolution], 0, user_data);
}
@@ -302,7 +318,7 @@ static void image_foreach_path(ID *id, BPathForeachPathData *bpath_data)
if (!BKE_image_has_packedfile(ima) &&
/* Image may have been painted onto (and not saved, T44543). */
!BKE_image_is_dirty(ima)) {
- BKE_image_signal(bpath_data->bmain, ima, NULL, IMA_SIGNAL_RELOAD);
+ BKE_image_signal(bpath_data->bmain, ima, nullptr, IMA_SIGNAL_RELOAD);
}
}
}
@@ -316,22 +332,22 @@ static void image_blend_write(BlendWriter *writer, ID *id, const void *id_addres
/* Clear all data that isn't read to reduce false detection of changed image during memfile undo.
*/
ima->lastused = 0;
- ima->cache = NULL;
+ ima->cache = nullptr;
ima->gpuflag = 0;
BLI_listbase_clear(&ima->anims);
- ima->runtime.partial_update_register = NULL;
- ima->runtime.partial_update_user = NULL;
+ ima->runtime.partial_update_register = nullptr;
+ ima->runtime.partial_update_user = nullptr;
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 2; j++) {
for (int resolution = 0; resolution < IMA_TEXTURE_RESOLUTION_LEN; resolution++) {
- ima->gputexture[i][j][resolution] = NULL;
+ ima->gputexture[i][j][resolution] = nullptr;
}
}
}
ImagePackedFile *imapf;
- BLI_assert(ima->packedfile == NULL);
+ BLI_assert(ima->packedfile == nullptr);
if (!is_undo) {
/* Do not store packed files in case this is a library override ID. */
if (ID_IS_OVERRIDE_LIBRARY(ima)) {
@@ -339,8 +355,8 @@ static void image_blend_write(BlendWriter *writer, ID *id, const void *id_addres
}
else {
/* Some trickery to keep forward compatibility of packed images. */
- if (ima->packedfiles.first != NULL) {
- imapf = ima->packedfiles.first;
+ if (ima->packedfiles.first != nullptr) {
+ imapf = static_cast<ImagePackedFile *>(ima->packedfiles.first);
ima->packedfile = imapf->packedfile;
}
}
@@ -350,7 +366,8 @@ static void image_blend_write(BlendWriter *writer, ID *id, const void *id_addres
BLO_write_id_struct(writer, Image, id_address, &ima->id);
BKE_id_blend_write(writer, &ima->id);
- for (imapf = ima->packedfiles.first; imapf; imapf = imapf->next) {
+ for (imapf = static_cast<ImagePackedFile *>(ima->packedfiles.first); imapf;
+ imapf = imapf->next) {
BLO_write_struct(writer, ImagePackedFile, imapf);
BKE_packedfile_blend_write(writer, imapf->packedfile);
}
@@ -364,7 +381,7 @@ static void image_blend_write(BlendWriter *writer, ID *id, const void *id_addres
BLO_write_struct_list(writer, ImageTile, &ima->tiles);
- ima->packedfile = NULL;
+ ima->packedfile = nullptr;
BLO_write_struct_list(writer, RenderSlot, &ima->renderslots);
}
@@ -387,7 +404,7 @@ static void image_blend_read_data(BlendDataReader *reader, ID *id)
LISTBASE_FOREACH (ImagePackedFile *, imapf, &ima->packedfiles) {
BKE_packedfile_blend_read(reader, &imapf->packedfile);
}
- ima->packedfile = NULL;
+ ima->packedfile = nullptr;
}
else {
BKE_packedfile_blend_read(reader, &ima->packedfile);
@@ -407,44 +424,48 @@ static void image_blend_read_data(BlendDataReader *reader, ID *id)
static void image_blend_read_lib(BlendLibReader *UNUSED(reader), ID *id)
{
Image *ima = (Image *)id;
- /* Images have some kind of 'main' cache, when NULL we should also clear all others. */
+ /* Images have some kind of 'main' cache, when null we should also clear all others. */
/* Needs to be done *after* cache pointers are restored (call to
* `foreach_cache`/`blo_cache_storage_entry_restore_in_new`), easier for now to do it in
* lib_link... */
- if (ima->cache == NULL) {
+ if (ima->cache == nullptr) {
BKE_image_free_buffers(ima);
}
}
-IDTypeInfo IDType_ID_IM = {
- .id_code = ID_IM,
- .id_filter = FILTER_ID_IM,
- .main_listbase_index = INDEX_ID_IM,
- .struct_size = sizeof(Image),
- .name = "Image",
- .name_plural = "images",
- .translation_context = BLT_I18NCONTEXT_ID_IMAGE,
- .flags = IDTYPE_FLAGS_NO_ANIMDATA | IDTYPE_FLAGS_APPEND_IS_REUSABLE,
- .asset_type_info = NULL,
+constexpr IDTypeInfo get_type_info()
+{
+ IDTypeInfo info{};
+ info.id_code = ID_IM;
+ info.id_filter = FILTER_ID_IM;
+ info.main_listbase_index = INDEX_ID_IM;
+ info.struct_size = sizeof(Image);
+ info.name = "Image";
+ info.name_plural = "images";
+ info.translation_context = BLT_I18NCONTEXT_ID_IMAGE;
+ info.flags = IDTYPE_FLAGS_NO_ANIMDATA | IDTYPE_FLAGS_APPEND_IS_REUSABLE;
+ info.asset_type_info = nullptr;
- .init_data = image_init_data,
- .copy_data = image_copy_data,
- .free_data = image_free_data,
- .make_local = NULL,
- .foreach_id = NULL,
- .foreach_cache = image_foreach_cache,
- .foreach_path = image_foreach_path,
- .owner_get = NULL,
+ info.init_data = image_init_data;
+ info.copy_data = image_copy_data;
+ info.free_data = image_free_data;
+ info.make_local = nullptr;
+ info.foreach_id = nullptr;
+ info.foreach_cache = image_foreach_cache;
+ info.foreach_path = image_foreach_path;
+ info.owner_get = nullptr;
- .blend_write = image_blend_write,
- .blend_read_data = image_blend_read_data,
- .blend_read_lib = image_blend_read_lib,
- .blend_read_expand = NULL,
+ info.blend_write = image_blend_write;
+ info.blend_read_data = image_blend_read_data;
+ info.blend_read_lib = image_blend_read_lib;
+ info.blend_read_expand = nullptr;
- .blend_read_undo_preserve = NULL,
+ info.blend_read_undo_preserve = nullptr;
- .lib_override_apply_post = NULL,
-};
+ info.lib_override_apply_post = nullptr;
+ return info;
+}
+IDTypeInfo IDType_ID_IM = get_type_info();
/* prototypes */
static int image_num_files(struct Image *ima);
@@ -462,7 +483,11 @@ static void image_add_view(Image *ima, const char *viewname, const char *filepat
# define IMA_INDEX_PASS(index) (index & ~1023)
#endif
-/* ******** IMAGE CACHE ************* */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Image Cache
+ * \{ */
typedef struct ImageCacheKey {
int index;
@@ -470,21 +495,21 @@ typedef struct ImageCacheKey {
static unsigned int imagecache_hashhash(const void *key_v)
{
- const ImageCacheKey *key = key_v;
+ const ImageCacheKey *key = static_cast<const ImageCacheKey *>(key_v);
return key->index;
}
static bool imagecache_hashcmp(const void *a_v, const void *b_v)
{
- const ImageCacheKey *a = a_v;
- const ImageCacheKey *b = b_v;
+ const ImageCacheKey *a = static_cast<const ImageCacheKey *>(a_v);
+ const ImageCacheKey *b = static_cast<const ImageCacheKey *>(b_v);
return (a->index != b->index);
}
static void imagecache_keydata(void *userkey, int *framenr, int *proxy, int *render_flags)
{
- ImageCacheKey *key = userkey;
+ ImageCacheKey *key = static_cast<ImageCacheKey *>(userkey);
*framenr = IMA_INDEX_ENTRY(key->index);
*proxy = IMB_PROXY_NONE;
@@ -495,7 +520,7 @@ static void imagecache_put(Image *image, int index, ImBuf *ibuf)
{
ImageCacheKey key;
- if (image->cache == NULL) {
+ if (image->cache == nullptr) {
// char cache_name[64];
// SNPRINTF(cache_name, "Image Datablock %s", image->id.name);
@@ -511,7 +536,7 @@ static void imagecache_put(Image *image, int index, ImBuf *ibuf)
static void imagecache_remove(Image *image, int index)
{
- if (image->cache == NULL) {
+ if (image->cache == nullptr) {
return;
}
@@ -528,23 +553,27 @@ static struct ImBuf *imagecache_get(Image *image, int index, bool *r_is_cached_e
return IMB_moviecache_get(image->cache, &key, r_is_cached_empty);
}
- return NULL;
+ return nullptr;
}
-/* ***************** ALLOC & FREE, DATA MANAGING *************** */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Allocate & Free, Data Managing
+ * \{ */
static void image_free_cached_frames(Image *image)
{
if (image->cache) {
IMB_moviecache_free(image->cache);
- image->cache = NULL;
+ image->cache = nullptr;
}
}
static void image_free_packedfiles(Image *ima)
{
while (ima->packedfiles.last) {
- ImagePackedFile *imapf = ima->packedfiles.last;
+ ImagePackedFile *imapf = static_cast<ImagePackedFile *>(ima->packedfiles.last);
if (imapf->packedfile) {
BKE_packedfile_free(imapf->packedfile);
}
@@ -566,10 +595,10 @@ void BKE_image_free_views(Image *image)
static void image_free_anims(Image *ima)
{
while (ima->anims.last) {
- ImageAnim *ia = ima->anims.last;
+ ImageAnim *ia = static_cast<ImageAnim *>(ima->anims.last);
if (ia->anim) {
IMB_free_anim(ia->anim);
- ia->anim = NULL;
+ ia->anim = nullptr;
}
BLI_remlink(&ima->anims, ia);
MEM_freeN(ia);
@@ -579,7 +608,7 @@ static void image_free_anims(Image *ima)
void BKE_image_free_buffers_ex(Image *ima, bool do_lock)
{
if (do_lock) {
- BLI_mutex_lock(ima->runtime.cache_mutex);
+ BLI_mutex_lock(static_cast<ThreadMutex *>(ima->runtime.cache_mutex));
}
image_free_cached_frames(ima);
@@ -587,13 +616,13 @@ void BKE_image_free_buffers_ex(Image *ima, bool do_lock)
if (ima->rr) {
RE_FreeRenderResult(ima->rr);
- ima->rr = NULL;
+ ima->rr = nullptr;
}
BKE_image_free_gputextures(ima);
if (do_lock) {
- BLI_mutex_unlock(ima->runtime.cache_mutex);
+ BLI_mutex_unlock(static_cast<ThreadMutex *>(ima->runtime.cache_mutex));
}
}
@@ -621,27 +650,27 @@ static void image_init(Image *ima, short source, short type)
ima->flag |= IMA_VIEW_AS_RENDER;
}
- ImageTile *tile = MEM_callocN(sizeof(ImageTile), "Image Tiles");
+ ImageTile *tile = MEM_cnew<ImageTile>("Image Tiles");
tile->tile_number = 1001;
BLI_addtail(&ima->tiles, tile);
if (type == IMA_TYPE_R_RESULT) {
for (int i = 0; i < 8; i++) {
- BKE_image_add_renderslot(ima, NULL);
+ BKE_image_add_renderslot(ima, nullptr);
}
}
image_runtime_reset(ima);
BKE_color_managed_colorspace_settings_init(&ima->colorspace_settings);
- ima->stereo3d_format = MEM_callocN(sizeof(Stereo3dFormat), "Image Stereo Format");
+ ima->stereo3d_format = MEM_cnew<Stereo3dFormat>("Image Stereo Format");
}
static Image *image_alloc(Main *bmain, const char *name, short source, short type)
{
Image *ima;
- ima = BKE_libblock_alloc(bmain, ID_IM, name, 0);
+ ima = static_cast<Image *>(BKE_libblock_alloc(bmain, ID_IM, name, 0));
if (ima) {
image_init(ima, source, type);
}
@@ -649,12 +678,12 @@ static Image *image_alloc(Main *bmain, const char *name, short source, short typ
return ima;
}
-/* Get the ibuf from an image cache by its index and entry.
+/**
+ * Get the ibuf from an image cache by its index and entry.
* Local use here only.
*
- * Returns referenced image buffer if it exists, callee is to
- * call IMB_freeImBuf to de-reference the image buffer after
- * it's done handling it.
+ * \returns referenced image buffer if it exists, callee is to call #IMB_freeImBuf
+ * to de-reference the image buffer after it's done handling it.
*/
static ImBuf *image_get_cached_ibuf_for_index_entry(Image *ima,
int index,
@@ -690,8 +719,10 @@ static void copy_image_packedfiles(ListBase *lb_dst, const ListBase *lb_src)
const ImagePackedFile *imapf_src;
BLI_listbase_clear(lb_dst);
- for (imapf_src = lb_src->first; imapf_src; imapf_src = imapf_src->next) {
- ImagePackedFile *imapf_dst = MEM_mallocN(sizeof(ImagePackedFile), "Image Packed Files (copy)");
+ for (imapf_src = static_cast<const ImagePackedFile *>(lb_src->first); imapf_src;
+ imapf_src = imapf_src->next) {
+ ImagePackedFile *imapf_dst = static_cast<ImagePackedFile *>(
+ MEM_mallocN(sizeof(ImagePackedFile), "Image Packed Files (copy)"));
STRNCPY(imapf_dst->filepath, imapf_src->filepath);
if (imapf_src->packedfile) {
@@ -706,23 +737,23 @@ void BKE_image_merge(Main *bmain, Image *dest, Image *source)
{
/* sanity check */
if (dest && source && dest != source) {
- BLI_mutex_lock(source->runtime.cache_mutex);
- BLI_mutex_lock(dest->runtime.cache_mutex);
+ BLI_mutex_lock(static_cast<ThreadMutex *>(source->runtime.cache_mutex));
+ BLI_mutex_lock(static_cast<ThreadMutex *>(dest->runtime.cache_mutex));
- if (source->cache != NULL) {
+ if (source->cache != nullptr) {
struct MovieCacheIter *iter;
iter = IMB_moviecacheIter_new(source->cache);
while (!IMB_moviecacheIter_done(iter)) {
ImBuf *ibuf = IMB_moviecacheIter_getImBuf(iter);
- ImageCacheKey *key = IMB_moviecacheIter_getUserKey(iter);
+ ImageCacheKey *key = static_cast<ImageCacheKey *>(IMB_moviecacheIter_getUserKey(iter));
imagecache_put(dest, key->index, ibuf);
IMB_moviecacheIter_step(iter);
}
IMB_moviecacheIter_free(iter);
}
- BLI_mutex_unlock(dest->runtime.cache_mutex);
- BLI_mutex_unlock(source->runtime.cache_mutex);
+ BLI_mutex_unlock(static_cast<ThreadMutex *>(dest->runtime.cache_mutex));
+ BLI_mutex_unlock(static_cast<ThreadMutex *>(source->runtime.cache_mutex));
BKE_id_free(bmain, source);
}
@@ -736,7 +767,7 @@ bool BKE_image_scale(Image *image, int width, int height)
ImBuf *ibuf;
void *lock;
- ibuf = BKE_image_acquire_ibuf(image, NULL, &lock);
+ ibuf = BKE_image_acquire_ibuf(image, nullptr, &lock);
if (ibuf) {
IMB_scaleImBuf(ibuf, width, height);
@@ -745,7 +776,7 @@ bool BKE_image_scale(Image *image, int width, int height)
BKE_image_release_ibuf(image, ibuf, lock);
- return (ibuf != NULL);
+ return (ibuf != nullptr);
}
bool BKE_image_has_opengl_texture(Image *ima)
@@ -753,7 +784,7 @@ bool BKE_image_has_opengl_texture(Image *ima)
for (int eye = 0; eye < 2; eye++) {
for (int i = 0; i < TEXTARGET_COUNT; i++) {
for (int resolution = 0; resolution < IMA_TEXTURE_RESOLUTION_LEN; resolution++) {
- if (ima->gputexture[i][eye][resolution] != NULL) {
+ if (ima->gputexture[i][eye][resolution] != nullptr) {
return true;
}
}
@@ -764,26 +795,26 @@ bool BKE_image_has_opengl_texture(Image *ima)
static int image_get_tile_number_from_iuser(Image *ima, const ImageUser *iuser)
{
- BLI_assert(ima != NULL && ima->tiles.first);
- ImageTile *tile = ima->tiles.first;
+ BLI_assert(ima != nullptr && ima->tiles.first);
+ ImageTile *tile = static_cast<ImageTile *>(ima->tiles.first);
return (iuser && iuser->tile) ? iuser->tile : tile->tile_number;
}
ImageTile *BKE_image_get_tile(Image *ima, int tile_number)
{
- if (ima == NULL) {
- return NULL;
+ if (ima == nullptr) {
+ return nullptr;
}
/* Tiles 0 and 1001 are a special case and refer to the first tile, typically
* coming from non-UDIM-aware code. */
if (ELEM(tile_number, 0, 1001)) {
- return ima->tiles.first;
+ return static_cast<ImageTile *>(ima->tiles.first);
}
/* Must have a tiled image and a valid tile number at this point. */
if (ima->source != IMA_SRC_TILED || tile_number < 1001 || tile_number > IMA_UDIM_MAX) {
- return NULL;
+ return nullptr;
}
LISTBASE_FOREACH (ImageTile *, tile, &ima->tiles) {
@@ -792,7 +823,7 @@ ImageTile *BKE_image_get_tile(Image *ima, int tile_number)
}
}
- return NULL;
+ return nullptr;
}
ImageTile *BKE_image_get_tile_from_iuser(Image *ima, const ImageUser *iuser)
@@ -806,7 +837,7 @@ int BKE_image_get_tile_from_pos(struct Image *ima,
float r_ofs[2])
{
float local_ofs[2];
- if (r_ofs == NULL) {
+ if (r_ofs == nullptr) {
r_ofs = local_ofs;
}
@@ -821,7 +852,7 @@ int BKE_image_get_tile_from_pos(struct Image *ima,
int iy = (int)uv[1];
int tile_number = 1001 + 10 * iy + ix;
- if (BKE_image_get_tile(ima, tile_number) == NULL) {
+ if (BKE_image_get_tile(ima, tile_number) == nullptr) {
return 0;
}
r_ofs[0] = ix;
@@ -841,7 +872,8 @@ int BKE_image_find_nearest_tile(const Image *image, const float co[2])
LISTBASE_FOREACH (const ImageTile *, tile, &image->tiles) {
const int tile_index = tile->tile_number - 1001;
/* Coordinates of the current tile. */
- const float tile_index_co[2] = {tile_index % 10, tile_index / 10};
+ const float tile_index_co[2] = {static_cast<float>(tile_index % 10),
+ static_cast<float>(tile_index / 10)};
if (equals_v2v2(co_floor, tile_index_co)) {
return tile->tile_number;
@@ -864,7 +896,7 @@ static void image_init_color_management(Image *ima)
ImBuf *ibuf;
char name[FILE_MAX];
- BKE_image_user_file_path(NULL, ima, name);
+ BKE_image_user_file_path(nullptr, ima, name);
/* will set input color space to image format default's */
ibuf = IMB_loadiffname(name, IB_test | IB_alphamode_detect, ima->colorspace_settings.name);
@@ -889,7 +921,7 @@ static void image_init_color_management(Image *ima)
char BKE_image_alpha_mode_from_extension_ex(const char *filepath)
{
- if (BLI_path_extension_check_n(filepath, ".exr", ".cin", ".dpx", ".hdr", NULL)) {
+ if (BLI_path_extension_check_n(filepath, ".exr", ".cin", ".dpx", ".hdr", nullptr)) {
return IMA_ALPHA_PREMUL;
}
@@ -914,7 +946,7 @@ Image *BKE_image_load(Main *bmain, const char *filepath)
file = BLI_open(str, O_BINARY | O_RDONLY, 0);
if (file == -1) {
if (!BKE_image_tile_filepath_exists(str)) {
- return NULL;
+ return nullptr;
}
}
else {
@@ -942,7 +974,8 @@ Image *BKE_image_load_exists_ex(Main *bmain, const char *filepath, bool *r_exist
BLI_path_abs(str, bmain->filepath);
/* first search an identical filepath */
- for (ima = bmain->images.first; ima; ima = ima->id.next) {
+ for (ima = static_cast<Image *>(bmain->images.first); ima;
+ ima = static_cast<Image *>(ima->id.next)) {
if (!ELEM(ima->source, IMA_SRC_VIEWER, IMA_SRC_GENERATED)) {
STRNCPY(strtest, ima->filepath);
BLI_path_abs(strtest, ID_BLEND_PATH(bmain, &ima->id));
@@ -967,21 +1000,21 @@ Image *BKE_image_load_exists_ex(Main *bmain, const char *filepath, bool *r_exist
Image *BKE_image_load_exists(Main *bmain, const char *filepath)
{
- return BKE_image_load_exists_ex(bmain, filepath, NULL);
+ return BKE_image_load_exists_ex(bmain, filepath, nullptr);
}
-typedef struct ImageFillData {
+struct ImageFillData {
short gen_type;
uint width;
uint height;
unsigned char *rect;
float *rect_float;
float fill_color[4];
-} ImageFillData;
+};
static void image_buf_fill_isolated(void *usersata_v)
{
- ImageFillData *usersata = usersata_v;
+ ImageFillData *usersata = static_cast<ImageFillData *>(usersata_v);
const short gen_type = usersata->gen_type;
const uint width = usersata->width;
@@ -1013,8 +1046,8 @@ static ImBuf *add_ibuf_size(unsigned int width,
ColorManagedColorspaceSettings *colorspace_settings)
{
ImBuf *ibuf;
- unsigned char *rect = NULL;
- float *rect_float = NULL;
+ unsigned char *rect = nullptr;
+ float *rect_float = nullptr;
float fill_color[4];
if (floatbuf) {
@@ -1027,7 +1060,7 @@ static ImBuf *add_ibuf_size(unsigned int width,
STRNCPY(colorspace_settings->name, colorspace);
}
- if (ibuf != NULL) {
+ if (ibuf != nullptr) {
rect_float = ibuf->rect_float;
IMB_colormanagement_check_is_data(ibuf, colorspace_settings->name);
}
@@ -1051,7 +1084,7 @@ static ImBuf *add_ibuf_size(unsigned int width,
STRNCPY(colorspace_settings->name, colorspace);
}
- if (ibuf != NULL) {
+ if (ibuf != nullptr) {
rect = (unsigned char *)ibuf->rect;
IMB_colormanagement_assign_rect_colorspace(ibuf, colorspace_settings->name);
}
@@ -1060,7 +1093,7 @@ static ImBuf *add_ibuf_size(unsigned int width,
}
if (!ibuf) {
- return NULL;
+ return nullptr;
}
STRNCPY(ibuf->name, name);
@@ -1099,14 +1132,15 @@ Image *BKE_image_add_generated(Main *bmain,
else {
ima = image_alloc(bmain, name, IMA_SRC_GENERATED, IMA_TYPE_UV_TEST);
}
- if (ima == NULL) {
- return NULL;
+ if (ima == nullptr) {
+ return nullptr;
}
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! */
+ /* NOTE: leave `ima->filepath` unset,
+ * setting it to a dummy value may write to an invalid file-path. */
ima->gen_x = width;
ima->gen_y = height;
ima->gen_type = gen_type;
@@ -1144,7 +1178,7 @@ Image *BKE_image_add_from_imbuf(Main *bmain, ImBuf *ibuf, const char *name)
/* on save, type is changed to FILE in editsima.c */
Image *ima;
- if (name == NULL) {
+ if (name == nullptr) {
name = BLI_path_basename(ibuf->name);
}
@@ -1158,14 +1192,14 @@ Image *BKE_image_add_from_imbuf(Main *bmain, ImBuf *ibuf, const char *name)
return ima;
}
-/* Pack image buffer to memory as PNG or EXR. */
+/** Pack image buffer to memory as PNG or EXR. */
static bool image_memorypack_imbuf(Image *ima, ImBuf *ibuf, const char *filepath)
{
ibuf->ftype = (ibuf->rect_float) ? IMB_FTYPE_OPENEXR : IMB_FTYPE_PNG;
IMB_saveiff(ibuf, filepath, IB_rect | IB_mem);
- if (ibuf->encodedbuffer == NULL) {
+ if (ibuf->encodedbuffer == nullptr) {
CLOG_STR_ERROR(&LOG, "memory save for pack error");
IMB_freeImBuf(ibuf);
image_free_packedfiles(ima);
@@ -1173,17 +1207,17 @@ static bool image_memorypack_imbuf(Image *ima, ImBuf *ibuf, const char *filepath
}
ImagePackedFile *imapf;
- PackedFile *pf = MEM_callocN(sizeof(*pf), "PackedFile");
+ PackedFile *pf = MEM_cnew<PackedFile>("PackedFile");
pf->data = ibuf->encodedbuffer;
pf->size = ibuf->encodedsize;
- imapf = MEM_mallocN(sizeof(ImagePackedFile), "Image PackedFile");
+ imapf = static_cast<ImagePackedFile *>(MEM_mallocN(sizeof(ImagePackedFile), "Image PackedFile"));
STRNCPY(imapf->filepath, filepath);
imapf->packedfile = pf;
BLI_addtail(&ima->packedfiles, imapf);
- ibuf->encodedbuffer = NULL;
+ ibuf->encodedbuffer = nullptr;
ibuf->encodedsize = 0;
ibuf->userflags &= ~IB_BITMAPDIRTY;
@@ -1201,8 +1235,9 @@ bool BKE_image_memorypack(Image *ima)
ImageView *iv;
int i;
- for (i = 0, iv = ima->views.first; iv; iv = iv->next, i++) {
- ImBuf *ibuf = image_get_cached_ibuf_for_index_entry(ima, i, 0, NULL);
+ for (i = 0, iv = static_cast<ImageView *>(ima->views.first); iv;
+ iv = static_cast<ImageView *>(iv->next), i++) {
+ ImBuf *ibuf = image_get_cached_ibuf_for_index_entry(ima, i, 0, nullptr);
if (!ibuf) {
ok = false;
@@ -1222,7 +1257,7 @@ bool BKE_image_memorypack(Image *ima)
ima->views_format = R_IMF_VIEWS_INDIVIDUAL;
}
else {
- ImBuf *ibuf = image_get_cached_ibuf_for_index_entry(ima, IMA_NO_INDEX, 0, NULL);
+ ImBuf *ibuf = image_get_cached_ibuf_for_index_entry(ima, IMA_NO_INDEX, 0, nullptr);
if (ibuf) {
ok = ok && image_memorypack_imbuf(ima, ibuf, ibuf->name);
@@ -1246,7 +1281,8 @@ void BKE_image_packfiles(ReportList *reports, Image *ima, const char *basepath)
const int totfiles = image_num_files(ima);
if (totfiles == 1) {
- ImagePackedFile *imapf = MEM_mallocN(sizeof(ImagePackedFile), "Image packed file");
+ ImagePackedFile *imapf = static_cast<ImagePackedFile *>(
+ MEM_mallocN(sizeof(ImagePackedFile), "Image packed file"));
BLI_addtail(&ima->packedfiles, imapf);
imapf->packedfile = BKE_packedfile_new(reports, ima->filepath, basepath);
if (imapf->packedfile) {
@@ -1257,9 +1293,9 @@ void BKE_image_packfiles(ReportList *reports, Image *ima, const char *basepath)
}
}
else {
- ImageView *iv;
- for (iv = ima->views.first; iv; iv = iv->next) {
- ImagePackedFile *imapf = MEM_mallocN(sizeof(ImagePackedFile), "Image packed file");
+ for (ImageView *iv = static_cast<ImageView *>(ima->views.first); iv; iv = iv->next) {
+ ImagePackedFile *imapf = static_cast<ImagePackedFile *>(
+ MEM_mallocN(sizeof(ImagePackedFile), "Image packed file"));
BLI_addtail(&ima->packedfiles, imapf);
imapf->packedfile = BKE_packedfile_new(reports, iv->filepath, basepath);
@@ -1284,7 +1320,8 @@ void BKE_image_packfiles_from_mem(ReportList *reports,
BKE_report(reports, RPT_ERROR, "Cannot pack multiview images from raw data currently...");
}
else {
- ImagePackedFile *imapf = MEM_mallocN(sizeof(ImagePackedFile), __func__);
+ ImagePackedFile *imapf = static_cast<ImagePackedFile *>(
+ MEM_mallocN(sizeof(ImagePackedFile), __func__));
BLI_addtail(&ima->packedfiles, imapf);
imapf->packedfile = BKE_packedfile_new_from_memory(data, data_len);
STRNCPY(imapf->filepath, ima->filepath);
@@ -1305,15 +1342,15 @@ static uintptr_t image_mem_size(Image *image)
return 0;
}
- BLI_mutex_lock(image->runtime.cache_mutex);
+ BLI_mutex_lock(static_cast<ThreadMutex *>(image->runtime.cache_mutex));
- if (image->cache != NULL) {
+ if (image->cache != nullptr) {
struct MovieCacheIter *iter = IMB_moviecacheIter_new(image->cache);
while (!IMB_moviecacheIter_done(iter)) {
ImBuf *ibuf = IMB_moviecacheIter_getImBuf(iter);
IMB_moviecacheIter_step(iter);
- if (ibuf == NULL) {
+ if (ibuf == nullptr) {
continue;
}
ImBuf *ibufm;
@@ -1341,7 +1378,7 @@ static uintptr_t image_mem_size(Image *image)
IMB_moviecacheIter_free(iter);
}
- BLI_mutex_unlock(image->runtime.cache_mutex);
+ BLI_mutex_unlock(static_cast<ThreadMutex *>(image->runtime.cache_mutex));
return size;
}
@@ -1351,13 +1388,15 @@ void BKE_image_print_memlist(Main *bmain)
Image *ima;
uintptr_t size, totsize = 0;
- for (ima = bmain->images.first; ima; ima = ima->id.next) {
+ for (ima = static_cast<Image *>(bmain->images.first); ima;
+ ima = static_cast<Image *>(ima->id.next)) {
totsize += image_mem_size(ima);
}
printf("\ntotal image memory len: %.3f MB\n", (double)totsize / (double)(1024 * 1024));
- for (ima = bmain->images.first; ima; ima = ima->id.next) {
+ for (ima = static_cast<Image *>(bmain->images.first); ima;
+ ima = static_cast<Image *>(ima->id.next)) {
size = image_mem_size(ima);
if (size) {
@@ -1368,7 +1407,7 @@ void BKE_image_print_memlist(Main *bmain)
static bool imagecache_check_dirty(ImBuf *ibuf, void *UNUSED(userkey), void *UNUSED(userdata))
{
- if (ibuf == NULL) {
+ if (ibuf == nullptr) {
return false;
}
return (ibuf->userflags & IB_BITMAPDIRTY) == 0;
@@ -1384,23 +1423,26 @@ void BKE_image_free_all_textures(Main *bmain)
uintptr_t tot_freed_size = 0;
#endif
- for (ima = bmain->images.first; ima; ima = ima->id.next) {
+ for (ima = static_cast<Image *>(bmain->images.first); ima;
+ ima = static_cast<Image *>(ima->id.next)) {
ima->id.tag &= ~LIB_TAG_DOIT;
}
- for (tex = bmain->textures.first; tex; tex = tex->id.next) {
+ for (tex = static_cast<Tex *>(bmain->textures.first); tex;
+ tex = static_cast<Tex *>(tex->id.next)) {
if (tex->ima) {
tex->ima->id.tag |= LIB_TAG_DOIT;
}
}
- for (ima = bmain->images.first; ima; ima = ima->id.next) {
+ for (ima = static_cast<Image *>(bmain->images.first); ima;
+ ima = static_cast<Image *>(ima->id.next)) {
if (ima->cache && (ima->id.tag & LIB_TAG_DOIT)) {
#ifdef CHECK_FREED_SIZE
uintptr_t old_size = image_mem_size(ima);
#endif
- IMB_moviecache_cleanup(ima->cache, imagecache_check_dirty, NULL);
+ IMB_moviecache_cleanup(ima->cache, imagecache_check_dirty, nullptr);
#ifdef CHECK_FREED_SIZE
tot_freed_size += old_size - image_mem_size(ima);
@@ -1414,7 +1456,7 @@ void BKE_image_free_all_textures(Main *bmain)
static bool imagecache_check_free_anim(ImBuf *ibuf, void *UNUSED(userkey), void *userdata)
{
- if (ibuf == NULL) {
+ if (ibuf == nullptr) {
return true;
}
int except_frame = *(int *)userdata;
@@ -1424,25 +1466,30 @@ static bool imagecache_check_free_anim(ImBuf *ibuf, void *UNUSED(userkey), void
void BKE_image_free_anim_ibufs(Image *ima, int except_frame)
{
- BLI_mutex_lock(ima->runtime.cache_mutex);
- if (ima->cache != NULL) {
+ BLI_mutex_lock(static_cast<ThreadMutex *>(ima->runtime.cache_mutex));
+ if (ima->cache != nullptr) {
IMB_moviecache_cleanup(ima->cache, imagecache_check_free_anim, &except_frame);
}
- BLI_mutex_unlock(ima->runtime.cache_mutex);
+ BLI_mutex_unlock(static_cast<ThreadMutex *>(ima->runtime.cache_mutex));
}
void BKE_image_all_free_anim_ibufs(Main *bmain, int cfra)
{
Image *ima;
- for (ima = bmain->images.first; ima; ima = ima->id.next) {
+ for (ima = static_cast<Image *>(bmain->images.first); ima;
+ ima = static_cast<Image *>(ima->id.next)) {
if (BKE_image_is_animated(ima)) {
BKE_image_free_anim_ibufs(ima, cfra);
}
}
}
-/* *********** READ AND WRITE ************** */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Read and Write
+ * \{ */
int BKE_image_imtype_to_ftype(const char imtype, ImbFormatOptions *r_options)
{
@@ -1577,7 +1624,7 @@ bool BKE_imtype_supports_zbuf(const char imtype)
{
switch (imtype) {
case R_IMF_IMTYPE_IRIZ:
- case R_IMF_IMTYPE_OPENEXR: /* but not R_IMF_IMTYPE_MULTILAYER */
+ case R_IMF_IMTYPE_OPENEXR: /* But not #R_IMF_IMTYPE_MULTILAYER. */
return true;
}
return false;
@@ -1765,7 +1812,7 @@ static bool do_add_image_extension(char *string,
const char imtype,
const ImageFormatData *im_format)
{
- const char *extension = NULL;
+ const char *extension = nullptr;
const char *extension_test;
(void)im_format; /* may be unused, depends on build options */
@@ -1815,7 +1862,7 @@ static bool do_add_image_extension(char *string,
}
#ifdef WITH_TIFF
else if (imtype == R_IMF_IMTYPE_TIFF) {
- if (!BLI_path_extension_check_n(string, extension_test = ".tif", ".tiff", NULL)) {
+ if (!BLI_path_extension_check_n(string, extension_test = ".tif", ".tiff", nullptr)) {
extension = extension_test;
}
}
@@ -1871,7 +1918,7 @@ static bool do_add_image_extension(char *string,
}
#endif
else { // R_IMF_IMTYPE_AVIRAW, R_IMF_IMTYPE_AVIJPEG, R_IMF_IMTYPE_JPEG90 etc
- if (!(BLI_path_extension_check_n(string, extension_test = ".jpg", ".jpeg", NULL))) {
+ if (!(BLI_path_extension_check_n(string, extension_test = ".jpg", ".jpeg", nullptr))) {
extension = extension_test;
}
}
@@ -1896,7 +1943,7 @@ int BKE_image_path_ensure_ext_from_imformat(char *string, const ImageFormatData
int BKE_image_path_ensure_ext_from_imtype(char *string, const char imtype)
{
- return do_add_image_extension(string, imtype, NULL);
+ return do_add_image_extension(string, imtype, nullptr);
}
void BKE_imformat_defaults(ImageFormatData *im_format)
@@ -2048,15 +2095,15 @@ void BKE_imbuf_to_image_format(struct ImageFormatData *im_format, const ImBuf *i
#define STAMP_NAME_SIZE ((MAX_ID_NAME - 2) + 16)
/* could allow access externally - 512 is for long names,
* STAMP_NAME_SIZE is for id names, allowing them some room for description */
-typedef struct StampDataCustomField {
+struct StampDataCustomField {
struct StampDataCustomField *next, *prev;
/* TODO(sergey): Think of better size here, maybe dynamically allocated even. */
char key[512];
char *value;
/* TODO(sergey): Support non-string values. */
-} StampDataCustomField;
+};
-typedef struct StampData {
+struct StampData {
char file[512];
char note[512];
char date[512];
@@ -2078,7 +2125,7 @@ typedef struct StampData {
* NOTE: This fields are not stamped onto the image. At least for now.
*/
ListBase custom_fields;
-} StampData;
+};
#undef STAMP_NAME_SIZE
/**
@@ -2111,7 +2158,7 @@ static void stampdata(
}
if (scene->r.stamp & R_STAMP_DATE) {
- t = time(NULL);
+ t = time(nullptr);
tl = localtime(&t);
SNPRINTF(text,
"%04d/%02d/%02d %02d:%02d:%02d",
@@ -2226,7 +2273,7 @@ static void stampdata(
{
Render *re = RE_GetSceneRender(scene);
- RenderStats *stats = re ? RE_GetStats(re) : NULL;
+ RenderStats *stats = re ? RE_GetStats(re) : nullptr;
if (use_dynamic && stats && (scene->r.stamp & R_STAMP_RENDERTIME)) {
BLI_timecode_string_from_time_simple(text, sizeof(text), stats->lastframetime);
@@ -2399,7 +2446,7 @@ void BKE_image_stamp_buf(Scene *scene,
display = IMB_colormanagement_display_get_named(display_device);
bool do_prefix = (scene->r.stamp & R_STAMP_HIDE_LABELS) == 0;
- if (stamp_data_template == NULL) {
+ if (stamp_data_template == nullptr) {
stampdata(scene, camera, &stamp_data, do_prefix, true);
}
else {
@@ -2717,7 +2764,7 @@ void BKE_image_stamp_buf(Scene *scene,
}
/* cleanup the buffer. */
- BLF_buffer(mono, NULL, NULL, 0, 0, 0, NULL);
+ BLF_buffer(mono, nullptr, nullptr, 0, 0, 0, nullptr);
BLF_wordwrap(mono, 0);
#undef TEXT_SIZE_CHECK
@@ -2738,7 +2785,7 @@ void BKE_render_result_stamp_info(Scene *scene,
}
if (!rr->stamp_data) {
- stamp_data = MEM_callocN(sizeof(StampData), "RenderResult.stamp_data");
+ stamp_data = MEM_cnew<StampData>("RenderResult.stamp_data");
}
else {
stamp_data = rr->stamp_data;
@@ -2758,13 +2805,13 @@ struct StampData *BKE_stamp_info_from_scene_static(const Scene *scene)
struct StampData *stamp_data;
if (!(scene && (scene->r.stamp & R_STAMP_ALL))) {
- return NULL;
+ return nullptr;
}
/* Memory is allocated here (instead of by the caller) so that the caller
* doesn't have to know the size of the StampData struct. */
- stamp_data = MEM_callocN(sizeof(StampData), __func__);
- stampdata(scene, NULL, stamp_data, 0, false);
+ stamp_data = MEM_cnew<StampData>(__func__);
+ stampdata(scene, nullptr, stamp_data, 0, false);
return stamp_data;
}
@@ -2784,13 +2831,13 @@ static const char *stamp_metadata_fields[] = {
"RenderTime",
"Memory",
"Hostname",
- NULL,
+ nullptr,
};
bool BKE_stamp_is_known_field(const char *field_name)
{
int i = 0;
- while (stamp_metadata_fields[i] != NULL) {
+ while (stamp_metadata_fields[i] != nullptr) {
if (STREQ(field_name, stamp_metadata_fields[i])) {
return true;
}
@@ -2804,7 +2851,7 @@ void BKE_stamp_info_callback(void *data,
StampCallback callback,
bool noskip)
{
- if ((callback == NULL) || (stamp_data == NULL)) {
+ if ((callback == nullptr) || (stamp_data == nullptr)) {
return;
}
@@ -2843,12 +2890,12 @@ void BKE_stamp_info_callback(void *data,
void BKE_render_result_stamp_data(RenderResult *rr, const char *key, const char *value)
{
StampData *stamp_data;
- if (rr->stamp_data == NULL) {
- rr->stamp_data = MEM_callocN(sizeof(StampData), "RenderResult.stamp_data");
+ if (rr->stamp_data == nullptr) {
+ rr->stamp_data = MEM_cnew<StampData>("RenderResult.stamp_data");
}
stamp_data = rr->stamp_data;
- StampDataCustomField *field = MEM_mallocN(sizeof(StampDataCustomField),
- "StampData Custom Field");
+ StampDataCustomField *field = static_cast<StampDataCustomField *>(
+ MEM_mallocN(sizeof(StampDataCustomField), "StampData Custom Field"));
STRNCPY(field->key, key);
field->value = BLI_strdup(value);
BLI_addtail(&stamp_data->custom_fields, field);
@@ -2856,15 +2903,15 @@ void BKE_render_result_stamp_data(RenderResult *rr, const char *key, const char
StampData *BKE_stamp_data_copy(const StampData *stamp_data)
{
- if (stamp_data == NULL) {
- return NULL;
+ if (stamp_data == nullptr) {
+ return nullptr;
}
- StampData *stamp_datan = MEM_dupallocN(stamp_data);
+ StampData *stamp_datan = static_cast<StampData *>(MEM_dupallocN(stamp_data));
BLI_duplicatelist(&stamp_datan->custom_fields, &stamp_data->custom_fields);
LISTBASE_FOREACH (StampDataCustomField *, custom_fieldn, &stamp_datan->custom_fields) {
- custom_fieldn->value = MEM_dupallocN(custom_fieldn->value);
+ custom_fieldn->value = static_cast<char *>(MEM_dupallocN(custom_fieldn->value));
}
return stamp_datan;
@@ -2872,7 +2919,7 @@ StampData *BKE_stamp_data_copy(const StampData *stamp_data)
void BKE_stamp_data_free(StampData *stamp_data)
{
- if (stamp_data == NULL) {
+ if (stamp_data == nullptr) {
return;
}
LISTBASE_FOREACH (StampDataCustomField *, custom_field, &stamp_data->custom_fields) {
@@ -2886,14 +2933,14 @@ void BKE_stamp_data_free(StampData *stamp_data)
static void metadata_set_field(void *data, const char *propname, char *propvalue, int UNUSED(len))
{
/* We know it is an ImBuf* because that's what we pass to BKE_stamp_info_callback. */
- struct ImBuf *imbuf = data;
+ ImBuf *imbuf = static_cast<ImBuf *>(data);
IMB_metadata_set_field(imbuf->metadata, propname, propvalue);
}
static void metadata_get_field(void *data, const char *propname, char *propvalue, int len)
{
/* We know it is an ImBuf* because that's what we pass to BKE_stamp_info_callback. */
- struct ImBuf *imbuf = data;
+ ImBuf *imbuf = static_cast<ImBuf *>(data);
IMB_metadata_get_field(imbuf->metadata, propname, propvalue, len);
}
@@ -2915,8 +2962,8 @@ static void metadata_copy_custom_fields(const char *field, const char *value, vo
void BKE_stamp_info_from_imbuf(RenderResult *rr, struct ImBuf *ibuf)
{
- if (rr->stamp_data == NULL) {
- rr->stamp_data = MEM_callocN(sizeof(StampData), "RenderResult.stamp_data");
+ if (rr->stamp_data == nullptr) {
+ rr->stamp_data = MEM_cnew<StampData>("RenderResult.stamp_data");
}
struct StampData *stamp_data = rr->stamp_data;
IMB_metadata_ensure(&ibuf->metadata);
@@ -3101,7 +3148,7 @@ void BKE_imbuf_write_prepare(ImBuf *ibuf, const ImageFormatData *imf)
}
#endif
else {
- /* R_IMF_IMTYPE_JPEG90, etc. default we save jpegs */
+ /* #R_IMF_IMTYPE_JPEG90, etc. fallback to JPEG image. */
if (quality < 10) {
quality = 90;
}
@@ -3167,7 +3214,7 @@ static void do_makepicstring(char *string,
const bool use_frames,
const char *suffix)
{
- if (string == NULL) {
+ if (string == nullptr) {
return;
}
BLI_strncpy(string, base, FILE_MAX - 10); /* weak assumption */
@@ -3208,7 +3255,7 @@ void BKE_image_path_from_imtype(char *string,
const bool use_frames,
const char *suffix)
{
- do_makepicstring(string, base, relbase, frame, imtype, NULL, use_ext, use_frames, suffix);
+ do_makepicstring(string, base, relbase, frame, imtype, nullptr, use_ext, use_frames, suffix);
}
struct anim *openanim_noload(const char *name,
@@ -3228,12 +3275,12 @@ struct anim *openanim(const char *name, int flags, int streamindex, char colorsp
struct ImBuf *ibuf;
anim = IMB_open_anim(name, flags, streamindex, colorspace);
- if (anim == NULL) {
- return NULL;
+ if (anim == nullptr) {
+ return nullptr;
}
ibuf = IMB_anim_absolute(anim, 0, IMB_TC_NONE, IMB_PROXY_NONE);
- if (ibuf == NULL) {
+ if (ibuf == nullptr) {
if (BLI_exists(name)) {
printf("not an anim: %s\n", name);
}
@@ -3241,14 +3288,18 @@ struct anim *openanim(const char *name, int flags, int streamindex, char colorsp
printf("anim file doesn't exist: %s\n", name);
}
IMB_free_anim(anim);
- return NULL;
+ return nullptr;
}
IMB_freeImBuf(ibuf);
return anim;
}
-/* ************************* New Image API *************** */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name New Image API
+ * \{ */
/* Notes about Image storage
* - packedfile
@@ -3260,8 +3311,8 @@ struct anim *openanim(const char *name, int flags, int streamindex, char colorsp
* - renderresult
* -> comes from packedfile or filename
* - listbase
- * -> ibufs from exrhandle
- * - flipbook array
+ * -> ibufs from EXR-handle.
+ * - flip-book array
* -> ibufs come from movie, temporary renderresult or sequence
* - ibuf
* -> comes from packedfile or filename or generated
@@ -3271,7 +3322,8 @@ Image *BKE_image_ensure_viewer(Main *bmain, int type, const char *name)
{
Image *ima;
- for (ima = bmain->images.first; ima; ima = ima->id.next) {
+ for (ima = static_cast<Image *>(bmain->images.first); ima;
+ ima = static_cast<Image *>(ima->id.next)) {
if (ima->source == IMA_SRC_VIEWER) {
if (ima->type == type) {
break;
@@ -3279,7 +3331,7 @@ Image *BKE_image_ensure_viewer(Main *bmain, int type, const char *name)
}
}
- if (ima == NULL) {
+ if (ima == nullptr) {
ima = image_alloc(bmain, name, IMA_SRC_VIEWER, type);
}
@@ -3297,8 +3349,8 @@ static void image_viewer_create_views(const RenderData *rd, Image *ima)
image_add_view(ima, "", "");
}
else {
- SceneRenderView *srv;
- for (srv = rd->views.first; srv; srv = srv->next) {
+ for (SceneRenderView *srv = static_cast<SceneRenderView *>(rd->views.first); srv;
+ srv = srv->next) {
if (BKE_scene_multiview_is_render_view_active(rd, srv) == false) {
continue;
}
@@ -3326,9 +3378,10 @@ void BKE_image_ensure_viewer_views(const RenderData *rd, Image *ima, ImageUser *
SceneRenderView *srv;
ImageView *iv;
- for (iv = ima->views.first; iv; iv = iv->next) {
- srv = BLI_findstring(&rd->views, iv->name, offsetof(SceneRenderView, name));
- if ((srv == NULL) || (BKE_scene_multiview_is_render_view_active(rd, srv) == false)) {
+ for (iv = static_cast<ImageView *>(ima->views.first); iv; iv = iv->next) {
+ srv = static_cast<SceneRenderView *>(
+ BLI_findstring(&rd->views, iv->name, offsetof(SceneRenderView, name)));
+ if ((srv == nullptr) || (BKE_scene_multiview_is_render_view_active(rd, srv) == false)) {
do_reset = true;
break;
}
@@ -3336,7 +3389,7 @@ void BKE_image_ensure_viewer_views(const RenderData *rd, Image *ima, ImageUser *
}
if (do_reset) {
- BLI_mutex_lock(ima->runtime.cache_mutex);
+ BLI_mutex_lock(static_cast<ThreadMutex *>(ima->runtime.cache_mutex));
image_free_cached_frames(ima);
BKE_image_free_views(ima);
@@ -3344,7 +3397,7 @@ void BKE_image_ensure_viewer_views(const RenderData *rd, Image *ima, ImageUser *
/* add new views */
image_viewer_create_views(rd, ima);
- BLI_mutex_unlock(ima->runtime.cache_mutex);
+ BLI_mutex_unlock(static_cast<ThreadMutex *>(ima->runtime.cache_mutex));
}
BLI_thread_unlock(LOCK_DRAW_IMAGE);
@@ -3361,12 +3414,12 @@ static void image_walk_ntree_all_users(
LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
if (node->id) {
if (node->type == SH_NODE_TEX_IMAGE) {
- NodeTexImage *tex = node->storage;
+ NodeTexImage *tex = static_cast<NodeTexImage *>(node->storage);
Image *ima = (Image *)node->id;
callback(ima, id, &tex->iuser, customdata);
}
if (node->type == SH_NODE_TEX_ENVIRONMENT) {
- NodeTexImage *tex = node->storage;
+ NodeTexImage *tex = static_cast<NodeTexImage *>(node->storage);
Image *ima = (Image *)node->id;
callback(ima, id, &tex->iuser, customdata);
}
@@ -3377,7 +3430,7 @@ static void image_walk_ntree_all_users(
LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
if (node->id && node->type == TEX_NODE_IMAGE) {
Image *ima = (Image *)node->id;
- ImageUser *iuser = node->storage;
+ ImageUser *iuser = static_cast<ImageUser *>(node->storage);
callback(ima, id, iuser, customdata);
}
}
@@ -3386,7 +3439,7 @@ static void image_walk_ntree_all_users(
LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
if (node->id && node->type == CMP_NODE_IMAGE) {
Image *ima = (Image *)node->id;
- ImageUser *iuser = node->storage;
+ ImageUser *iuser = static_cast<ImageUser *>(node->storage);
callback(ima, id, iuser, customdata);
}
}
@@ -3421,7 +3474,7 @@ static void image_walk_id_all_users(
case ID_OB: {
Object *ob = (Object *)id;
if (ob->empty_drawtype == OB_EMPTY_IMAGE && ob->data) {
- callback(ob->data, &ob->id, ob->iuser, customdata);
+ callback(static_cast<Image *>(ob->data), &ob->id, ob->iuser, customdata);
}
break;
}
@@ -3466,7 +3519,7 @@ static void image_walk_id_all_users(
case ID_CA: {
Camera *cam = (Camera *)id;
LISTBASE_FOREACH (CameraBGImage *, bgpic, &cam->bg_images) {
- callback(bgpic->ima, NULL, &bgpic->iuser, customdata);
+ callback(bgpic->ima, nullptr, &bgpic->iuser, customdata);
}
break;
}
@@ -3477,8 +3530,8 @@ static void image_walk_id_all_users(
LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
if (area->spacetype == SPACE_IMAGE) {
- SpaceImage *sima = area->spacedata.first;
- callback(sima->image, NULL, &sima->iuser, customdata);
+ SpaceImage *sima = static_cast<SpaceImage *>(area->spacedata.first);
+ callback(sima->image, nullptr, &sima->iuser, customdata);
}
}
}
@@ -3506,46 +3559,55 @@ void BKE_image_walk_all_users(
void *customdata,
void callback(Image *ima, ID *iuser_id, ImageUser *iuser, void *customdata))
{
- for (Scene *scene = mainp->scenes.first; scene; scene = scene->id.next) {
+ for (Scene *scene = static_cast<Scene *>(mainp->scenes.first); scene;
+ scene = static_cast<Scene *>(scene->id.next)) {
image_walk_id_all_users(&scene->id, false, customdata, callback);
}
- for (Object *ob = mainp->objects.first; ob; ob = ob->id.next) {
+ for (Object *ob = static_cast<Object *>(mainp->objects.first); ob;
+ ob = static_cast<Object *>(ob->id.next)) {
image_walk_id_all_users(&ob->id, false, customdata, callback);
}
- for (bNodeTree *ntree = mainp->nodetrees.first; ntree; ntree = ntree->id.next) {
+ for (bNodeTree *ntree = static_cast<bNodeTree *>(mainp->nodetrees.first); ntree;
+ ntree = static_cast<bNodeTree *>(ntree->id.next)) {
image_walk_id_all_users(&ntree->id, false, customdata, callback);
}
- for (Material *ma = mainp->materials.first; ma; ma = ma->id.next) {
+ for (Material *ma = static_cast<Material *>(mainp->materials.first); ma;
+ ma = static_cast<Material *>(ma->id.next)) {
image_walk_id_all_users(&ma->id, false, customdata, callback);
}
- for (Light *light = mainp->materials.first; light; light = light->id.next) {
+ for (Light *light = static_cast<Light *>(mainp->materials.first); light;
+ light = static_cast<Light *>(light->id.next)) {
image_walk_id_all_users(&light->id, false, customdata, callback);
}
- for (World *world = mainp->materials.first; world; world = world->id.next) {
+ for (World *world = static_cast<World *>(mainp->materials.first); world;
+ world = static_cast<World *>(world->id.next)) {
image_walk_id_all_users(&world->id, false, customdata, callback);
}
- for (Tex *tex = mainp->textures.first; tex; tex = tex->id.next) {
+ for (Tex *tex = static_cast<Tex *>(mainp->textures.first); tex;
+ tex = static_cast<Tex *>(tex->id.next)) {
image_walk_id_all_users(&tex->id, false, customdata, callback);
}
- for (Camera *cam = mainp->cameras.first; cam; cam = cam->id.next) {
+ for (Camera *cam = static_cast<Camera *>(mainp->cameras.first); cam;
+ cam = static_cast<Camera *>(cam->id.next)) {
image_walk_id_all_users(&cam->id, false, customdata, callback);
}
- for (wmWindowManager *wm = mainp->wm.first; wm; wm = wm->id.next) { /* only 1 wm */
+ for (wmWindowManager *wm = static_cast<wmWindowManager *>(mainp->wm.first); wm;
+ wm = static_cast<wmWindowManager *>(wm->id.next)) { /* only 1 wm */
image_walk_id_all_users(&wm->id, false, customdata, callback);
}
}
static void image_tag_frame_recalc(Image *ima, ID *iuser_id, ImageUser *iuser, void *customdata)
{
- Image *changed_image = customdata;
+ Image *changed_image = static_cast<Image *>(customdata);
if (ima == changed_image && BKE_image_is_animated(ima)) {
iuser->flag |= IMA_NEED_FRAME_RECALC;
@@ -3559,7 +3621,7 @@ static void image_tag_frame_recalc(Image *ima, ID *iuser_id, ImageUser *iuser, v
static void image_tag_reload(Image *ima, ID *iuser_id, ImageUser *iuser, void *customdata)
{
- Image *changed_image = customdata;
+ Image *changed_image = static_cast<Image *>(customdata);
if (ima == changed_image) {
if (iuser->scene) {
@@ -3603,9 +3665,9 @@ static void image_free_tile(Image *ima, ImageTile *tile)
for (int eye = 0; eye < 2; eye++) {
for (int resolution = 0; resolution < IMA_TEXTURE_RESOLUTION_LEN; resolution++) {
- if (ima->gputexture[i][eye][resolution] != NULL) {
+ if (ima->gputexture[i][eye][resolution] != nullptr) {
GPU_texture_free(ima->gputexture[i][eye][resolution]);
- ima->gputexture[i][eye][resolution] = NULL;
+ ima->gputexture[i][eye][resolution] = nullptr;
}
}
}
@@ -3625,11 +3687,11 @@ static void image_free_tile(Image *ima, ImageTile *tile)
void BKE_image_signal(Main *bmain, Image *ima, ImageUser *iuser, int signal)
{
- if (ima == NULL) {
+ if (ima == nullptr) {
return;
}
- BLI_mutex_lock(ima->runtime.cache_mutex);
+ BLI_mutex_lock(static_cast<ThreadMutex *>(ima->runtime.cache_mutex));
switch (signal) {
case IMA_SIGNAL_FREE:
@@ -3650,7 +3712,7 @@ void BKE_image_signal(Main *bmain, Image *ima, ImageUser *iuser, int signal)
if (ima->source == IMA_SRC_GENERATED) {
if (ima->gen_x == 0 || ima->gen_y == 0) {
- ImBuf *ibuf = image_get_cached_ibuf_for_index_entry(ima, IMA_NO_INDEX, 0, NULL);
+ ImBuf *ibuf = image_get_cached_ibuf_for_index_entry(ima, IMA_NO_INDEX, 0, nullptr);
if (ibuf) {
ima->gen_x = ibuf->x;
ima->gen_y = ibuf->y;
@@ -3677,7 +3739,7 @@ void BKE_image_signal(Main *bmain, Image *ima, ImageUser *iuser, int signal)
image_free_tile(ima, tile);
MEM_freeN(tile);
}
- base_tile->next = NULL;
+ base_tile->next = nullptr;
ima->tiles.last = base_tile;
}
@@ -3691,7 +3753,7 @@ void BKE_image_signal(Main *bmain, Image *ima, ImageUser *iuser, int signal)
BKE_image_free_buffers(ima);
if (iuser) {
- image_tag_frame_recalc(ima, NULL, iuser, ima);
+ image_tag_frame_recalc(ima, nullptr, iuser, ima);
}
BKE_image_walk_all_users(bmain, ima, image_tag_frame_recalc);
@@ -3705,13 +3767,14 @@ void BKE_image_signal(Main *bmain, Image *ima, ImageUser *iuser, int signal)
if (totfiles != BLI_listbase_count_at_most(&ima->packedfiles, totfiles + 1)) {
/* in case there are new available files to be loaded */
image_free_packedfiles(ima);
- BKE_image_packfiles(NULL, ima, ID_BLEND_PATH(bmain, &ima->id));
+ BKE_image_packfiles(nullptr, ima, ID_BLEND_PATH(bmain, &ima->id));
}
else {
ImagePackedFile *imapf;
- for (imapf = ima->packedfiles.first; imapf; imapf = imapf->next) {
+ for (imapf = static_cast<ImagePackedFile *>(ima->packedfiles.first); imapf;
+ imapf = imapf->next) {
PackedFile *pf;
- pf = BKE_packedfile_new(NULL, imapf->filepath, ID_BLEND_PATH(bmain, &ima->id));
+ pf = BKE_packedfile_new(nullptr, imapf->filepath, ID_BLEND_PATH(bmain, &ima->id));
if (pf) {
BKE_packedfile_free(imapf->packedfile);
imapf->packedfile = pf;
@@ -3731,7 +3794,7 @@ void BKE_image_signal(Main *bmain, Image *ima, ImageUser *iuser, int signal)
}
if (ima->source == IMA_SRC_TILED) {
- ListBase new_tiles = {NULL, NULL};
+ ListBase new_tiles = {nullptr, nullptr};
int new_start, new_range;
char filepath[FILE_MAX];
@@ -3743,7 +3806,7 @@ void BKE_image_signal(Main *bmain, Image *ima, ImageUser *iuser, int signal)
* to account for how the two sets might or might not overlap. To be complete, we start
* the refresh process by clearing all existing tiles, stopping when there's only 1 tile
* left. */
- while (BKE_image_remove_tile(ima, ima->tiles.last)) {
+ while (BKE_image_remove_tile(ima, static_cast<ImageTile *>(ima->tiles.last))) {
;
}
@@ -3753,7 +3816,7 @@ void BKE_image_signal(Main *bmain, Image *ima, ImageUser *iuser, int signal)
/* Add in all the new tiles. */
LISTBASE_FOREACH (LinkData *, new_tile, &new_tiles) {
int new_tile_number = POINTER_AS_INT(new_tile->data);
- BKE_image_add_tile(ima, new_tile_number, NULL);
+ BKE_image_add_tile(ima, new_tile_number, nullptr);
if (new_tile_number == remaining_tile_number) {
needs_final_cleanup = false;
}
@@ -3768,7 +3831,7 @@ void BKE_image_signal(Main *bmain, Image *ima, ImageUser *iuser, int signal)
}
if (iuser) {
- image_tag_reload(ima, NULL, iuser, ima);
+ image_tag_reload(ima, nullptr, iuser, ima);
}
BKE_image_walk_all_users(bmain, ima, image_tag_reload);
break;
@@ -3786,26 +3849,29 @@ void BKE_image_signal(Main *bmain, Image *ima, ImageUser *iuser, int signal)
break;
}
- BLI_mutex_unlock(ima->runtime.cache_mutex);
+ BLI_mutex_unlock(static_cast<ThreadMutex *>(ima->runtime.cache_mutex));
BKE_ntree_update_tag_id_changed(bmain, &ima->id);
- BKE_ntree_update_main(bmain, NULL);
+ BKE_ntree_update_main(bmain, nullptr);
}
-/* return renderpass for a given pass index and active view */
-/* fallback to available if there are missing passes for active view */
+/**
+ * \return render-pass for a given pass index and active view.
+ * fallback to available if there are missing passes for active view.
+ */
static RenderPass *image_render_pass_get(RenderLayer *rl,
const int pass,
const int view,
int *r_passindex)
{
- RenderPass *rpass_ret = NULL;
+ RenderPass *rpass_ret = nullptr;
RenderPass *rpass;
int rp_index = 0;
const char *rp_name = "";
- for (rpass = rl->passes.first; rpass; rpass = rpass->next, rp_index++) {
+ for (rpass = static_cast<RenderPass *>(rl->passes.first); rpass;
+ rpass = rpass->next, rp_index++) {
if (rp_index == pass) {
rpass_ret = rpass;
if (view == 0) {
@@ -3823,9 +3889,9 @@ static RenderPass *image_render_pass_get(RenderLayer *rl,
}
/* fallback to the first pass in the layer */
- if (rpass_ret == NULL) {
+ if (rpass_ret == nullptr) {
rp_index = 0;
- rpass_ret = rl->passes.first;
+ rpass_ret = static_cast<RenderPass *>(rl->passes.first);
}
if (r_passindex) {
@@ -3838,7 +3904,7 @@ static RenderPass *image_render_pass_get(RenderLayer *rl,
void BKE_image_get_tile_label(Image *ima, ImageTile *tile, char *label, int len_label)
{
label[0] = '\0';
- if (ima == NULL || tile == NULL) {
+ if (ima == nullptr || tile == nullptr) {
return;
}
@@ -3850,10 +3916,7 @@ void BKE_image_get_tile_label(Image *ima, ImageTile *tile, char *label, int len_
}
}
-bool BKE_image_get_tile_info(char *filepath,
- ListBase *udim_tiles,
- int *udim_start,
- int *udim_range)
+bool BKE_image_get_tile_info(char *filepath, ListBase *tiles, int *tile_start, int *tile_range)
{
char filename[FILE_MAXFILE], dirname[FILE_MAXDIR];
BLI_split_dirfile(filepath, dirname, filename, sizeof(dirname), sizeof(filename));
@@ -3884,7 +3947,7 @@ bool BKE_image_get_tile_info(char *filepath,
break;
}
- BLI_addtail(udim_tiles, BLI_genericNodeN(POINTER_FROM_INT(id)));
+ BLI_addtail(tiles, BLI_genericNodeN(POINTER_FROM_INT(id)));
min_udim = min_ii(min_udim, id);
max_udim = max_ii(max_udim, id);
}
@@ -3894,8 +3957,8 @@ bool BKE_image_get_tile_info(char *filepath,
if (is_udim && min_udim <= IMA_UDIM_MAX) {
BLI_join_dirfile(filepath, FILE_MAX, dirname, filename);
- *udim_start = min_udim;
- *udim_range = max_udim - min_udim + 1;
+ *tile_start = min_udim;
+ *tile_range = max_udim - min_udim + 1;
return true;
}
return false;
@@ -3904,27 +3967,28 @@ bool BKE_image_get_tile_info(char *filepath,
ImageTile *BKE_image_add_tile(struct Image *ima, int tile_number, const char *label)
{
if (ima->source != IMA_SRC_TILED) {
- return NULL;
+ return nullptr;
}
if (tile_number < 1001 || tile_number > IMA_UDIM_MAX) {
- return NULL;
+ return nullptr;
}
/* Search the first tile that has a higher number.
* We then insert before that to keep the list sorted. */
ImageTile *next_tile;
- for (next_tile = ima->tiles.first; next_tile; next_tile = next_tile->next) {
+ for (next_tile = static_cast<ImageTile *>(ima->tiles.first); next_tile;
+ next_tile = next_tile->next) {
if (next_tile->tile_number == tile_number) {
/* Tile already exists. */
- return NULL;
+ return nullptr;
}
if (next_tile->tile_number > tile_number) {
break;
}
}
- ImageTile *tile = MEM_callocN(sizeof(ImageTile), "image new tile");
+ ImageTile *tile = MEM_cnew<ImageTile>("image new tile");
tile->tile_number = tile_number;
if (next_tile) {
@@ -3941,13 +4005,13 @@ ImageTile *BKE_image_add_tile(struct Image *ima, int tile_number, const char *la
for (int eye = 0; eye < 2; eye++) {
for (int resolution = 0; resolution < IMA_TEXTURE_RESOLUTION_LEN; resolution++) {
/* Reallocate GPU tile array. */
- if (ima->gputexture[TEXTARGET_2D_ARRAY][eye][resolution] != NULL) {
+ if (ima->gputexture[TEXTARGET_2D_ARRAY][eye][resolution] != nullptr) {
GPU_texture_free(ima->gputexture[TEXTARGET_2D_ARRAY][eye][resolution]);
- ima->gputexture[TEXTARGET_2D_ARRAY][eye][resolution] = NULL;
+ ima->gputexture[TEXTARGET_2D_ARRAY][eye][resolution] = nullptr;
}
- if (ima->gputexture[TEXTARGET_TILE_MAPPING][eye][resolution] != NULL) {
+ if (ima->gputexture[TEXTARGET_TILE_MAPPING][eye][resolution] != nullptr) {
GPU_texture_free(ima->gputexture[TEXTARGET_TILE_MAPPING][eye][resolution]);
- ima->gputexture[TEXTARGET_TILE_MAPPING][eye][resolution] = NULL;
+ ima->gputexture[TEXTARGET_TILE_MAPPING][eye][resolution] = nullptr;
}
}
}
@@ -3958,7 +4022,7 @@ ImageTile *BKE_image_add_tile(struct Image *ima, int tile_number, const char *la
bool BKE_image_remove_tile(struct Image *ima, ImageTile *tile)
{
- if (ima == NULL || tile == NULL || ima->source != IMA_SRC_TILED) {
+ if (ima == nullptr || tile == nullptr || ima->source != IMA_SRC_TILED) {
return false;
}
@@ -3976,7 +4040,7 @@ bool BKE_image_remove_tile(struct Image *ima, ImageTile *tile)
void BKE_image_reassign_tile(struct Image *ima, ImageTile *tile, int new_tile_number)
{
- if (ima == NULL || tile == NULL || ima->source != IMA_SRC_TILED) {
+ if (ima == nullptr || tile == nullptr || ima->source != IMA_SRC_TILED) {
return;
}
@@ -3990,14 +4054,14 @@ void BKE_image_reassign_tile(struct Image *ima, ImageTile *tile, int new_tile_nu
if (BKE_image_is_multiview(ima)) {
const int totviews = BLI_listbase_count(&ima->views);
for (int i = 0; i < totviews; i++) {
- ImBuf *ibuf = image_get_cached_ibuf_for_index_entry(ima, i, old_tile_number, NULL);
+ ImBuf *ibuf = image_get_cached_ibuf_for_index_entry(ima, i, old_tile_number, nullptr);
image_remove_ibuf(ima, i, old_tile_number);
image_assign_ibuf(ima, ibuf, i, new_tile_number);
IMB_freeImBuf(ibuf);
}
}
else {
- ImBuf *ibuf = image_get_cached_ibuf_for_index_entry(ima, 0, old_tile_number, NULL);
+ ImBuf *ibuf = image_get_cached_ibuf_for_index_entry(ima, 0, old_tile_number, nullptr);
image_remove_ibuf(ima, 0, old_tile_number);
image_assign_ibuf(ima, ibuf, 0, new_tile_number);
IMB_freeImBuf(ibuf);
@@ -4007,13 +4071,13 @@ void BKE_image_reassign_tile(struct Image *ima, ImageTile *tile, int new_tile_nu
for (int resolution = 0; resolution < IMA_TEXTURE_RESOLUTION_LEN; resolution++) {
/* Reallocate GPU tile array. */
- if (ima->gputexture[TEXTARGET_2D_ARRAY][eye][resolution] != NULL) {
+ if (ima->gputexture[TEXTARGET_2D_ARRAY][eye][resolution] != nullptr) {
GPU_texture_free(ima->gputexture[TEXTARGET_2D_ARRAY][eye][resolution]);
- ima->gputexture[TEXTARGET_2D_ARRAY][eye][resolution] = NULL;
+ ima->gputexture[TEXTARGET_2D_ARRAY][eye][resolution] = nullptr;
}
- if (ima->gputexture[TEXTARGET_TILE_MAPPING][eye][resolution] != NULL) {
+ if (ima->gputexture[TEXTARGET_TILE_MAPPING][eye][resolution] != nullptr) {
GPU_texture_free(ima->gputexture[TEXTARGET_TILE_MAPPING][eye][resolution]);
- ima->gputexture[TEXTARGET_TILE_MAPPING][eye][resolution] = NULL;
+ ima->gputexture[TEXTARGET_TILE_MAPPING][eye][resolution] = nullptr;
}
}
}
@@ -4022,14 +4086,14 @@ void BKE_image_reassign_tile(struct Image *ima, ImageTile *tile, int new_tile_nu
static int tile_sort_cb(const void *a, const void *b)
{
- const ImageTile *tile_a = a;
- const ImageTile *tile_b = b;
+ const ImageTile *tile_a = static_cast<const ImageTile *>(a);
+ const ImageTile *tile_b = static_cast<const ImageTile *>(b);
return (tile_a->tile_number > tile_b->tile_number) ? 1 : 0;
}
void BKE_image_sort_tiles(struct Image *ima)
{
- if (ima == NULL || ima->source != IMA_SRC_TILED) {
+ if (ima == nullptr || ima->source != IMA_SRC_TILED) {
return;
}
@@ -4045,7 +4109,7 @@ bool BKE_image_fill_tile(struct Image *ima,
int planes,
bool is_float)
{
- if (ima == NULL || tile == NULL || ima->source != IMA_SRC_TILED) {
+ if (ima == nullptr || tile == nullptr || ima->source != IMA_SRC_TILED) {
return false;
}
@@ -4054,9 +4118,9 @@ bool BKE_image_fill_tile(struct Image *ima,
ImBuf *tile_ibuf = add_ibuf_size(
width, height, ima->filepath, planes, is_float, gen_type, color, &ima->colorspace_settings);
- if (tile_ibuf != NULL) {
+ if (tile_ibuf != nullptr) {
image_assign_ibuf(ima, tile_ibuf, 0, tile->tile_number);
- BKE_image_release_ibuf(ima, tile_ibuf, NULL);
+ BKE_image_release_ibuf(ima, tile_ibuf, nullptr);
return true;
}
return false;
@@ -4064,11 +4128,11 @@ bool BKE_image_fill_tile(struct Image *ima,
void BKE_image_ensure_tile_token(char *filename)
{
- BLI_assert_msg(BLI_path_slash_find(filename) == NULL,
+ BLI_assert_msg(BLI_path_slash_find(filename) == nullptr,
"Only the file-name component should be used!");
/* Is there a '<' character in the filename? Assume tokens already present. */
- if (strstr(filename, "<") != NULL) {
+ if (strstr(filename, "<") != nullptr) {
return;
}
@@ -4176,21 +4240,21 @@ bool BKE_image_tile_filepath_exists(const char *filepath)
char *BKE_image_get_tile_strformat(const char *filepath, eUDIM_TILE_FORMAT *r_tile_format)
{
- if (filepath == NULL || r_tile_format == NULL) {
- return NULL;
+ if (filepath == nullptr || r_tile_format == nullptr) {
+ return nullptr;
}
- if (strstr(filepath, "<UDIM>") != NULL) {
+ if (strstr(filepath, "<UDIM>") != nullptr) {
*r_tile_format = UDIM_TILE_FORMAT_UDIM;
return BLI_str_replaceN(filepath, "<UDIM>", "%d");
}
- if (strstr(filepath, "<UVTILE>") != NULL) {
+ if (strstr(filepath, "<UVTILE>") != nullptr) {
*r_tile_format = UDIM_TILE_FORMAT_UVTILE;
return BLI_str_replaceN(filepath, "<UVTILE>", "u%d_v%d");
}
*r_tile_format = UDIM_TILE_FORMAT_NONE;
- return NULL;
+ return nullptr;
}
bool BKE_image_get_tile_number_from_filepath(const char *filepath,
@@ -4198,7 +4262,7 @@ bool BKE_image_get_tile_number_from_filepath(const char *filepath,
eUDIM_TILE_FORMAT tile_format,
int *r_tile_number)
{
- if (filepath == NULL || pattern == NULL || r_tile_number == NULL) {
+ if (filepath == nullptr || pattern == nullptr || r_tile_number == nullptr) {
return false;
}
@@ -4226,7 +4290,7 @@ void BKE_image_set_filepath_from_tile_number(char *filepath,
eUDIM_TILE_FORMAT tile_format,
int tile_number)
{
- if (filepath == NULL || pattern == NULL) {
+ if (filepath == nullptr || pattern == nullptr) {
return;
}
@@ -4245,10 +4309,10 @@ void BKE_image_set_filepath_from_tile_number(char *filepath,
RenderPass *BKE_image_multilayer_index(RenderResult *rr, ImageUser *iuser)
{
RenderLayer *rl;
- RenderPass *rpass = NULL;
+ RenderPass *rpass = nullptr;
- if (rr == NULL) {
- return NULL;
+ if (rr == nullptr) {
+ return nullptr;
}
if (iuser) {
@@ -4260,7 +4324,7 @@ RenderPass *BKE_image_multilayer_index(RenderResult *rr, ImageUser *iuser)
rl_index += 1;
}
- for (rl = rr->layers.first; rl; rl = rl->next, rl_index++) {
+ for (rl = static_cast<RenderLayer *>(rr->layers.first); rl; rl = rl->next, rl_index++) {
if (iuser->layer == rl_index) {
int rp_index;
rpass = image_render_pass_get(rl, iuser->pass, rv_index, &rp_index);
@@ -4313,7 +4377,7 @@ bool BKE_image_is_multilayer(Image *ima)
bool BKE_image_is_multiview(Image *ima)
{
- ImageView *view = ima->views.first;
+ ImageView *view = static_cast<ImageView *>(ima->views.first);
return (view && (view->next || view->name[0]));
}
@@ -4331,8 +4395,8 @@ static void image_init_multilayer_multiview(Image *ima, RenderResult *rr)
* be acquired with a mutex along with the render result, but there are still
* some places with just an image pointer that need to access views */
if (rr && BLI_listbase_count(&ima->views) == BLI_listbase_count(&rr->views)) {
- ImageView *iv = ima->views.first;
- RenderView *rv = rr->views.first;
+ ImageView *iv = static_cast<ImageView *>(ima->views.first);
+ RenderView *rv = static_cast<RenderView *>(rr->views.first);
bool modified = false;
for (; rv; rv = rv->next, iv = iv->next) {
modified |= !STREQ(rv->name, iv->name);
@@ -4346,7 +4410,7 @@ static void image_init_multilayer_multiview(Image *ima, RenderResult *rr)
if (rr) {
LISTBASE_FOREACH (RenderView *, rv, &rr->views) {
- ImageView *iv = MEM_callocN(sizeof(ImageView), "Viewer Image View");
+ ImageView *iv = MEM_cnew<ImageView>("Viewer Image View");
STRNCPY(iv->name, rv->name);
BLI_addtail(&ima->views, iv);
}
@@ -4355,7 +4419,7 @@ static void image_init_multilayer_multiview(Image *ima, RenderResult *rr)
RenderResult *BKE_image_acquire_renderresult(Scene *scene, Image *ima)
{
- RenderResult *rr = NULL;
+ RenderResult *rr = nullptr;
if (ima->rr) {
rr = ima->rr;
}
@@ -4407,7 +4471,7 @@ void BKE_image_backup_render(Scene *scene, Image *ima, bool free_current_slot)
/* Ensure we always have a valid render slot. */
if (!ima->renderslots.first) {
- BKE_image_add_renderslot(ima, NULL);
+ BKE_image_add_renderslot(ima, nullptr);
ima->render_slot = 0;
ima->last_render_slot = 0;
}
@@ -4420,12 +4484,12 @@ void BKE_image_backup_render(Scene *scene, Image *ima, bool free_current_slot)
RenderSlot *cur_slot = BKE_image_get_renderslot(ima, ima->render_slot);
if (last_slot && ima->render_slot != ima->last_render_slot) {
- last_slot->render = NULL;
+ last_slot->render = nullptr;
RE_SwapResult(re, &last_slot->render);
if (cur_slot->render) {
if (free_current_slot) {
- BKE_image_clear_renderslot(ima, NULL, ima->render_slot);
+ BKE_image_clear_renderslot(ima, nullptr, ima->render_slot);
}
else {
RE_SwapResult(re, &cur_slot->render);
@@ -4436,13 +4500,17 @@ void BKE_image_backup_render(Scene *scene, Image *ima, bool free_current_slot)
ima->last_render_slot = ima->render_slot;
}
-/**************************** multiview load openexr *********************************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Multiview Load OpenEXR
+ * \{ */
static void image_add_view(Image *ima, const char *viewname, const char *filepath)
{
ImageView *iv;
- iv = MEM_mallocN(sizeof(ImageView), "Viewer Image View");
+ iv = static_cast<ImageView *>(MEM_mallocN(sizeof(ImageView), "Viewer Image View"));
STRNCPY(iv->name, viewname);
STRNCPY(iv->filepath, filepath);
@@ -4454,9 +4522,10 @@ static void image_add_view(Image *ima, const char *viewname, const char *filepat
BLI_addhead(&ima->views, iv);
}
else if (STREQ(viewname, STEREO_RIGHT_NAME)) {
- ImageView *left_iv = BLI_findstring(&ima->views, STEREO_LEFT_NAME, offsetof(ImageView, name));
+ ImageView *left_iv = static_cast<ImageView *>(
+ BLI_findstring(&ima->views, STEREO_LEFT_NAME, offsetof(ImageView, name)));
- if (left_iv == NULL) {
+ if (left_iv == nullptr) {
BLI_addhead(&ima->views, iv);
}
else {
@@ -4468,8 +4537,8 @@ static void image_add_view(Image *ima, const char *viewname, const char *filepat
}
}
-/* after imbuf load, openexr type can return with a exrhandle open */
-/* in that case we have to build a render-result */
+/* After imbuf load, OpenEXR type can return with a EXR-handle open
+ * in that case we have to build a render-result. */
#ifdef WITH_OPENEXR
static void image_create_multilayer(Image *ima, ImBuf *ibuf, int framenr)
{
@@ -4483,8 +4552,8 @@ static void image_create_multilayer(Image *ima, ImBuf *ibuf, int framenr)
IMB_exr_close(ibuf->userdata);
- ibuf->userdata = NULL;
- if (ima->rr != NULL) {
+ ibuf->userdata = nullptr;
+ if (ima->rr != nullptr) {
ima->rr->framenr = framenr;
BKE_stamp_info_from_imbuf(ima->rr, ibuf);
}
@@ -4494,12 +4563,12 @@ static void image_create_multilayer(Image *ima, ImBuf *ibuf, int framenr)
}
#endif /* WITH_OPENEXR */
-/* common stuff to do with images after loading */
+/** Common stuff to do with images after loading. */
static void image_init_after_load(Image *ima, ImageUser *iuser, ImBuf *UNUSED(ibuf))
{
- /* Preview is NULL when it has never been used as an icon before.
+ /* Preview is null when it has never been used as an icon before.
* Never handle previews/icons outside of main thread. */
- if (G.background == 0 && ima->preview == NULL && BLI_thread_is_main()) {
+ if (G.background == 0 && ima->preview == nullptr && BLI_thread_is_main()) {
BKE_icon_changed(BKE_icon_id_ensure(&ima->id));
}
@@ -4509,7 +4578,7 @@ static void image_init_after_load(Image *ima, ImageUser *iuser, ImBuf *UNUSED(ib
ImageTile *tile = BKE_image_get_tile_from_iuser(ima, iuser);
/* Images should never get loaded if the corresponding tile does not exist,
* but we should at least not crash if it happens due to a bug elsewhere. */
- BLI_assert(tile != NULL);
+ BLI_assert(tile != nullptr);
UNUSED_VARS_NDEBUG(tile);
}
@@ -4529,7 +4598,9 @@ static int imbuf_alpha_flags_for_image(Image *ima)
return 0;
}
-/* the number of files will vary according to the stereo format */
+/**
+ * \return the number of files will vary according to the stereo format.
+ */
static int image_num_files(Image *ima)
{
const bool is_multiview = BKE_image_is_multiview(ima);
@@ -4551,7 +4622,7 @@ static ImBuf *load_sequence_single(
struct ImBuf *ibuf;
char name[FILE_MAX];
int flag;
- ImageUser iuser_t = {0};
+ ImageUser iuser_t{};
*r_cache_ibuf = true;
@@ -4593,9 +4664,9 @@ static ImBuf *load_sequence_single(
image_create_multilayer(ima, ibuf, frame);
ima->type = IMA_TYPE_MULTILAYER;
IMB_freeImBuf(ibuf);
- ibuf = NULL;
- /* NULL ibuf in the cache means the image failed to load. However for multilayer we load
- * pixels into RenderResult instead and intentionally leave ibuf NULL. */
+ ibuf = nullptr;
+ /* Null ibuf in the cache means the image failed to load. However for multilayer we load
+ * pixels into RenderResult instead and intentionally leave ibuf null. */
*r_cache_ibuf = false;
}
}
@@ -4612,7 +4683,7 @@ static ImBuf *load_sequence_single(
static ImBuf *image_load_sequence_file(Image *ima, ImageUser *iuser, int entry, int frame)
{
- struct ImBuf *ibuf = NULL;
+ struct ImBuf *ibuf = nullptr;
const bool is_multiview = BKE_image_is_multiview(ima);
const int totfiles = image_num_files(ima);
@@ -4625,13 +4696,11 @@ static ImBuf *image_load_sequence_file(Image *ima, ImageUser *iuser, int entry,
}
else {
const int totviews = BLI_listbase_count(&ima->views);
- struct ImBuf **ibuf_arr;
-
- ibuf_arr = MEM_mallocN(sizeof(ImBuf *) * totviews, "Image Views Imbufs");
- bool *cache_ibuf_arr = MEM_mallocN(sizeof(bool) * totviews, "Image View Put In Cache");
+ Array<ImBuf *> ibuf_arr(totviews);
+ Array<bool> cache_ibuf_arr(totviews);
for (int i = 0; i < totfiles; i++) {
- ibuf_arr[i] = load_sequence_single(ima, iuser, frame, i, cache_ibuf_arr + i);
+ ibuf_arr[i] = load_sequence_single(ima, iuser, frame, i, &cache_ibuf_arr[i]);
}
if (BKE_image_is_stereo(ima) && ima->views_format == R_IMF_VIEWS_STEREO_3D) {
@@ -4653,10 +4722,6 @@ static ImBuf *image_load_sequence_file(Image *ima, ImageUser *iuser, int entry,
IMB_freeImBuf(ibuf_arr[i]);
}
}
-
- /* cleanup */
- MEM_freeN(ibuf_arr);
- MEM_freeN(cache_ibuf_arr);
}
return ibuf;
@@ -4664,12 +4729,12 @@ static ImBuf *image_load_sequence_file(Image *ima, ImageUser *iuser, int entry,
static ImBuf *image_load_sequence_multilayer(Image *ima, ImageUser *iuser, int entry, int frame)
{
- struct ImBuf *ibuf = NULL;
+ struct ImBuf *ibuf = nullptr;
/* either we load from RenderResult, or we have to load a new one */
/* check for new RenderResult */
- if (ima->rr == NULL || frame != ima->rr->framenr) {
+ if (ima->rr == nullptr || frame != ima->rr->framenr) {
if (ima->rr) {
/* Cached image buffers shares pointers with render result,
* need to ensure there's no image buffers are hanging around
@@ -4677,7 +4742,7 @@ static ImBuf *image_load_sequence_multilayer(Image *ima, ImageUser *iuser, int e
*/
image_free_cached_frames(ima);
RE_FreeRenderResult(ima->rr);
- ima->rr = NULL;
+ ima->rr = nullptr;
}
ibuf = image_load_sequence_file(ima, iuser, entry, frame);
@@ -4694,7 +4759,7 @@ static ImBuf *image_load_sequence_multilayer(Image *ima, ImageUser *iuser, int e
// printf("load from pass %s\n", rpass->name);
/* since we free render results, we copy the rect */
ibuf = IMB_allocImBuf(ima->rr->rectx, ima->rr->recty, 32, 0);
- ibuf->rect_float = MEM_dupallocN(rpass->rect);
+ ibuf->rect_float = static_cast<float *>(MEM_dupallocN(rpass->rect));
ibuf->flags |= IB_rectfloat;
ibuf->mall = IB_rectfloat;
ibuf->channels = rpass->channels;
@@ -4712,15 +4777,15 @@ static ImBuf *image_load_sequence_multilayer(Image *ima, ImageUser *iuser, int e
static ImBuf *load_movie_single(Image *ima, ImageUser *iuser, int frame, const int view_id)
{
- struct ImBuf *ibuf = NULL;
+ struct ImBuf *ibuf = nullptr;
ImageAnim *ia;
- ia = BLI_findlink(&ima->anims, view_id);
+ ia = static_cast<ImageAnim *>(BLI_findlink(&ima->anims, view_id));
- if (ia->anim == NULL) {
+ if (ia->anim == nullptr) {
char str[FILE_MAX];
int flags = IB_rect;
- ImageUser iuser_t;
+ ImageUser iuser_t{};
if (ima->flag & IMA_DEINTERLACE) {
flags |= IB_animdeinterlace;
@@ -4765,7 +4830,7 @@ static ImBuf *load_movie_single(Image *ima, ImageUser *iuser, int frame, const i
static ImBuf *image_load_movie_file(Image *ima, ImageUser *iuser, int frame)
{
- struct ImBuf *ibuf = NULL;
+ struct ImBuf *ibuf = nullptr;
const bool is_multiview = BKE_image_is_multiview(ima);
const int totfiles = image_num_files(ima);
@@ -4774,7 +4839,7 @@ static ImBuf *image_load_movie_file(Image *ima, ImageUser *iuser, int frame)
for (int i = 0; i < totfiles; i++) {
/* allocate the ImageAnim */
- ImageAnim *ia = MEM_callocN(sizeof(ImageAnim), "Image Anim");
+ ImageAnim *ia = MEM_cnew<ImageAnim>("Image Anim");
BLI_addtail(&ima->anims, ia);
}
}
@@ -4784,10 +4849,8 @@ static ImBuf *image_load_movie_file(Image *ima, ImageUser *iuser, int frame)
image_assign_ibuf(ima, ibuf, 0, frame);
}
else {
- struct ImBuf **ibuf_arr;
const int totviews = BLI_listbase_count(&ima->views);
-
- ibuf_arr = MEM_mallocN(sizeof(ImBuf *) * totviews, "Image Views (movie) Imbufs");
+ Array<ImBuf *> ibuf_arr(totviews);
for (int i = 0; i < totfiles; i++) {
ibuf_arr[i] = load_movie_single(ima, iuser, frame, i);
@@ -4810,9 +4873,6 @@ static ImBuf *image_load_movie_file(Image *ima, ImageUser *iuser, int frame)
IMB_freeImBuf(ibuf_arr[i]);
}
}
-
- /* cleanup */
- MEM_freeN(ibuf_arr);
}
return ibuf;
@@ -4826,7 +4886,7 @@ static ImBuf *load_image_single(Image *ima,
bool *r_cache_ibuf)
{
char filepath[FILE_MAX];
- struct ImBuf *ibuf = NULL;
+ struct ImBuf *ibuf = nullptr;
int flag;
*r_cache_ibuf = true;
@@ -4838,7 +4898,7 @@ static ImBuf *load_image_single(Image *ima,
flag = IB_rect | IB_multilayer;
flag |= imbuf_alpha_flags_for_image(ima);
- imapf = BLI_findlink(&ima->packedfiles, view_id);
+ imapf = static_cast<ImagePackedFile *>(BLI_findlink(&ima->packedfiles, view_id));
if (imapf->packedfile) {
ibuf = IMB_ibImageFromMemory((unsigned char *)imapf->packedfile->data,
imapf->packedfile->size,
@@ -4848,7 +4908,7 @@ static ImBuf *load_image_single(Image *ima,
}
}
else {
- ImageUser iuser_t;
+ ImageUser iuser_t{};
flag = IB_rect | IB_multilayer | IB_metadata;
flag |= imbuf_alpha_flags_for_image(ima);
@@ -4880,9 +4940,9 @@ static ImBuf *load_image_single(Image *ima,
image_create_multilayer(ima, ibuf, cfra);
ima->type = IMA_TYPE_MULTILAYER;
IMB_freeImBuf(ibuf);
- ibuf = NULL;
- /* NULL ibuf in the cache means the image failed to load. However for multilayer we load
- * pixels into RenderResult instead and intentionally leave ibuf NULL. */
+ ibuf = nullptr;
+ /* Null ibuf in the cache means the image failed to load. However for multilayer we load
+ * pixels into RenderResult instead and intentionally leave ibuf null. */
*r_cache_ibuf = false;
}
}
@@ -4893,12 +4953,13 @@ static ImBuf *load_image_single(Image *ima,
/* Make packed file for auto-pack. */
if ((has_packed == false) && (G.fileflags & G_FILE_AUTOPACK)) {
- ImagePackedFile *imapf = MEM_mallocN(sizeof(ImagePackedFile), "Image Pack-file");
+ ImagePackedFile *imapf = static_cast<ImagePackedFile *>(
+ MEM_mallocN(sizeof(ImagePackedFile), "Image Pack-file"));
BLI_addtail(&ima->packedfiles, imapf);
STRNCPY(imapf->filepath, filepath);
imapf->packedfile = BKE_packedfile_new(
- NULL, filepath, ID_BLEND_PATH_FROM_GLOBAL(&ima->id));
+ nullptr, filepath, ID_BLEND_PATH_FROM_GLOBAL(&ima->id));
}
}
}
@@ -4906,12 +4967,12 @@ static ImBuf *load_image_single(Image *ima,
return ibuf;
}
-/* warning, 'iuser' can be NULL
+/* warning, 'iuser' can be null
* NOTE: Image->views was already populated (in image_update_views_format)
*/
static ImBuf *image_load_image_file(Image *ima, ImageUser *iuser, int cfra)
{
- struct ImBuf *ibuf = NULL;
+ struct ImBuf *ibuf = nullptr;
const bool is_multiview = BKE_image_is_multiview(ima);
const int totfiles = image_num_files(ima);
bool has_packed = BKE_image_has_packedfile(ima);
@@ -4935,18 +4996,17 @@ static ImBuf *image_load_image_file(Image *ima, ImageUser *iuser, int cfra)
}
}
else {
- struct ImBuf **ibuf_arr;
const int totviews = BLI_listbase_count(&ima->views);
BLI_assert(totviews > 0);
- ibuf_arr = MEM_callocN(sizeof(ImBuf *) * totviews, "Image Views Imbufs");
- bool *cache_ibuf_arr = MEM_mallocN(sizeof(bool) * totviews, "Image Views Put In Cache");
+ Array<ImBuf *> ibuf_arr(totviews);
+ Array<bool> cache_ibuf_arr(totviews);
for (int i = 0; i < totfiles; i++) {
- ibuf_arr[i] = load_image_single(ima, iuser, cfra, i, has_packed, cache_ibuf_arr + i);
+ ibuf_arr[i] = load_image_single(ima, iuser, cfra, i, has_packed, &cache_ibuf_arr[i]);
}
- /* multi-views/multi-layers OpenEXR files directly populate ima, and return NULL ibuf... */
+ /* multi-views/multi-layers OpenEXR files directly populate ima, and return null ibuf... */
if (BKE_image_is_stereo(ima) && ima->views_format == R_IMF_VIEWS_STEREO_3D && ibuf_arr[0] &&
totfiles == 1 && totviews >= 2) {
IMB_ImBufFromStereo3d(ima->stereo3d_format, ibuf_arr[0], &ibuf_arr[0], &ibuf_arr[1]);
@@ -4968,10 +5028,6 @@ static ImBuf *image_load_image_file(Image *ima, ImageUser *iuser, int cfra)
IMB_freeImBuf(ibuf_arr[i]);
}
}
-
- /* cleanup */
- MEM_freeN(ibuf_arr);
- MEM_freeN(cache_ibuf_arr);
}
return ibuf;
@@ -4979,9 +5035,9 @@ static ImBuf *image_load_image_file(Image *ima, ImageUser *iuser, int cfra)
static ImBuf *image_get_ibuf_multilayer(Image *ima, ImageUser *iuser)
{
- ImBuf *ibuf = NULL;
+ ImBuf *ibuf = nullptr;
- if (ima->rr == NULL) {
+ if (ima->rr == nullptr) {
ibuf = image_load_image_file(ima, iuser, 0);
if (ibuf) { /* actually an error */
ima->type = IMA_TYPE_IMAGE;
@@ -5015,7 +5071,6 @@ static ImBuf *image_get_ibuf_multilayer(Image *ima, ImageUser *iuser)
static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser, void **r_lock)
{
Render *re;
- RenderResult rres;
RenderView *rv;
float *rectf, *rectz;
unsigned int *rect;
@@ -5026,12 +5081,12 @@ static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser, void **r_loc
int actview;
if (!(iuser && iuser->scene)) {
- return NULL;
+ return nullptr;
}
/* if we the caller is not going to release the lock, don't give the image */
if (!r_lock) {
- return NULL;
+ return nullptr;
}
re = RE_GetSceneRender(iuser->scene);
@@ -5045,40 +5100,62 @@ static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser, void **r_loc
actview = iuser->multiview_eye;
}
+ RenderResult rres{};
RenderSlot *slot;
if (from_render) {
RE_AcquireResultImage(re, &rres, actview);
}
else if ((slot = BKE_image_get_renderslot(ima, ima->render_slot))->render) {
- rres = *(slot->render);
- rres.have_combined = ((RenderView *)rres.views.first)->rectf != NULL;
- }
- else {
- memset(&rres, 0, sizeof(RenderResult));
+ /* Unfortunately each field needs to be set individually because RenderResult
+ * contains volatile fields and using memcpy would invoke undefined behavior with c++. */
+ rres.next = slot->render->next;
+ rres.prev = slot->render->prev;
+ rres.rectx = slot->render->rectx;
+ rres.recty = slot->render->recty;
+ rres.sample_nr = slot->render->sample_nr;
+ rres.rect32 = slot->render->rect32;
+ rres.rectf = slot->render->rectf;
+ rres.rectz = slot->render->rectz;
+ rres.tilerect = slot->render->tilerect;
+ rres.xof = slot->render->xof;
+ rres.yof = slot->render->yof;
+ rres.layers = slot->render->layers;
+ rres.views = slot->render->views;
+ rres.renrect.xmin = slot->render->renrect.xmin;
+ rres.renrect.xmax = slot->render->renrect.xmax;
+ rres.renrect.ymin = slot->render->renrect.ymin;
+ rres.renrect.ymax = slot->render->renrect.ymax;
+ rres.renlay = slot->render->renlay;
+ rres.framenr = slot->render->framenr;
+ rres.text = slot->render->text;
+ rres.error = slot->render->error;
+ rres.stamp_data = slot->render->stamp_data;
+ rres.passes_allocated = slot->render->passes_allocated;
+ rres.have_combined = ((RenderView *)rres.views.first)->rectf != nullptr;
}
if (!(rres.rectx > 0 && rres.recty > 0)) {
if (from_render) {
RE_ReleaseResultImage(re);
}
- return NULL;
+ return nullptr;
}
/* release is done in BKE_image_release_ibuf using r_lock */
if (from_render) {
BLI_thread_lock(LOCK_VIEWER);
*r_lock = re;
- rv = NULL;
+ rv = nullptr;
}
else {
- rv = BLI_findlink(&rres.views, actview);
- if (rv == NULL) {
- rv = rres.views.first;
+ rv = static_cast<RenderView *>(BLI_findlink(&rres.views, actview));
+ if (rv == nullptr) {
+ rv = static_cast<RenderView *>(rres.views.first);
}
}
/* this gives active layer, composite or sequence result */
- if (rv == NULL) {
+ if (rv == nullptr) {
rect = (unsigned int *)rres.rect32;
rectf = rres.rectf;
rectz = rres.rectz;
@@ -5101,12 +5178,13 @@ static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser, void **r_loc
* in this case we ignore float buffer, because it could have
* hung from previous pass which was float
*/
- rectf = NULL;
+ rectf = nullptr;
}
else if (rres.layers.first) {
- RenderLayer *rl = BLI_findlink(&rres.layers, layer - (rres.have_combined ? 1 : 0));
+ RenderLayer *rl = static_cast<RenderLayer *>(
+ BLI_findlink(&rres.layers, layer - (rres.have_combined ? 1 : 0)));
if (rl) {
- RenderPass *rpass = image_render_pass_get(rl, pass, actview, NULL);
+ RenderPass *rpass = image_render_pass_get(rl, pass, actview, nullptr);
if (rpass) {
rectf = rpass->rect;
if (pass != 0) {
@@ -5115,7 +5193,7 @@ static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser, void **r_loc
}
}
- for (rpass = rl->passes.first; rpass; rpass = rpass->next) {
+ for (rpass = static_cast<RenderPass *>(rl->passes.first); rpass; rpass = rpass->next) {
if (STREQ(rpass->name, RE_PASSNAME_Z) && rpass->view_id == actview) {
rectz = rpass->rect;
}
@@ -5123,10 +5201,10 @@ static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser, void **r_loc
}
}
- ibuf = image_get_cached_ibuf_for_index_entry(ima, IMA_NO_INDEX, 0, NULL);
+ ibuf = image_get_cached_ibuf_for_index_entry(ima, IMA_NO_INDEX, 0, nullptr);
/* make ibuf if needed, and initialize it */
- if (ibuf == NULL) {
+ if (ibuf == nullptr) {
ibuf = IMB_allocImBuf(rres.rectx, rres.recty, 32, 0);
image_assign_ibuf(ima, ibuf, IMA_NO_INDEX, 0);
}
@@ -5164,7 +5242,7 @@ static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser, void **r_loc
* or if it's reusing buffer from render result
*/
if ((ibuf->mall & IB_rect) == 0) {
- ibuf->rect = NULL;
+ ibuf->rect = nullptr;
}
}
@@ -5174,7 +5252,7 @@ static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser, void **r_loc
ibuf->channels = channels;
}
else {
- ibuf->rect_float = NULL;
+ ibuf->rect_float = nullptr;
ibuf->flags &= ~IB_rectfloat;
}
@@ -5183,16 +5261,16 @@ static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser, void **r_loc
ibuf->flags |= IB_zbuffloat;
}
else {
- ibuf->zbuf_float = NULL;
+ ibuf->zbuf_float = nullptr;
ibuf->flags &= ~IB_zbuffloat;
}
/* TODO(sergey): Make this faster by either simply referencing the stamp
* or by changing both ImBug and RenderResult to use same data type to
* store metadata. */
- if (ibuf->metadata != NULL) {
+ if (ibuf->metadata != nullptr) {
IMB_metadata_free(ibuf->metadata);
- ibuf->metadata = NULL;
+ ibuf->metadata = nullptr;
}
BKE_imbuf_stamp_info(&rres, ibuf);
@@ -5207,7 +5285,7 @@ static int image_get_multiview_index(Image *ima, ImageUser *iuser)
{
const bool is_multilayer = BKE_image_is_multilayer(ima);
const bool is_backdrop = (ima->source == IMA_SRC_VIEWER) && (ima->type == IMA_TYPE_COMPOSITE) &&
- (iuser == NULL);
+ (iuser == nullptr);
int index = BKE_image_has_multiple_ibufs(ima) ? 0 : IMA_NO_INDEX;
if (is_multilayer) {
@@ -5259,7 +5337,7 @@ static void image_get_entry_and_index(Image *ima, ImageUser *iuser, int *r_entry
static ImBuf *image_get_cached_ibuf(
Image *ima, ImageUser *iuser, int *r_entry, int *r_index, bool *r_is_cached_empty)
{
- ImBuf *ibuf = NULL;
+ ImBuf *ibuf = nullptr;
int entry = 0, index = image_get_multiview_index(ima, iuser);
/* see if we already have an appropriate ibuf, with image source and type */
@@ -5315,12 +5393,12 @@ static ImBuf *image_get_cached_ibuf(
BLI_INLINE bool image_quick_test(Image *ima, const ImageUser *iuser)
{
- if (ima == NULL) {
+ if (ima == nullptr) {
return false;
}
ImageTile *tile = BKE_image_get_tile_from_iuser(ima, iuser);
- if (tile == NULL) {
+ if (tile == nullptr) {
return false;
}
@@ -5334,49 +5412,49 @@ BLI_INLINE bool image_quick_test(Image *ima, const ImageUser *iuser)
*/
static ImBuf *image_acquire_ibuf(Image *ima, ImageUser *iuser, void **r_lock)
{
- ImBuf *ibuf = NULL;
+ ImBuf *ibuf = nullptr;
int entry = 0, index = 0;
if (r_lock) {
- *r_lock = NULL;
+ *r_lock = nullptr;
}
/* quick reject tests */
if (!image_quick_test(ima, iuser)) {
- return NULL;
+ return nullptr;
}
bool is_cached_empty = false;
ibuf = image_get_cached_ibuf(ima, iuser, &entry, &index, &is_cached_empty);
if (is_cached_empty) {
- return NULL;
+ return nullptr;
}
- if (ibuf == NULL) {
- /* we are sure we have to load the ibuf, using source and type */
+ if (ibuf == nullptr) {
+ /* We are sure we have to load the ibuf, using source and type. */
if (ima->source == IMA_SRC_MOVIE) {
- /* source is from single file, use flipbook to store ibuf */
+ /* Source is from single file, use flip-book to store ibuf. */
ibuf = image_load_movie_file(ima, iuser, entry);
}
else if (ima->source == IMA_SRC_SEQUENCE) {
if (ima->type == IMA_TYPE_IMAGE) {
- /* regular files, ibufs in flipbook, allows saving */
+ /* Regular files, ibufs in flip-book, allows saving. */
ibuf = image_load_sequence_file(ima, iuser, entry, entry);
}
/* no else; on load the ima type can change */
if (ima->type == IMA_TYPE_MULTILAYER) {
- /* only 1 layer/pass stored in imbufs, no exrhandle anim storage, no saving */
+ /* Only 1 layer/pass stored in imbufs, no EXR-handle anim storage, no saving. */
ibuf = image_load_sequence_multilayer(ima, iuser, entry, entry);
}
}
else if (ima->source == IMA_SRC_TILED) {
if (ima->type == IMA_TYPE_IMAGE) {
- /* regular files, ibufs in flipbook, allows saving */
+ /* Regular files, ibufs in flip-book, allows saving */
ibuf = image_load_sequence_file(ima, iuser, entry, 0);
}
/* no else; on load the ima type can change */
if (ima->type == IMA_TYPE_MULTILAYER) {
- /* only 1 layer/pass stored in imbufs, no exrhandle anim storage, no saving */
+ /* Only 1 layer/pass stored in imbufs, no EXR-handle anim storage, no saving. */
ibuf = image_load_sequence_multilayer(ima, iuser, entry, 0);
}
}
@@ -5392,8 +5470,8 @@ static ImBuf *image_acquire_ibuf(Image *ima, ImageUser *iuser, void **r_lock)
}
}
else if (ima->source == IMA_SRC_GENERATED) {
- /* generated is: ibuf is allocated dynamically */
- /* UV testgrid or black or solid etc */
+ /* Generated is: `ibuf` is allocated dynamically. */
+ /* UV test-grid or black or solid etc. */
if (ima->gen_x == 0) {
ima->gen_x = 1024;
}
@@ -5428,7 +5506,7 @@ static ImBuf *image_acquire_ibuf(Image *ima, ImageUser *iuser, void **r_lock)
/* XXX anim play for viewer nodes not yet supported */
entry = 0; // XXX iuser ? iuser->framenr : 0;
- ibuf = image_get_cached_ibuf_for_index_entry(ima, index, entry, NULL);
+ ibuf = image_get_cached_ibuf_for_index_entry(ima, index, entry, nullptr);
if (!ibuf) {
/* Composite Viewer, all handled in compositor */
@@ -5441,7 +5519,7 @@ static ImBuf *image_acquire_ibuf(Image *ima, ImageUser *iuser, void **r_lock)
}
/* We only want movies and sequences to be memory limited. */
- if (ibuf != NULL && !ELEM(ima->source, IMA_SRC_MOVIE, IMA_SRC_SEQUENCE)) {
+ if (ibuf != nullptr && !ELEM(ima->source, IMA_SRC_MOVIE, IMA_SRC_SEQUENCE)) {
ibuf->userflags |= IB_PERSISTENT;
}
}
@@ -5456,38 +5534,38 @@ ImBuf *BKE_image_acquire_ibuf(Image *ima, ImageUser *iuser, void **r_lock)
/* NOTE: same as #image_acquire_ibuf, but can be used to retrieve images being rendered in
* a thread safe way, always call both acquire and release. */
- if (ima == NULL) {
- return NULL;
+ if (ima == nullptr) {
+ return nullptr;
}
ImBuf *ibuf;
- BLI_mutex_lock(ima->runtime.cache_mutex);
+ BLI_mutex_lock(static_cast<ThreadMutex *>(ima->runtime.cache_mutex));
ibuf = image_acquire_ibuf(ima, iuser, r_lock);
- BLI_mutex_unlock(ima->runtime.cache_mutex);
+ BLI_mutex_unlock(static_cast<ThreadMutex *>(ima->runtime.cache_mutex));
return ibuf;
}
void BKE_image_release_ibuf(Image *ima, ImBuf *ibuf, void *lock)
{
- if (lock != NULL) {
+ if (lock != nullptr) {
/* for getting image during threaded render / compositing, need to release */
if (lock == ima) {
BLI_thread_unlock(LOCK_VIEWER); /* viewer image */
}
else {
- RE_ReleaseResultImage(lock); /* render result */
- BLI_thread_unlock(LOCK_VIEWER); /* view image imbuf */
+ RE_ReleaseResultImage(static_cast<Render *>(lock)); /* render result */
+ BLI_thread_unlock(LOCK_VIEWER); /* view image imbuf */
}
}
if (ibuf) {
- BLI_mutex_lock(ima->runtime.cache_mutex);
+ BLI_mutex_lock(static_cast<ThreadMutex *>(ima->runtime.cache_mutex));
IMB_freeImBuf(ibuf);
- BLI_mutex_unlock(ima->runtime.cache_mutex);
+ BLI_mutex_unlock(static_cast<ThreadMutex *>(ima->runtime.cache_mutex));
}
}
@@ -5500,40 +5578,44 @@ bool BKE_image_has_ibuf(Image *ima, ImageUser *iuser)
return false;
}
- BLI_mutex_lock(ima->runtime.cache_mutex);
+ BLI_mutex_lock(static_cast<ThreadMutex *>(ima->runtime.cache_mutex));
- ibuf = image_get_cached_ibuf(ima, iuser, NULL, NULL, NULL);
+ ibuf = image_get_cached_ibuf(ima, iuser, nullptr, nullptr, nullptr);
if (!ibuf) {
- ibuf = image_acquire_ibuf(ima, iuser, NULL);
+ ibuf = image_acquire_ibuf(ima, iuser, nullptr);
}
- BLI_mutex_unlock(ima->runtime.cache_mutex);
+ BLI_mutex_unlock(static_cast<ThreadMutex *>(ima->runtime.cache_mutex));
IMB_freeImBuf(ibuf);
- return ibuf != NULL;
+ return ibuf != nullptr;
}
-/* ******** Pool for image buffers ******** */
+/** \} */
-typedef struct ImagePoolItem {
+/* -------------------------------------------------------------------- */
+/** \name Pool for Image Buffers
+ * \{ */
+
+struct ImagePoolItem {
struct ImagePoolItem *next, *prev;
Image *image;
ImBuf *ibuf;
int index;
int entry;
-} ImagePoolItem;
+};
-typedef struct ImagePool {
+struct ImagePool {
ListBase image_buffers;
BLI_mempool *memory_pool;
ThreadMutex mutex;
-} ImagePool;
+};
ImagePool *BKE_image_pool_new(void)
{
- ImagePool *pool = MEM_callocN(sizeof(ImagePool), "Image Pool");
+ ImagePool *pool = MEM_cnew<ImagePool>("Image Pool");
pool->memory_pool = BLI_mempool_create(sizeof(ImagePoolItem), 0, 128, BLI_MEMPOOL_NOP);
BLI_mutex_init(&pool->mutex);
@@ -5545,11 +5627,13 @@ void BKE_image_pool_free(ImagePool *pool)
{
/* Use single lock to dereference all the image buffers. */
BLI_mutex_lock(&pool->mutex);
- for (ImagePoolItem *item = pool->image_buffers.first; item != NULL; item = item->next) {
- if (item->ibuf != NULL) {
- BLI_mutex_lock(item->image->runtime.cache_mutex);
+ for (ImagePoolItem *item = static_cast<ImagePoolItem *>(pool->image_buffers.first);
+ item != nullptr;
+ item = item->next) {
+ if (item->ibuf != nullptr) {
+ BLI_mutex_lock(static_cast<ThreadMutex *>(item->image->runtime.cache_mutex));
IMB_freeImBuf(item->ibuf);
- BLI_mutex_unlock(item->image->runtime.cache_mutex);
+ BLI_mutex_unlock(static_cast<ThreadMutex *>(item->image->runtime.cache_mutex));
}
}
BLI_mutex_unlock(&pool->mutex);
@@ -5568,14 +5652,14 @@ BLI_INLINE ImBuf *image_pool_find_item(
*found = false;
- for (item = pool->image_buffers.first; item; item = item->next) {
+ for (item = static_cast<ImagePoolItem *>(pool->image_buffers.first); item; item = item->next) {
if (item->image == image && item->entry == entry && item->index == index) {
*found = true;
return item->ibuf;
}
}
- return NULL;
+ return nullptr;
}
ImBuf *BKE_image_pool_acquire_ibuf(Image *ima, ImageUser *iuser, ImagePool *pool)
@@ -5585,12 +5669,12 @@ ImBuf *BKE_image_pool_acquire_ibuf(Image *ima, ImageUser *iuser, ImagePool *pool
bool found;
if (!image_quick_test(ima, iuser)) {
- return NULL;
+ return nullptr;
}
- if (pool == NULL) {
- /* Pool could be NULL, in this case use general acquire function. */
- return BKE_image_acquire_ibuf(ima, iuser, NULL);
+ if (pool == nullptr) {
+ /* Pool could be null, in this case use general acquire function. */
+ return BKE_image_acquire_ibuf(ima, iuser, nullptr);
}
image_get_entry_and_index(ima, iuser, &entry, &index);
@@ -5616,9 +5700,9 @@ ImBuf *BKE_image_pool_acquire_ibuf(Image *ima, ImageUser *iuser, ImagePool *pool
/* Thread-safe acquisition of an image buffer from the image.
* The acquisition does not use image pools, so there is no risk of recursive or out-of-order
* mutex locking. */
- ibuf = BKE_image_acquire_ibuf(ima, iuser, NULL);
+ ibuf = BKE_image_acquire_ibuf(ima, iuser, nullptr);
- item = BLI_mempool_alloc(pool->memory_pool);
+ item = static_cast<ImagePoolItem *>(BLI_mempool_alloc(pool->memory_pool));
item->image = ima;
item->entry = entry;
item->index = index;
@@ -5637,8 +5721,8 @@ void BKE_image_pool_release_ibuf(Image *ima, ImBuf *ibuf, ImagePool *pool)
/* if pool wasn't actually used, use general release stuff,
* for pools image buffers will be dereferenced on pool free
*/
- if (pool == NULL) {
- BKE_image_release_ibuf(ima, ibuf, NULL);
+ if (pool == nullptr) {
+ BKE_image_release_ibuf(ima, ibuf, nullptr);
}
}
@@ -5758,7 +5842,7 @@ void BKE_image_editors_update_frame(const Main *bmain, int cfra)
{
/* This only updates images used by the user interface. For others the
* dependency graph will call BKE_image_user_id_eval_animation. */
- wmWindowManager *wm = bmain->wm.first;
+ wmWindowManager *wm = static_cast<wmWindowManager *>(bmain->wm.first);
image_walk_id_all_users(&wm->id, false, &cfra, image_editors_update_frame);
}
@@ -5818,7 +5902,7 @@ void BKE_image_user_file_path(ImageUser *iuser, Image *ima, char *filepath)
void BKE_image_user_file_path_ex(ImageUser *iuser, Image *ima, char *filepath, bool resolve_udim)
{
if (BKE_image_is_multiview(ima)) {
- ImageView *iv = BLI_findlink(&ima->views, iuser->view);
+ ImageView *iv = static_cast<ImageView *>(BLI_findlink(&ima->views, iuser->view));
if (iv->filepath[0]) {
BLI_strncpy(filepath, iv->filepath, FILE_MAX);
}
@@ -5853,17 +5937,14 @@ void BKE_image_user_file_path_ex(ImageUser *iuser, Image *ima, char *filepath, b
BLI_path_abs(filepath, ID_BLEND_PATH_FROM_GLOBAL(&ima->id));
}
-bool BKE_image_has_alpha(struct Image *image)
+bool BKE_image_has_alpha(Image *image)
{
- ImBuf *ibuf;
void *lock;
- int planes;
-
- ibuf = BKE_image_acquire_ibuf(image, NULL, &lock);
- planes = (ibuf ? ibuf->planes : 0);
+ ImBuf *ibuf = BKE_image_acquire_ibuf(image, NULL, &lock);
+ const int planes = (ibuf ? ibuf->planes : 0);
BKE_image_release_ibuf(image, ibuf, lock);
- if (planes == 32) {
+ if (planes == 32 || planes == 16) {
return true;
}
@@ -5872,10 +5953,10 @@ bool BKE_image_has_alpha(struct Image *image)
void BKE_image_get_size(Image *image, ImageUser *iuser, int *r_width, int *r_height)
{
- ImBuf *ibuf = NULL;
+ ImBuf *ibuf = nullptr;
void *lock;
- if (image != NULL) {
+ if (image != nullptr) {
ibuf = BKE_image_acquire_ibuf(image, iuser, &lock);
}
@@ -5883,8 +5964,8 @@ void BKE_image_get_size(Image *image, ImageUser *iuser, int *r_width, int *r_hei
*r_width = ibuf->x;
*r_height = ibuf->y;
}
- else if (image != NULL && image->type == IMA_TYPE_R_RESULT && iuser != NULL &&
- iuser->scene != NULL) {
+ else if (image != nullptr && image->type == IMA_TYPE_R_RESULT && iuser != nullptr &&
+ iuser->scene != nullptr) {
Scene *scene = iuser->scene;
*r_width = (scene->r.xsch * scene->r.size) / 100;
*r_height = (scene->r.ysch * scene->r.size) / 100;
@@ -5898,7 +5979,7 @@ void BKE_image_get_size(Image *image, ImageUser *iuser, int *r_width, int *r_hei
*r_height = IMG_SIZE_FALLBACK;
}
- if (image != NULL) {
+ if (image != nullptr) {
BKE_image_release_ibuf(image, ibuf, lock);
}
}
@@ -5931,7 +6012,7 @@ unsigned char *BKE_image_get_pixels_for_frame(struct Image *image, int frame, in
BKE_imageuser_default(&iuser);
void *lock;
ImBuf *ibuf;
- unsigned char *pixels = NULL;
+ unsigned char *pixels = nullptr;
iuser.framenr = frame;
iuser.tile = tile;
@@ -5942,14 +6023,14 @@ unsigned char *BKE_image_get_pixels_for_frame(struct Image *image, int frame, in
pixels = (unsigned char *)ibuf->rect;
if (pixels) {
- pixels = MEM_dupallocN(pixels);
+ pixels = static_cast<unsigned char *>(MEM_dupallocN(pixels));
}
BKE_image_release_ibuf(image, ibuf, lock);
}
if (!pixels) {
- return NULL;
+ return nullptr;
}
return pixels;
@@ -5961,7 +6042,7 @@ float *BKE_image_get_float_pixels_for_frame(struct Image *image, int frame, int
BKE_imageuser_default(&iuser);
void *lock;
ImBuf *ibuf;
- float *pixels = NULL;
+ float *pixels = nullptr;
iuser.framenr = frame;
iuser.tile = tile;
@@ -5972,14 +6053,14 @@ float *BKE_image_get_float_pixels_for_frame(struct Image *image, int frame, int
pixels = ibuf->rect_float;
if (pixels) {
- pixels = MEM_dupallocN(pixels);
+ pixels = static_cast<float *>(MEM_dupallocN(pixels));
}
BKE_image_release_ibuf(image, ibuf, lock);
}
if (!pixels) {
- return NULL;
+ return nullptr;
}
return pixels;
@@ -5987,7 +6068,7 @@ float *BKE_image_get_float_pixels_for_frame(struct Image *image, int frame, int
int BKE_image_sequence_guess_offset(Image *image)
{
- return BLI_path_sequence_decode(image->filepath, NULL, NULL, NULL);
+ return BLI_path_sequence_decode(image->filepath, nullptr, nullptr, nullptr);
}
bool BKE_image_has_anim(Image *ima)
@@ -6022,13 +6103,13 @@ bool BKE_image_is_dirty_writable(Image *image, bool *r_is_writable)
bool is_dirty = false;
bool is_writable = false;
- BLI_mutex_lock(image->runtime.cache_mutex);
- if (image->cache != NULL) {
+ BLI_mutex_lock(static_cast<ThreadMutex *>(image->runtime.cache_mutex));
+ if (image->cache != nullptr) {
struct MovieCacheIter *iter = IMB_moviecacheIter_new(image->cache);
while (!IMB_moviecacheIter_done(iter)) {
ImBuf *ibuf = IMB_moviecacheIter_getImBuf(iter);
- if (ibuf != NULL && ibuf->userflags & IB_BITMAPDIRTY) {
+ if (ibuf != nullptr && ibuf->userflags & IB_BITMAPDIRTY) {
is_writable = BKE_image_buffer_format_writable(ibuf);
is_dirty = true;
break;
@@ -6037,7 +6118,7 @@ bool BKE_image_is_dirty_writable(Image *image, bool *r_is_writable)
}
IMB_moviecacheIter_free(iter);
}
- BLI_mutex_unlock(image->runtime.cache_mutex);
+ BLI_mutex_unlock(static_cast<ThreadMutex *>(image->runtime.cache_mutex));
if (r_is_writable) {
*r_is_writable = is_writable;
@@ -6048,7 +6129,7 @@ bool BKE_image_is_dirty_writable(Image *image, bool *r_is_writable)
bool BKE_image_is_dirty(Image *image)
{
- return BKE_image_is_dirty_writable(image, NULL);
+ return BKE_image_is_dirty_writable(image, nullptr);
}
void BKE_image_mark_dirty(Image *UNUSED(image), ImBuf *ibuf)
@@ -6066,34 +6147,34 @@ bool BKE_image_buffer_format_writable(ImBuf *ibuf)
void BKE_image_file_format_set(Image *image, int ftype, const ImbFormatOptions *options)
{
- BLI_mutex_lock(image->runtime.cache_mutex);
- if (image->cache != NULL) {
+ BLI_mutex_lock(static_cast<ThreadMutex *>(image->runtime.cache_mutex));
+ if (image->cache != nullptr) {
struct MovieCacheIter *iter = IMB_moviecacheIter_new(image->cache);
while (!IMB_moviecacheIter_done(iter)) {
ImBuf *ibuf = IMB_moviecacheIter_getImBuf(iter);
- if (ibuf != NULL) {
- ibuf->ftype = ftype;
+ if (ibuf != nullptr) {
+ ibuf->ftype = static_cast<eImbFileType>(ftype);
ibuf->foptions = *options;
}
IMB_moviecacheIter_step(iter);
}
IMB_moviecacheIter_free(iter);
}
- BLI_mutex_unlock(image->runtime.cache_mutex);
+ BLI_mutex_unlock(static_cast<ThreadMutex *>(image->runtime.cache_mutex));
}
bool BKE_image_has_loaded_ibuf(Image *image)
{
bool has_loaded_ibuf = false;
- BLI_mutex_lock(image->runtime.cache_mutex);
- if (image->cache != NULL) {
+ BLI_mutex_lock(static_cast<ThreadMutex *>(image->runtime.cache_mutex));
+ if (image->cache != nullptr) {
struct MovieCacheIter *iter = IMB_moviecacheIter_new(image->cache);
while (!IMB_moviecacheIter_done(iter)) {
ImBuf *ibuf = IMB_moviecacheIter_getImBuf(iter);
- if (ibuf != NULL) {
+ if (ibuf != nullptr) {
has_loaded_ibuf = true;
break;
}
@@ -6101,22 +6182,22 @@ bool BKE_image_has_loaded_ibuf(Image *image)
}
IMB_moviecacheIter_free(iter);
}
- BLI_mutex_unlock(image->runtime.cache_mutex);
+ BLI_mutex_unlock(static_cast<ThreadMutex *>(image->runtime.cache_mutex));
return has_loaded_ibuf;
}
ImBuf *BKE_image_get_ibuf_with_name(Image *image, const char *name)
{
- ImBuf *ibuf = NULL;
+ ImBuf *ibuf = nullptr;
- BLI_mutex_lock(image->runtime.cache_mutex);
- if (image->cache != NULL) {
+ BLI_mutex_lock(static_cast<ThreadMutex *>(image->runtime.cache_mutex));
+ if (image->cache != nullptr) {
struct MovieCacheIter *iter = IMB_moviecacheIter_new(image->cache);
while (!IMB_moviecacheIter_done(iter)) {
ImBuf *current_ibuf = IMB_moviecacheIter_getImBuf(iter);
- if (current_ibuf != NULL && STREQ(current_ibuf->name, name)) {
+ if (current_ibuf != nullptr && STREQ(current_ibuf->name, name)) {
ibuf = current_ibuf;
IMB_refImBuf(ibuf);
break;
@@ -6125,29 +6206,29 @@ ImBuf *BKE_image_get_ibuf_with_name(Image *image, const char *name)
}
IMB_moviecacheIter_free(iter);
}
- BLI_mutex_unlock(image->runtime.cache_mutex);
+ BLI_mutex_unlock(static_cast<ThreadMutex *>(image->runtime.cache_mutex));
return ibuf;
}
ImBuf *BKE_image_get_first_ibuf(Image *image)
{
- ImBuf *ibuf = NULL;
+ ImBuf *ibuf = nullptr;
- BLI_mutex_lock(image->runtime.cache_mutex);
- if (image->cache != NULL) {
+ BLI_mutex_lock(static_cast<ThreadMutex *>(image->runtime.cache_mutex));
+ if (image->cache != nullptr) {
struct MovieCacheIter *iter = IMB_moviecacheIter_new(image->cache);
while (!IMB_moviecacheIter_done(iter)) {
ibuf = IMB_moviecacheIter_getImBuf(iter);
- if (ibuf != NULL) {
+ if (ibuf != nullptr) {
IMB_refImBuf(ibuf);
}
break;
}
IMB_moviecacheIter_free(iter);
}
- BLI_mutex_unlock(image->runtime.cache_mutex);
+ BLI_mutex_unlock(static_cast<ThreadMutex *>(image->runtime.cache_mutex));
return ibuf;
}
@@ -6178,7 +6259,7 @@ static void image_update_views_format(Image *ima, ImageUser *iuser)
/* R_IMF_VIEWS_INDIVIDUAL */
char prefix[FILE_MAX] = {'\0'};
char *name = ima->filepath;
- const char *ext = NULL;
+ const char *ext = nullptr;
BKE_scene_multiview_view_prefix_get(scene, name, prefix, &ext);
@@ -6188,7 +6269,7 @@ static void image_update_views_format(Image *ima, ImageUser *iuser)
}
/* create all the image views */
- for (srv = scene->r.views.first; srv; srv = srv->next) {
+ for (srv = static_cast<SceneRenderView *>(scene->r.views.first); srv; srv = srv->next) {
if (BKE_scene_multiview_is_render_view_active(&scene->r, srv)) {
char filepath[FILE_MAX];
SNPRINTF(filepath, "%s%s%s", prefix, srv->suffix, ext);
@@ -6197,7 +6278,7 @@ static void image_update_views_format(Image *ima, ImageUser *iuser)
}
/* check if the files are all available */
- iv = ima->views.last;
+ iv = static_cast<ImageView *>(ima->views.last);
while (iv) {
int file;
char str[FILE_MAX];
@@ -6226,11 +6307,15 @@ static void image_update_views_format(Image *ima, ImageUser *iuser)
}
}
-/**************************** Render Slots ***************************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Render Slots
+ * \{ */
RenderSlot *BKE_image_add_renderslot(Image *ima, const char *name)
{
- RenderSlot *slot = MEM_callocN(sizeof(RenderSlot), "Image new Render Slot");
+ RenderSlot *slot = MEM_cnew<RenderSlot>("Image new Render Slot");
if (name && name[0]) {
BLI_strncpy(slot->name, name, sizeof(slot->name));
}
@@ -6242,9 +6327,9 @@ RenderSlot *BKE_image_add_renderslot(Image *ima, const char *name)
return slot;
}
-bool BKE_image_remove_renderslot(Image *ima, ImageUser *iuser, int index)
+bool BKE_image_remove_renderslot(Image *ima, ImageUser *iuser, int slot)
{
- if (index == ima->last_render_slot) {
+ if (slot == ima->last_render_slot) {
/* Don't remove render slot while rendering to it. */
if (G.is_rendering) {
return false;
@@ -6252,17 +6337,20 @@ bool BKE_image_remove_renderslot(Image *ima, ImageUser *iuser, int index)
}
int num_slots = BLI_listbase_count(&ima->renderslots);
- if (index >= num_slots || num_slots == 1) {
+ if (slot >= num_slots || num_slots == 1) {
return false;
}
- RenderSlot *remove_slot = BLI_findlink(&ima->renderslots, index);
- RenderSlot *current_slot = BLI_findlink(&ima->renderslots, ima->render_slot);
- RenderSlot *current_last_slot = BLI_findlink(&ima->renderslots, ima->last_render_slot);
+ RenderSlot *remove_slot = static_cast<RenderSlot *>(BLI_findlink(&ima->renderslots, slot));
+ RenderSlot *current_slot = static_cast<RenderSlot *>(
+ BLI_findlink(&ima->renderslots, ima->render_slot));
+ RenderSlot *current_last_slot = static_cast<RenderSlot *>(
+ BLI_findlink(&ima->renderslots, ima->last_render_slot));
RenderSlot *next_slot;
if (current_slot == remove_slot) {
- next_slot = BLI_findlink(&ima->renderslots, (index == num_slots - 1) ? index - 1 : index + 1);
+ next_slot = static_cast<RenderSlot *>(
+ BLI_findlink(&ima->renderslots, (slot == num_slots - 1) ? slot - 1 : slot + 1));
}
else {
next_slot = current_slot;
@@ -6308,9 +6396,9 @@ bool BKE_image_remove_renderslot(Image *ima, ImageUser *iuser, int index)
return true;
}
-bool BKE_image_clear_renderslot(Image *ima, ImageUser *iuser, int index)
+bool BKE_image_clear_renderslot(Image *ima, ImageUser *iuser, int slot)
{
- if (index == ima->last_render_slot) {
+ if (slot == ima->last_render_slot) {
if (!iuser) {
return false;
}
@@ -6325,19 +6413,21 @@ bool BKE_image_clear_renderslot(Image *ima, ImageUser *iuser, int index)
return true;
}
- RenderSlot *slot = BLI_findlink(&ima->renderslots, index);
+ RenderSlot *render_slot = static_cast<RenderSlot *>(BLI_findlink(&ima->renderslots, slot));
if (!slot) {
return false;
}
- if (slot->render) {
- RE_FreeRenderResult(slot->render);
- slot->render = NULL;
+ if (render_slot->render) {
+ RE_FreeRenderResult(render_slot->render);
+ render_slot->render = nullptr;
}
return true;
}
RenderSlot *BKE_image_get_renderslot(Image *ima, int index)
{
- /* Can be NULL for images without render slots. */
- return BLI_findlink(&ima->renderslots, index);
+ /* Can be null for images without render slots. */
+ return static_cast<RenderSlot *>(BLI_findlink(&ima->renderslots, index));
}
+
+/** \} */
diff --git a/source/blender/blenkernel/intern/image_gpu.cc b/source/blender/blenkernel/intern/image_gpu.cc
index c4a43d8b023..0d470c5b663 100644
--- a/source/blender/blenkernel/intern/image_gpu.cc
+++ b/source/blender/blenkernel/intern/image_gpu.cc
@@ -280,7 +280,7 @@ static GPUTexture **get_image_gpu_texture_ptr(Image *ima,
{
const bool in_range = (textarget >= 0) && (textarget < TEXTARGET_COUNT);
BLI_assert(in_range);
- BLI_assert(multiview_eye == 0 || multiview_eye == 1);
+ BLI_assert(ELEM(multiview_eye, 0, 1));
const int resolution = (texture_resolution == IMA_TEXTURE_RESOLUTION_LIMITED) ? 1 : 0;
if (in_range) {
diff --git a/source/blender/blenkernel/intern/key.c b/source/blender/blenkernel/intern/key.c
index e28094c0abc..bd6ffa2bc55 100644
--- a/source/blender/blenkernel/intern/key.c
+++ b/source/blender/blenkernel/intern/key.c
@@ -206,7 +206,7 @@ IDTypeInfo IDType_ID_KE = {
.foreach_id = shapekey_foreach_id,
.foreach_cache = NULL,
.foreach_path = NULL,
- /* A bit weird, due to shapekeys not being strictly speaking embedded data... But they also
+ /* A bit weird, due to shape-keys not being strictly speaking embedded data... But they also
* share a lot with those (non linkable, only ever used by one owner ID, etc.). */
.owner_get = shapekey_owner_get,
diff --git a/source/blender/blenkernel/intern/lib_id.c b/source/blender/blenkernel/intern/lib_id.c
index 7cd3204f3f1..28745f1d2c7 100644
--- a/source/blender/blenkernel/intern/lib_id.c
+++ b/source/blender/blenkernel/intern/lib_id.c
@@ -1875,7 +1875,7 @@ void BKE_library_make_local(Main *bmain,
for (int a = set_listbasepointers(bmain, lbarray); a--;) {
ID *id = lbarray[a]->first;
- /* Do not explicitly make local non-linkable IDs (shapekeys, in fact),
+ /* Do not explicitly make local non-linkable IDs (shape-keys, in fact),
* they are assumed to be handled by real data-blocks responsible of them. */
const bool do_skip = (id && !BKE_idtype_idcode_is_linkable(GS(id->name)));
@@ -1902,8 +1902,8 @@ void BKE_library_make_local(Main *bmain,
* to discover all your links are lost after appending).
* Also, never ever make proxified objects local, would not make any sense. */
/* Some more notes:
- * - Shapekeys are never tagged here (since they are not linkable).
- * - Nodetrees used in materials etc. have to be tagged manually,
+ * - Shape-keys are never tagged here (since they are not linkable).
+ * - Node-trees used in materials etc. have to be tagged manually,
* since they do not exist in Main (!).
* This is ok-ish on 'make local' side of things
* (since those are handled by their 'owner' IDs),
diff --git a/source/blender/blenkernel/intern/lib_override.c b/source/blender/blenkernel/intern/lib_override.c
index 922c1beda38..7f34ccfc36f 100644
--- a/source/blender/blenkernel/intern/lib_override.c
+++ b/source/blender/blenkernel/intern/lib_override.c
@@ -1063,7 +1063,7 @@ static void lib_override_library_create_post_process(Main *bmain,
break;
}
default:
- BLI_assert(0);
+ break;
}
}
if (default_instantiating_collection == NULL) {
@@ -2854,6 +2854,7 @@ bool BKE_lib_override_library_status_check_reference(Main *bmain, ID *local)
bool BKE_lib_override_library_operations_create(Main *bmain, ID *local)
{
+ BLI_assert(!ID_IS_LINKED(local));
BLI_assert(local->override_library != NULL);
const bool is_template = (local->override_library->reference == NULL);
bool created = false;
@@ -2978,6 +2979,12 @@ bool BKE_lib_override_library_main_operations_create(Main *bmain, const bool for
id->override_library, IDOVERRIDE_LIBRARY_TAG_UNUSED, false);
}
}
+ else {
+ /* Clear 'unused' tag for un-processed IDs, otherwise e.g. linked overrides will loose their
+ * list of overridden properties. */
+ BKE_lib_override_library_properties_tag(
+ id->override_library, IDOVERRIDE_LIBRARY_TAG_UNUSED, false);
+ }
id->tag &= ~LIB_TAG_OVERRIDE_LIBRARY_AUTOREFRESH;
}
FOREACH_MAIN_ID_END;
@@ -3413,7 +3420,7 @@ ID *BKE_lib_override_library_operations_store_start(Main *bmain,
{
if (ID_IS_OVERRIDE_LIBRARY_TEMPLATE(local) || ID_IS_OVERRIDE_LIBRARY_VIRTUAL(local)) {
/* This is actually purely local data with an override template, or one of those embedded IDs
- * (root node trees, master collections or shapekeys) that cannot have their own override.
+ * (root node trees, master collections or shape-keys) that cannot have their own override.
* Nothing to do here! */
return NULL;
}
diff --git a/source/blender/blenkernel/intern/linestyle.c b/source/blender/blenkernel/intern/linestyle.c
index e50d6263423..bbcc886f3ff 100644
--- a/source/blender/blenkernel/intern/linestyle.c
+++ b/source/blender/blenkernel/intern/linestyle.c
@@ -2035,7 +2035,7 @@ bool BKE_linestyle_use_textures(FreestyleLineStyle *linestyle, const bool use_sh
void BKE_linestyle_default_shader(const bContext *C, FreestyleLineStyle *linestyle)
{
- bNode *uv_along_stroke, *input_texure, *output_linestyle;
+ bNode *uv_along_stroke, *input_texture, *output_linestyle;
bNodeSocket *fromsock, *tosock;
bNodeTree *ntree;
@@ -2050,9 +2050,9 @@ void BKE_linestyle_default_shader(const bContext *C, FreestyleLineStyle *linesty
uv_along_stroke->locy = 300.0f;
uv_along_stroke->custom1 = 0; /* use_tips */
- input_texure = nodeAddStaticNode(C, ntree, SH_NODE_TEX_IMAGE);
- input_texure->locx = 200.0f;
- input_texure->locy = 300.0f;
+ input_texture = nodeAddStaticNode(C, ntree, SH_NODE_TEX_IMAGE);
+ input_texture->locx = 200.0f;
+ input_texture->locy = 300.0f;
output_linestyle = nodeAddStaticNode(C, ntree, SH_NODE_OUTPUT_LINESTYLE);
output_linestyle->locx = 400.0f;
@@ -2060,15 +2060,15 @@ void BKE_linestyle_default_shader(const bContext *C, FreestyleLineStyle *linesty
output_linestyle->custom1 = MA_RAMP_BLEND;
output_linestyle->custom2 = 0; /* use_clamp */
- nodeSetActive(ntree, input_texure);
+ nodeSetActive(ntree, input_texture);
fromsock = BLI_findlink(&uv_along_stroke->outputs, 0); /* UV */
- tosock = BLI_findlink(&input_texure->inputs, 0); /* UV */
- nodeAddLink(ntree, uv_along_stroke, fromsock, input_texure, tosock);
+ tosock = BLI_findlink(&input_texture->inputs, 0); /* UV */
+ nodeAddLink(ntree, uv_along_stroke, fromsock, input_texture, tosock);
- fromsock = BLI_findlink(&input_texure->outputs, 0); /* Color */
+ fromsock = BLI_findlink(&input_texture->outputs, 0); /* Color */
tosock = BLI_findlink(&output_linestyle->inputs, 0); /* Color */
- nodeAddLink(ntree, input_texure, fromsock, output_linestyle, tosock);
+ nodeAddLink(ntree, input_texture, fromsock, output_linestyle, tosock);
BKE_ntree_update_main_tree(CTX_data_main(C), ntree, NULL);
}
diff --git a/source/blender/blenkernel/intern/mask.c b/source/blender/blenkernel/intern/mask.c
index fca7c10ca77..42e65a95404 100644
--- a/source/blender/blenkernel/intern/mask.c
+++ b/source/blender/blenkernel/intern/mask.c
@@ -609,7 +609,7 @@ float BKE_mask_spline_project_co(MaskSpline *spline,
if (len_squared_v2(v1) > proj_eps_sq) {
ang1 = angle_v2v2(v1, n1);
- if (ang1 > (float)M_PI / 2.0f) {
+ if (ang1 > (float)M_PI_2) {
ang1 = (float)M_PI - ang1;
}
@@ -635,7 +635,7 @@ float BKE_mask_spline_project_co(MaskSpline *spline,
if (len_squared_v2(v2) > proj_eps_sq) {
ang2 = angle_v2v2(v2, n2);
- if (ang2 > (float)M_PI / 2.0f) {
+ if (ang2 > (float)M_PI_2) {
ang2 = (float)M_PI - ang2;
}
@@ -1374,7 +1374,7 @@ static void mask_calc_point_handle(MaskSplinePoint *point,
else if (handle_type == HD_AUTO) {
BKE_nurb_handle_calc(bezt, bezt_prev, bezt_next, 0, 0);
}
- else if (handle_type == HD_ALIGN || handle_type == HD_ALIGN_DOUBLESIDE) {
+ else if (ELEM(handle_type, HD_ALIGN, HD_ALIGN_DOUBLESIDE)) {
float v1[3], v2[3];
float vec[3], h[3];
diff --git a/source/blender/blenkernel/intern/mesh.cc b/source/blender/blenkernel/intern/mesh.cc
index 37564f9334f..824c1ab1b90 100644
--- a/source/blender/blenkernel/intern/mesh.cc
+++ b/source/blender/blenkernel/intern/mesh.cc
@@ -142,11 +142,11 @@ static void mesh_copy_data(Main *bmain, ID *id_dst, const ID *id_src, const int
mesh_dst->mselect = (MSelect *)MEM_dupallocN(mesh_dst->mselect);
- /* Set normal layers dirty, since they aren't included in CD_MASK_MESH and are therefore not
- * copied to the destination mesh. Alternatively normal layers could be copied if they aren't
- * dirty, avoiding recomputation in some cases. However, a copied mesh is often changed anyway,
- * so that idea is not clearly better. With proper reference counting, all custom data layers
- * could be copied as the cost would be much lower. */
+ /* Set normal layers dirty. They should be dirty by default on new meshes anyway, but being
+ * explicit about it is safer. Alternatively normal layers could be copied if they aren't dirty,
+ * avoiding recomputation in some cases. However, a copied mesh is often changed anyway, so that
+ * idea is not clearly better. With proper reference counting, all custom data layers could be
+ * copied as the cost would be much lower. */
BKE_mesh_normals_tag_dirty(mesh_dst);
/* TODO: Do we want to add flag to prevent this? */
@@ -510,7 +510,6 @@ static int customdata_compare(
return MESHCMP_VERTCOMISMATCH;
}
}
- /* I don't care about normals, let's just do coordinates. */
}
break;
}
diff --git a/source/blender/blenkernel/intern/movieclip.c b/source/blender/blenkernel/intern/movieclip.c
index a53714c8a98..c23110b4703 100644
--- a/source/blender/blenkernel/intern/movieclip.c
+++ b/source/blender/blenkernel/intern/movieclip.c
@@ -1609,8 +1609,10 @@ void BKE_movieclip_get_cache_segments(MovieClip *clip,
if (clip->cache) {
int proxy = rendersize_to_proxy(user, clip->flag);
+ BLI_thread_lock(LOCK_MOVIECLIP);
IMB_moviecache_get_cache_segments(
clip->cache->moviecache, proxy, user->render_flag, r_totseg, r_points);
+ BLI_thread_unlock(LOCK_MOVIECLIP);
}
}
diff --git a/source/blender/blenkernel/intern/node.cc b/source/blender/blenkernel/intern/node.cc
index 1c0eb0ecd44..29770ea5475 100644
--- a/source/blender/blenkernel/intern/node.cc
+++ b/source/blender/blenkernel/intern/node.cc
@@ -553,7 +553,7 @@ void ntreeBlendWrite(BlendWriter *writer, bNodeTree *ntree)
BKE_curvemapping_blend_write(writer, (const CurveMapping *)node->storage);
}
else if ((ntree->type == NTREE_TEXTURE) &&
- (node->type == TEX_NODE_CURVE_RGB || node->type == TEX_NODE_CURVE_TIME)) {
+ ELEM(node->type, TEX_NODE_CURVE_RGB, TEX_NODE_CURVE_TIME)) {
BKE_curvemapping_blend_write(writer, (const CurveMapping *)node->storage);
}
else if ((ntree->type == NTREE_COMPOSIT) && (node->type == CMP_NODE_MOVIEDISTORTION)) {
@@ -579,7 +579,7 @@ void ntreeBlendWrite(BlendWriter *writer, bNodeTree *ntree)
BLO_write_struct_by_name(writer, node->typeinfo->storagename, node->storage);
}
else if ((ntree->type == NTREE_COMPOSIT) &&
- (ELEM(node->type, CMP_NODE_CRYPTOMATTE, CMP_NODE_CRYPTOMATTE_LEGACY))) {
+ ELEM(node->type, CMP_NODE_CRYPTOMATTE, CMP_NODE_CRYPTOMATTE_LEGACY)) {
NodeCryptomatte *nc = (NodeCryptomatte *)node->storage;
BLO_write_string(writer, nc->matte_id);
LISTBASE_FOREACH (CryptomatteEntry *, entry, &nc->entries) {
diff --git a/source/blender/blenkernel/intern/paint.c b/source/blender/blenkernel/intern/paint.c
index d42c8ea37d5..238cf1ad74e 100644
--- a/source/blender/blenkernel/intern/paint.c
+++ b/source/blender/blenkernel/intern/paint.c
@@ -551,6 +551,8 @@ ePaintMode BKE_paintmode_get_active_from_context(const bContext *C)
return PAINT_MODE_TEXTURE_3D;
case OB_MODE_EDIT:
return PAINT_MODE_SCULPT_UV;
+ case OB_MODE_SCULPT_CURVES:
+ return PAINT_MODE_SCULPT_CURVES;
default:
return PAINT_MODE_TEXTURE_2D;
}
diff --git a/source/blender/blenkernel/intern/particle_child.c b/source/blender/blenkernel/intern/particle_child.c
index 7a2e4eb4ac9..8106ae8b302 100644
--- a/source/blender/blenkernel/intern/particle_child.c
+++ b/source/blender/blenkernel/intern/particle_child.c
@@ -85,7 +85,7 @@ static void do_kink_spiral_deform(ParticleKey *state,
* and goes up to the Golden Spiral for 1.0
* https://en.wikipedia.org/wiki/Golden_spiral
*/
- const float b = shape * (1.0f + sqrtf(5.0f)) / (float)M_PI * 0.25f;
+ const float b = shape * (1.0f + sqrtf(5.0f)) / (float)M_PI_4;
/* angle of the spiral against the curve (rotated opposite to make a smooth transition) */
const float start_angle = ((b != 0.0f) ? atanf(1.0f / b) : (float)-M_PI_2) +
(b > 0.0f ? -(float)M_PI_2 : (float)M_PI_2);
diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c
index 859e3499cc4..19abff19b77 100644
--- a/source/blender/blenkernel/intern/pointcache.c
+++ b/source/blender/blenkernel/intern/pointcache.c
@@ -683,8 +683,7 @@ static int ptcache_dynamicpaint_write(PTCacheFile *pf, void *dp_v)
if (surface->type == MOD_DPAINT_SURFACE_T_PAINT) {
in_len = sizeof(PaintPoint) * total_points;
}
- else if (surface->type == MOD_DPAINT_SURFACE_T_DISPLACE ||
- surface->type == MOD_DPAINT_SURFACE_T_WEIGHT) {
+ else if (ELEM(surface->type, MOD_DPAINT_SURFACE_T_DISPLACE, MOD_DPAINT_SURFACE_T_WEIGHT)) {
in_len = sizeof(float) * total_points;
}
else if (surface->type == MOD_DPAINT_SURFACE_T_WAVE) {
diff --git a/source/blender/blenkernel/intern/screen.c b/source/blender/blenkernel/intern/screen.c
index b1b9a24ebaa..ebc87c6ccc0 100644
--- a/source/blender/blenkernel/intern/screen.c
+++ b/source/blender/blenkernel/intern/screen.c
@@ -58,7 +58,7 @@ static void screen_free_data(ID *id)
{
bScreen *screen = (bScreen *)id;
- /* No animdata here. */
+ /* No animation-data here. */
LISTBASE_FOREACH (ARegion *, region, &screen->regionbase) {
BKE_area_region_free(NULL, region);
diff --git a/source/blender/blenkernel/intern/sound.c b/source/blender/blenkernel/intern/sound.c
index fd9735ff07f..b991805fae8 100644
--- a/source/blender/blenkernel/intern/sound.c
+++ b/source/blender/blenkernel/intern/sound.c
@@ -87,7 +87,7 @@ static void sound_free_data(ID *id)
{
bSound *sound = (bSound *)id;
- /* No animdata here. */
+ /* No animation-data here. */
if (sound->packedfile) {
BKE_packedfile_free(sound->packedfile);
@@ -727,16 +727,11 @@ void *BKE_sound_add_scene_sound(
}
sound_verify_evaluated_id(&sequence->sound->id);
const double fps = FPS;
- void *handle = AUD_Sequence_add(scene->sound_scene,
- sequence->sound->playback_handle,
- startframe / fps,
- endframe / fps,
- frameskip / fps + sequence->sound->offset_time);
- AUD_SequenceEntry_setMuted(handle, (sequence->flag & SEQ_MUTE) != 0);
- AUD_SequenceEntry_setAnimationData(handle, AUD_AP_VOLUME, CFRA, &sequence->volume, 0);
- AUD_SequenceEntry_setAnimationData(handle, AUD_AP_PITCH, CFRA, &sequence->pitch, 0);
- AUD_SequenceEntry_setAnimationData(handle, AUD_AP_PANNING, CFRA, &sequence->pan, 0);
- return handle;
+ return AUD_Sequence_add(scene->sound_scene,
+ sequence->sound->playback_handle,
+ startframe / fps,
+ endframe / fps,
+ frameskip / fps + sequence->sound->offset_time);
}
void *BKE_sound_add_scene_sound_defaults(Scene *scene, Sequence *sequence)
diff --git a/source/blender/blenkernel/intern/spline_bezier.cc b/source/blender/blenkernel/intern/spline_bezier.cc
index 3c2ac1dae9c..e9ae51b16f8 100644
--- a/source/blender/blenkernel/intern/spline_bezier.cc
+++ b/source/blender/blenkernel/intern/spline_bezier.cc
@@ -365,7 +365,7 @@ BezierSpline::InsertResult BezierSpline::calculate_segment_insertion(const int i
using namespace blender::math;
BLI_assert(parameter <= 1.0f && parameter >= 0.0f);
- BLI_assert(next_index == 0 || next_index == index + 1);
+ BLI_assert(ELEM(next_index, 0, index + 1));
const float3 &point_prev = positions_[index];
const float3 &handle_prev = handle_positions_right_[index];
const float3 &handle_next = handle_positions_left_[next_index];
diff --git a/source/blender/blenkernel/intern/spline_nurbs.cc b/source/blender/blenkernel/intern/spline_nurbs.cc
index c2479e9e595..7dc5ac3ea12 100644
--- a/source/blender/blenkernel/intern/spline_nurbs.cc
+++ b/source/blender/blenkernel/intern/spline_nurbs.cc
@@ -142,15 +142,11 @@ bool NURBSpline::check_valid_size_and_order() const
return false;
}
- if (!is_cyclic_ && this->knots_mode == KnotsMode::Bezier) {
- if (order_ == 4) {
- if (this->size() < 5) {
- return false;
- }
- }
- else if (order_ != 3) {
+ if (ELEM(this->knots_mode, NURBS_KNOT_MODE_BEZIER, NURBS_KNOT_MODE_ENDPOINT_BEZIER)) {
+ if (this->knots_mode == NURBS_KNOT_MODE_BEZIER && this->size() <= order_) {
return false;
}
+ return (!is_cyclic_ || this->size() % (order_ - 1) == 0);
}
return true;
@@ -166,12 +162,13 @@ void NURBSpline::calculate_knots() const
{
const KnotsMode mode = this->knots_mode;
const int order = order_;
- const bool is_bezier = mode == NURBSpline::KnotsMode::Bezier;
- const bool is_end_point = mode == NURBSpline::KnotsMode::EndPoint;
+ const bool is_bezier = ELEM(mode, NURBS_KNOT_MODE_BEZIER, NURBS_KNOT_MODE_ENDPOINT_BEZIER);
+ const bool is_end_point = ELEM(mode, NURBS_KNOT_MODE_ENDPOINT, NURBS_KNOT_MODE_ENDPOINT_BEZIER);
/* Inner knots are always repeated once except on Bezier case. */
const int repeat_inner = is_bezier ? order - 1 : 1;
/* How many times to repeat 0.0 at the beginning of knot. */
- const int head = is_end_point && !is_cyclic_ ? order : (is_bezier ? order / 2 : 1);
+ const int head = is_end_point ? (order - (is_cyclic_ ? 1 : 0)) :
+ (is_bezier ? min_ii(2, repeat_inner) : 1);
/* Number of knots replicating widths of the starting knots.
* Covers both Cyclic and EndPoint cases. */
const int tail = is_cyclic_ ? 2 * order - 1 : (is_end_point ? order : 0);
@@ -182,7 +179,13 @@ void NURBSpline::calculate_knots() const
int r = head;
float current = 0.0f;
- for (const int i : IndexRange(knots.size() - tail)) {
+ const int offset = is_end_point && is_cyclic_ ? 1 : 0;
+ if (offset) {
+ knots[0] = current;
+ current += 1.0f;
+ }
+
+ for (const int i : IndexRange(offset, knots.size() - offset - tail)) {
knots[i] = current;
r--;
if (r == 0) {
@@ -219,17 +222,17 @@ Span<float> NURBSpline::knots() const
static void calculate_basis_for_point(const float parameter,
const int size,
- const int order,
+ const int degree,
Span<float> knots,
MutableSpan<float> basis_buffer,
NURBSpline::BasisCache &basis_cache)
{
/* Clamp parameter due to floating point inaccuracy. */
- const float t = std::clamp(parameter, knots[0], knots[size + order - 1]);
+ const float t = std::clamp(parameter, knots[0], knots[size + degree]);
int start = 0;
int end = 0;
- for (const int i : IndexRange(size + order - 1)) {
+ for (const int i : IndexRange(size + degree)) {
const bool knots_equal = knots[i] == knots[i + 1];
if (knots_equal || t < knots[i] || t > knots[i + 1]) {
basis_buffer[i] = 0.0f;
@@ -237,16 +240,16 @@ static void calculate_basis_for_point(const float parameter,
}
basis_buffer[i] = 1.0f;
- start = std::max(i - order - 1, 0);
+ start = std::max(i - degree, 0);
end = i;
- basis_buffer.slice(i + 1, size + order - 1 - i).fill(0.0f);
+ basis_buffer.slice(i + 1, size + degree - i).fill(0.0f);
break;
}
- basis_buffer[size + order - 1] = 0.0f;
+ basis_buffer[size + degree] = 0.0f;
- for (const int i_order : IndexRange(2, order - 1)) {
- if (end + i_order >= size + order) {
- end = size + order - 1 - i_order;
+ for (const int i_order : IndexRange(2, degree)) {
+ if (end + i_order >= size + degree + 1) {
+ end = size + degree - i_order;
}
for (const int i : IndexRange(start, end - start + 1)) {
float new_basis = 0.0f;
@@ -296,6 +299,7 @@ Span<NURBSpline::BasisCache> NURBSpline::calculate_basis_cache() const
basis_cache_.resize(eval_size);
const int order = this->order();
+ const int degree = order - 1;
Span<float> control_weights = this->weights();
Span<float> knots = this->knots();
@@ -305,14 +309,14 @@ Span<NURBSpline::BasisCache> NURBSpline::calculate_basis_cache() const
* Theoretically it could be optimized away in the future. */
Array<float> basis_buffer(this->knots_size());
- const float start = knots[order - 1];
- const float end = is_cyclic_ ? knots[size + order - 1] : knots[size];
+ const float start = knots[degree];
+ const float end = is_cyclic_ ? knots[size + degree] : knots[size];
const float step = (end - start) / this->evaluated_edges_size();
float parameter = start;
for (const int i : IndexRange(eval_size)) {
BasisCache &basis = basis_cache[i];
calculate_basis_for_point(
- parameter, size + (is_cyclic_ ? order - 1 : 0), order, knots, basis_buffer, basis);
+ parameter, size + (is_cyclic_ ? degree : 0), degree, knots, basis_buffer, basis);
BLI_assert(basis.weights.size() <= order);
for (const int j : basis.weights.index_range()) {
diff --git a/source/blender/blenkernel/intern/text.c b/source/blender/blenkernel/intern/text.c
index 5d0e515040d..486449c3f86 100644
--- a/source/blender/blenkernel/intern/text.c
+++ b/source/blender/blenkernel/intern/text.c
@@ -1436,78 +1436,20 @@ void txt_from_buf_for_undo(Text *text, const char *buf, int buf_len)
char *txt_to_buf(Text *text, int *r_buf_strlen)
{
- int length;
- TextLine *tmp, *linef, *linel;
- int charf, charl;
- char *buf;
-
- if (r_buf_strlen) {
- *r_buf_strlen = 0;
- }
-
- if (!text->curl) {
- return NULL;
- }
- if (!text->sell) {
- return NULL;
- }
- if (!text->lines.first) {
- return NULL;
- }
-
- linef = text->lines.first;
- charf = 0;
-
- linel = text->lines.last;
- charl = linel->len;
-
- if (linef == text->lines.last) {
- length = charl - charf;
-
- buf = MEM_mallocN(length + 2, "text buffer");
-
- BLI_strncpy(buf, linef->line + charf, length + 1);
- buf[length] = 0;
- }
- else {
- length = linef->len - charf;
- length += charl;
- length += 2; /* For the 2 '\n' */
-
- tmp = linef->next;
- while (tmp && tmp != linel) {
- length += tmp->len + 1;
- tmp = tmp->next;
- }
-
- buf = MEM_mallocN(length + 1, "cut buffer");
-
- strncpy(buf, linef->line + charf, linef->len - charf);
- length = linef->len - charf;
-
- buf[length++] = '\n';
-
- tmp = linef->next;
- while (tmp && tmp != linel) {
- strncpy(buf + length, tmp->line, tmp->len);
- length += tmp->len;
-
- buf[length++] = '\n';
-
- tmp = tmp->next;
- }
- strncpy(buf + length, linel->line, charl);
- length += charl;
-
- /* python compiler wants an empty end line */
- buf[length++] = '\n';
- buf[length] = 0;
+ /* Identical to #txt_to_buf_for_undo except that the string is nil terminated. */
+ int buf_len = 0;
+ LISTBASE_FOREACH (const TextLine *, l, &text->lines) {
+ buf_len += l->len + 1;
}
-
- if (r_buf_strlen) {
- *r_buf_strlen = length;
+ char *buf = MEM_mallocN(buf_len + 1, __func__);
+ char *buf_step = buf;
+ LISTBASE_FOREACH (const TextLine *, l, &text->lines) {
+ memcpy(buf_step, l->line, l->len);
+ buf_step += l->len;
+ *buf_step++ = '\n';
}
-
+ *buf_step = '\0';
+ *r_buf_strlen = buf_len;
return buf;
}
diff --git a/source/blender/blenkernel/intern/tracking.c b/source/blender/blenkernel/intern/tracking.c
index 5708d3eeaec..2a415b8f6fb 100644
--- a/source/blender/blenkernel/intern/tracking.c
+++ b/source/blender/blenkernel/intern/tracking.c
@@ -1473,7 +1473,7 @@ static const MovieTrackingMarker *get_usable_marker_for_interpolation(
const MovieTrackingMarker *anchor_marker,
const int direction)
{
- BLI_assert(direction == -1 || direction == 1);
+ BLI_assert(ELEM(direction, -1, 1));
const MovieTrackingMarker *last_marker = track->markers + track->markersnr - 1;
const MovieTrackingMarker *current_marker = anchor_marker;
diff --git a/source/blender/blenkernel/intern/writeffmpeg.c b/source/blender/blenkernel/intern/writeffmpeg.c
index b9d013d4756..5e11cd0703a 100644
--- a/source/blender/blenkernel/intern/writeffmpeg.c
+++ b/source/blender/blenkernel/intern/writeffmpeg.c
@@ -622,8 +622,7 @@ static AVStream *alloc_video_stream(FFMpegContext *context,
if (codec_id == AV_CODEC_ID_VP9 && rd->im_format.planes == R_IMF_PLANES_RGBA) {
c->pix_fmt = AV_PIX_FMT_YUVA420P;
}
- else if ((codec_id == AV_CODEC_ID_H264 || codec_id == AV_CODEC_ID_VP9) &&
- context->ffmpeg_crf == 0) {
+ else if (ELEM(codec_id, AV_CODEC_ID_H264, AV_CODEC_ID_VP9) && (context->ffmpeg_crf == 0)) {
/* Use 4:4:4 instead of 4:2:0 pixel format for lossless rendering. */
c->pix_fmt = AV_PIX_FMT_YUV444P;
}
diff --git a/source/blender/blenlib/BLI_fileops.h b/source/blender/blenlib/BLI_fileops.h
index 6f8b479dddd..04b40904187 100644
--- a/source/blender/blenlib/BLI_fileops.h
+++ b/source/blender/blenlib/BLI_fileops.h
@@ -149,10 +149,10 @@ eFileAttributes BLI_file_attributes(const char *path);
* \{ */
/**
- * Scans the contents of the directory named *dirname, and allocates and fills in an
- * array of entries describing them in *filelist.
+ * Scans the contents of the directory named `dir`, and allocates and fills in an
+ * array of entries describing them in `r_filelist`.
*
- * \return The length of filelist array.
+ * \return The length of `r_filelist` array.
*/
unsigned int BLI_filelist_dir_contents(const char *dir, struct direntry **r_filelist);
/**
diff --git a/source/blender/blenlib/BLI_memiter.h b/source/blender/blenlib/BLI_memiter.h
index 727092706c4..bf54b0ea14d 100644
--- a/source/blender/blenlib/BLI_memiter.h
+++ b/source/blender/blenlib/BLI_memiter.h
@@ -34,11 +34,12 @@ BLI_memiter *BLI_memiter_create(unsigned int chunk_size_min)
ATTR_MALLOC ATTR_WARN_UNUSED_RESULT ATTR_RETURNS_NONNULL;
void *BLI_memiter_alloc(BLI_memiter *mi, unsigned int size)
/* WARNING: `ATTR_MALLOC` attribute on #BLI_memiter_alloc causes crash, see: D2756. */
- ATTR_RETURNS_NONNULL ATTR_WARN_UNUSED_RESULT ATTR_RETURNS_NONNULL ATTR_NONNULL(1);
+ ATTR_WARN_UNUSED_RESULT ATTR_RETURNS_NONNULL ATTR_NONNULL(1);
void BLI_memiter_alloc_from(BLI_memiter *mi, uint elem_size, const void *data_from)
ATTR_NONNULL(1, 3);
-void *BLI_memiter_calloc(BLI_memiter *mi, unsigned int size)
- ATTR_RETURNS_NONNULL ATTR_WARN_UNUSED_RESULT ATTR_RETURNS_NONNULL ATTR_NONNULL(1);
+void *BLI_memiter_calloc(BLI_memiter *mi,
+ unsigned int size) ATTR_WARN_UNUSED_RESULT ATTR_RETURNS_NONNULL
+ ATTR_NONNULL(1);
void BLI_memiter_destroy(BLI_memiter *mi) ATTR_NONNULL(1);
void BLI_memiter_clear(BLI_memiter *mi) ATTR_NONNULL(1);
unsigned int BLI_memiter_count(const BLI_memiter *mi) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1);
diff --git a/source/blender/blenlib/intern/math_base_inline.c b/source/blender/blenlib/intern/math_base_inline.c
index 90a91cbe26f..bb6bc0db00d 100644
--- a/source/blender/blenlib/intern/math_base_inline.c
+++ b/source/blender/blenlib/intern/math_base_inline.c
@@ -95,10 +95,10 @@ MINLINE float saacos(float fac)
MINLINE float saasin(float fac)
{
if (UNLIKELY(fac <= -1.0f)) {
- return (float)-M_PI / 2.0f;
+ return (float)-M_PI_2;
}
else if (UNLIKELY(fac >= 1.0f)) {
- return (float)M_PI / 2.0f;
+ return (float)M_PI_2;
}
else {
return asinf(fac);
@@ -131,10 +131,10 @@ MINLINE float saacosf(float fac)
MINLINE float saasinf(float fac)
{
if (UNLIKELY(fac <= -1.0f)) {
- return (float)-M_PI / 2.0f;
+ return (float)-M_PI_2;
}
else if (UNLIKELY(fac >= 1.0f)) {
- return (float)M_PI / 2.0f;
+ return (float)M_PI_2;
}
else {
return asinf(fac);
diff --git a/source/blender/blenlib/intern/math_vector.c b/source/blender/blenlib/intern/math_vector.c
index e71b1150d8f..da6a6dff16f 100644
--- a/source/blender/blenlib/intern/math_vector.c
+++ b/source/blender/blenlib/intern/math_vector.c
@@ -289,7 +289,7 @@ void mid_v3_v3v3_angle_weighted(float r[3], const float a[3], const float b[3])
BLI_ASSERT_UNIT_V3(b);
add_v3_v3v3(r, a, b);
- angle = ((float)(1.0 / (M_PI / 2.0)) *
+ angle = ((float)M_2_PI *
/* normally we would only multiply by 2,
* but instead of an angle make this 0-1 factor */
2.0f) *
@@ -305,7 +305,7 @@ void mid_v3_angle_weighted(float r[3])
/* double check they are normalized */
BLI_assert(len_squared_v3(r) <= 1.0f + FLT_EPSILON);
- angle = ((float)(1.0 / (M_PI / 2.0)) *
+ angle = ((float)M_2_PI *
/* normally we would only multiply by 2,
* but instead of an angle make this 0-1 factor */
2.0f) *
diff --git a/source/blender/blenlib/intern/path_util.c b/source/blender/blenlib/intern/path_util.c
index 69ba9f7fb7b..f94d49cf1dd 100644
--- a/source/blender/blenlib/intern/path_util.c
+++ b/source/blender/blenlib/intern/path_util.c
@@ -470,7 +470,7 @@ void BLI_path_rel(char *file, const char *relfile)
* can happen with old recent-files.txt files */
BLI_windows_get_default_root_dir(temp);
ptemp = &temp[2];
- if (relfile[0] != '\\' && relfile[0] != '/') {
+ if (!ELEM(relfile[0], '\\', '/')) {
ptemp++;
}
BLI_strncpy(ptemp, relfile, FILE_MAX - 3);
@@ -629,7 +629,7 @@ bool BLI_path_parent_dir(char *path)
BLI_path_normalize(NULL, tmp); /* does all the work of normalizing the path for us */
if (!BLI_path_extension_check(tmp, parent_dir)) {
- strcpy(path, tmp); /* We assume pardir is always shorter... */
+ strcpy(path, tmp); /* We assume the parent directory is always shorter. */
return true;
}
diff --git a/source/blender/blenlib/tests/BLI_task_test.cc b/source/blender/blenlib/tests/BLI_task_test.cc
index 6a12ff10415..52852873a06 100644
--- a/source/blender/blenlib/tests/BLI_task_test.cc
+++ b/source/blender/blenlib/tests/BLI_task_test.cc
@@ -91,7 +91,7 @@ TEST(task, MempoolIter)
int i;
- /* 'Randomly' add and remove some items from mempool, to create a non-homogenous one. */
+ /* 'Randomly' add and remove some items from mempool, to create a non-homogeneous one. */
int num_items = 0;
for (i = 0; i < NUM_ITEMS; i++) {
data[i] = (int *)BLI_mempool_alloc(mempool);
diff --git a/source/blender/blenloader/BLO_read_write.h b/source/blender/blenloader/BLO_read_write.h
index 8f0f9fae97f..536c3989aff 100644
--- a/source/blender/blenloader/BLO_read_write.h
+++ b/source/blender/blenloader/BLO_read_write.h
@@ -286,8 +286,8 @@ void BLO_expand_id(BlendExpander *expander, struct ID *id);
* This function ensures that reports are printed,
* in the case of library linking errors this is important!
*
- * bit kludge but better than doubling up on prints,
- * we could alternatively have a versions of a report function which forces printing - campbell
+ * NOTE(@campbellbarton) a kludge but better than doubling up on prints,
+ * we could alternatively have a versions of a report function which forces printing.
*/
void BLO_reportf_wrap(struct BlendFileReadReport *reports,
eReportType type,
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index 9539436cf69..4ea6287399c 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -161,14 +161,14 @@
* which keeps large arrays in memory from data-blocks we may not even use.
*
* \note This is disabled when using compression,
- * while zlib supports seek it's unusably slow, see: T61880.
+ * while ZLIB supports seek it's unusably slow, see: T61880.
*/
#define USE_BHEAD_READ_ON_DEMAND
-/* use GHash for BHead name-based lookups (speeds up linking) */
+/** Use #GHash for #BHead name-based lookups (speeds up linking). */
#define USE_GHASH_BHEAD
-/* Use GHash for restoring pointers by name */
+/** Use #GHash for restoring pointers by name. */
#define USE_GHASH_RESTORE_POINTER
static CLG_LogRef LOG = {"blo.readfile"};
@@ -194,8 +194,10 @@ typedef struct BHeadN {
#define BHEADN_FROM_BHEAD(bh) ((BHeadN *)POINTER_OFFSET(bh, -(int)offsetof(BHeadN, bhead)))
-/* We could change this in the future, for now it's simplest if only data is delayed
- * because ID names are used in lookup tables. */
+/**
+ * We could change this in the future, for now it's simplest if only data is delayed
+ * because ID names are used in lookup tables.
+ */
#define BHEAD_USE_READ_ON_DEMAND(bhead) ((bhead)->code == DATA)
void BLO_reportf_wrap(BlendFileReadReport *reports, eReportType type, const char *format, ...)
@@ -4711,9 +4713,9 @@ static void read_library_linked_ids(FileData *basefd,
read_library_linked_id(basefd, fd, mainvar, id, realid);
}
- /* realid shall never be NULL - unless some source file/lib is broken
+ /* `realid` shall never be NULL - unless some source file/lib is broken
* (known case: some directly linked shapekey from a missing lib...). */
- /* BLI_assert(*realid != NULL); */
+ // BLI_assert(*realid != NULL);
/* Now that we have a real ID, replace all pointers to placeholders in
* fd->libmap with pointers to the real data-blocks. We do this for all
diff --git a/source/blender/blenloader/intern/versioning_260.c b/source/blender/blenloader/intern/versioning_260.c
index 28b934843af..655dc297c35 100644
--- a/source/blender/blenloader/intern/versioning_260.c
+++ b/source/blender/blenloader/intern/versioning_260.c
@@ -1838,7 +1838,7 @@ void blo_do_versions_260(FileData *fd, Library *UNUSED(lib), Main *bmain)
Image *image = blo_do_versions_newlibadr(fd, tex->id.lib, tex->ima);
if (image && (image->flag & IMA_DO_PREMUL) == 0) {
- const int IMA_IGNORE_ALPHA = (1 << 12);
+ enum { IMA_IGNORE_ALPHA = (1 << 12) };
image->flag |= IMA_IGNORE_ALPHA;
}
}
diff --git a/source/blender/blenloader/intern/versioning_280.c b/source/blender/blenloader/intern/versioning_280.c
index 32dbabf2643..b1c982649d2 100644
--- a/source/blender/blenloader/intern/versioning_280.c
+++ b/source/blender/blenloader/intern/versioning_280.c
@@ -1550,7 +1550,7 @@ void do_versions_after_linking_280(Main *bmain, ReportList *UNUSED(reports))
if (!MAIN_VERSION_ATLEAST(bmain, 280, 69)) {
/* Unify DOF settings (EEVEE part only) */
- const int SCE_EEVEE_DOF_ENABLED = (1 << 7);
+ enum { SCE_EEVEE_DOF_ENABLED = (1 << 7) };
LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
if (STREQ(scene->r.engine, RE_engine_id_BLENDER_EEVEE)) {
if (scene->eevee.flag & SCE_EEVEE_DOF_ENABLED) {
@@ -2312,7 +2312,7 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain)
} \
} \
((void)0)
- const int SCE_EEVEE_DOF_ENABLED = (1 << 7);
+ enum { SCE_EEVEE_DOF_ENABLED = (1 << 7) };
IDProperty *props = IDP_GetPropertyFromGroup(scene->layer_properties,
RE_engine_id_BLENDER_EEVEE);
// EEVEE_GET_BOOL(props, volumetric_enable, SCE_EEVEE_VOLUMETRIC_ENABLED);
@@ -4032,7 +4032,7 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain)
if (!MAIN_VERSION_ATLEAST(bmain, 280, 70)) {
/* New image alpha modes. */
LISTBASE_FOREACH (Image *, image, &bmain->images) {
- const int IMA_IGNORE_ALPHA = (1 << 12);
+ enum { IMA_IGNORE_ALPHA = (1 << 12) };
if (image->flag & IMA_IGNORE_ALPHA) {
image->alpha_mode = IMA_ALPHA_IGNORE;
image->flag &= ~IMA_IGNORE_ALPHA;
@@ -4497,7 +4497,7 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain)
clmd->sim_parms->max_internal_tension = 15.0f;
clmd->sim_parms->internal_compression = 15.0f;
clmd->sim_parms->max_internal_compression = 15.0f;
- clmd->sim_parms->internal_spring_max_diversion = M_PI / 4.0f;
+ clmd->sim_parms->internal_spring_max_diversion = M_PI_4;
}
}
}
diff --git a/source/blender/blenloader/intern/versioning_290.c b/source/blender/blenloader/intern/versioning_290.c
index ada011f191d..3ae26dea767 100644
--- a/source/blender/blenloader/intern/versioning_290.c
+++ b/source/blender/blenloader/intern/versioning_290.c
@@ -701,8 +701,10 @@ static void panels_remove_x_closed_flag_recursive(Panel *panel)
static void do_versions_point_attributes(CustomData *pdata)
{
/* Change to generic named float/float3 attributes. */
- const int CD_LOCATION = 43;
- const int CD_RADIUS = 44;
+ enum {
+ CD_LOCATION = 43,
+ CD_RADIUS = 44,
+ };
for (int i = 0; i < pdata->totlayer; i++) {
CustomDataLayer *layer = &pdata->layers[i];
diff --git a/source/blender/blenloader/intern/versioning_300.c b/source/blender/blenloader/intern/versioning_300.c
index 2a840ea585a..accb3e521e1 100644
--- a/source/blender/blenloader/intern/versioning_300.c
+++ b/source/blender/blenloader/intern/versioning_300.c
@@ -42,6 +42,7 @@
#include "BKE_armature.h"
#include "BKE_asset.h"
#include "BKE_collection.h"
+#include "BKE_curve.h"
#include "BKE_deform.h"
#include "BKE_fcurve.h"
#include "BKE_fcurve_driver.h"
@@ -1481,6 +1482,10 @@ static void version_liboverride_rnacollections_insertion_animdata(ID *id)
/* NOLINTNEXTLINE: readability-function-size */
void blo_do_versions_300(FileData *fd, Library *UNUSED(lib), Main *bmain)
{
+ /* The #SCE_SNAP_SEQ flag has been removed in favor of the #SCE_SNAP which can be used for each
+ * snap_flag member individually. */
+ enum { SCE_SNAP_SEQ = (1 << 7) };
+
if (!MAIN_VERSION_ATLEAST(bmain, 300, 1)) {
/* Set default value for the new bisect_threshold parameter in the mirror modifier. */
if (!DNA_struct_elem_find(fd->filesdna, "MirrorModifierData", "float", "bisect_threshold")) {
@@ -2567,6 +2572,59 @@ void blo_do_versions_300(FileData *fd, Library *UNUSED(lib), Main *bmain)
}
}
+ if (!MAIN_VERSION_ATLEAST(bmain, 302, 6)) {
+ LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
+ ToolSettings *ts = scene->toolsettings;
+ if (ts->uv_relax_method == 0) {
+ ts->uv_relax_method = UV_SCULPT_TOOL_RELAX_LAPLACIAN;
+ }
+ }
+ LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
+ ToolSettings *tool_settings = scene->toolsettings;
+ tool_settings->snap_flag_seq = tool_settings->snap_flag & ~(SCE_SNAP | SCE_SNAP_SEQ);
+ if (tool_settings->snap_flag & SCE_SNAP_SEQ) {
+ tool_settings->snap_flag_seq |= SCE_SNAP;
+ tool_settings->snap_flag &= ~SCE_SNAP_SEQ;
+ }
+
+ tool_settings->snap_flag_node = tool_settings->snap_flag;
+ tool_settings->snap_uv_flag |= tool_settings->snap_flag & SCE_SNAP;
+ }
+
+ /* Alter NURBS knot mode flags to fit new modes. */
+ LISTBASE_FOREACH (Curve *, curve, &bmain->curves) {
+ LISTBASE_FOREACH (Nurb *, nurb, &curve->nurb) {
+ /* Previously other flags were ignored if CU_NURB_CYCLIC is set. */
+ if (nurb->flagu & CU_NURB_CYCLIC) {
+ nurb->flagu = CU_NURB_CYCLIC;
+ }
+ /* CU_NURB_BEZIER and CU_NURB_ENDPOINT were ignored if combined. */
+ else if (nurb->flagu & CU_NURB_BEZIER && nurb->flagu & CU_NURB_ENDPOINT) {
+ nurb->flagu &= ~(CU_NURB_BEZIER | CU_NURB_ENDPOINT);
+ BKE_nurb_knot_calc_u(nurb);
+ }
+ /* Bezier NURBS of order 3 were clamped to first control point. */
+ else if (nurb->orderu == 3 && (nurb->flagu & CU_NURB_BEZIER)) {
+ nurb->flagu |= CU_NURB_ENDPOINT;
+ }
+
+ /* Previously other flags were ignored if CU_NURB_CYCLIC is set. */
+ if (nurb->flagv & CU_NURB_CYCLIC) {
+ nurb->flagv = CU_NURB_CYCLIC;
+ }
+ /* CU_NURB_BEZIER and CU_NURB_ENDPOINT were ignored if used together. */
+ else if (nurb->flagv & CU_NURB_BEZIER && nurb->flagv & CU_NURB_ENDPOINT) {
+ nurb->flagv &= ~(CU_NURB_BEZIER | CU_NURB_ENDPOINT);
+ BKE_nurb_knot_calc_v(nurb);
+ }
+ /* Bezier NURBS of order 3 were clamped to first control point. */
+ else if (nurb->orderv == 3 && (nurb->flagv & CU_NURB_BEZIER)) {
+ nurb->flagv |= CU_NURB_ENDPOINT;
+ }
+ }
+ }
+ }
+
/**
* Versioning code until next subversion bump goes here.
*
diff --git a/source/blender/blenloader/intern/versioning_cycles.c b/source/blender/blenloader/intern/versioning_cycles.c
index c654972730f..e1ceed82ba7 100644
--- a/source/blender/blenloader/intern/versioning_cycles.c
+++ b/source/blender/blenloader/intern/versioning_cycles.c
@@ -330,7 +330,7 @@ static void image_node_colorspace(bNode *node)
return;
}
- const int SHD_COLORSPACE_NONE = 0;
+ enum { SHD_COLORSPACE_NONE = 0 };
Image *image = (Image *)node->id;
if (color_space == SHD_COLORSPACE_NONE) {
STRNCPY(image->colorspace_settings.name,
@@ -1362,10 +1362,12 @@ void blo_do_versions_cycles(FileData *UNUSED(fd), Library *UNUSED(lib), Main *bm
void do_versions_after_linking_cycles(Main *bmain)
{
- const int DENOISER_AUTO = 0;
- const int DENOISER_NLM = 1;
- const int DENOISER_OPTIX = 2;
- const int DENOISER_OPENIMAGEDENOISE = 4;
+ enum {
+ DENOISER_AUTO = 0,
+ DENOISER_NLM = 1,
+ DENOISER_OPTIX = 2,
+ DENOISER_OPENIMAGEDENOISE = 4,
+ };
if (!MAIN_VERSION_ATLEAST(bmain, 280, 66)) {
/* Shader node tree changes. After lib linking so we have all the typeinfo
diff --git a/source/blender/blenloader/intern/versioning_legacy.c b/source/blender/blenloader/intern/versioning_legacy.c
index 2908b2b151b..5b026c1cca0 100644
--- a/source/blender/blenloader/intern/versioning_legacy.c
+++ b/source/blender/blenloader/intern/versioning_legacy.c
@@ -1075,11 +1075,10 @@ void blo_do_versions_pre250(FileData *fd, Library *lib, Main *bmain)
}
}
- /* ton: made this 230 instead of 229,
- * to be sure (tuho files) and this is a reliable check anyway
+ /* NOTE(@ton): made this 230 instead of 229,
+ * to be sure (files from the `tuhopuu` branch) and this is a reliable check anyway
* nevertheless, we might need to think over a fitness (initialize)
- * check apart from the do_versions()
- */
+ * check apart from the do_versions(). */
if (bmain->versionfile <= 230) {
bScreen *screen;
diff --git a/source/blender/bmesh/intern/bmesh_mesh_convert.cc b/source/blender/bmesh/intern/bmesh_mesh_convert.cc
index f581e2967c0..fd14a3416e2 100644
--- a/source/blender/bmesh/intern/bmesh_mesh_convert.cc
+++ b/source/blender/bmesh/intern/bmesh_mesh_convert.cc
@@ -607,7 +607,7 @@ static BMVert **bm_to_mesh_vertex_map(BMesh *bm, int ototvert)
*
* WARNING: There is an exception to the rule of ignoring coordinates in the destination:
* that is when shape-key data in `bm` can't be found (which is itself an error/exception).
- * In this case our own rule is violated as the alternative is loosing the shape-data entirely.
+ * In this case our own rule is violated as the alternative is losing the shape-data entirely.
*
* Flushing Coordinates Back to the #BMesh
* ---------------------------------------
@@ -677,8 +677,16 @@ static int bm_to_mesh_shape_layer_index_from_kb(BMesh *bm, KeyBlock *currkey)
* \param bm: The source BMesh.
* \param key: The destination key.
* \param mvert: The destination vertex array (in some situations it's coordinates are updated).
+ * \param active_shapekey_to_mvert: When editing a non-basis shape key, the coordinates for the
+ * basis are typically copied into the `mvert` array since it makes sense for the meshes
+ * vertex coordinates to match the "Basis" key.
+ * When enabled, skip this step and copy #BMVert.co directly to #MVert.co,
+ * See #BMeshToMeshParams.active_shapekey_to_mvert doc-string.
*/
-static void bm_to_mesh_shape(BMesh *bm, Key *key, MVert *mvert)
+static void bm_to_mesh_shape(BMesh *bm,
+ Key *key,
+ MVert *mvert,
+ const bool active_shapekey_to_mvert)
{
KeyBlock *actkey = static_cast<KeyBlock *>(BLI_findlink(&key->block, bm->shapenr - 1));
@@ -762,12 +770,14 @@ static void bm_to_mesh_shape(BMesh *bm, Key *key, MVert *mvert)
* In this case it's important to overwrite these coordinates with the basis-keys coordinates. */
bool update_vertex_coords_from_refkey = false;
int cd_shape_offset_refkey = -1;
- if ((actkey != key->refkey) && (cd_shape_keyindex_offset != -1)) {
- const int refkey_uuid = bm_to_mesh_shape_layer_index_from_kb(bm, key->refkey);
- if (refkey_uuid != -1) {
- cd_shape_offset_refkey = CustomData_get_n_offset(&bm->vdata, CD_SHAPEKEY, refkey_uuid);
- if (cd_shape_offset_refkey != -1) {
- update_vertex_coords_from_refkey = true;
+ if (active_shapekey_to_mvert == false) {
+ if ((actkey != key->refkey) && (cd_shape_keyindex_offset != -1)) {
+ const int refkey_uuid = bm_to_mesh_shape_layer_index_from_kb(bm, key->refkey);
+ if (refkey_uuid != -1) {
+ cd_shape_offset_refkey = CustomData_get_n_offset(&bm->vdata, CD_SHAPEKEY, refkey_uuid);
+ if (cd_shape_offset_refkey != -1) {
+ update_vertex_coords_from_refkey = true;
+ }
}
}
}
@@ -1137,7 +1147,7 @@ void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMesh
}
if (me->key) {
- bm_to_mesh_shape(bm, me->key, me->mvert);
+ bm_to_mesh_shape(bm, me->key, me->mvert, params->active_shapekey_to_mvert);
}
/* Run this even when shape keys aren't used since it may be used for hooks or vertex parents. */
diff --git a/source/blender/bmesh/intern/bmesh_mesh_convert.h b/source/blender/bmesh/intern/bmesh_mesh_convert.h
index 8e87fc86b6d..0bd70749cb1 100644
--- a/source/blender/bmesh/intern/bmesh_mesh_convert.h
+++ b/source/blender/bmesh/intern/bmesh_mesh_convert.h
@@ -53,6 +53,11 @@ struct BMeshToMeshParams {
* that have become invalid from updating the shape-key, see T71865.
*/
uint update_shapekey_indices : 1;
+ /**
+ * Instead of copying the basis shape-key into the #MVert array,
+ * copy the #BMVert.co directly to #MVert.co (used for reading undo data).
+ */
+ uint active_shapekey_to_mvert : 1;
struct CustomData_MeshMasks cd_mask_extra;
};
/**
diff --git a/source/blender/bmesh/operators/bmo_fill_edgeloop.c b/source/blender/bmesh/operators/bmo_fill_edgeloop.c
index 352b9336a20..86d204ea6a7 100644
--- a/source/blender/bmesh/operators/bmo_fill_edgeloop.c
+++ b/source/blender/bmesh/operators/bmo_fill_edgeloop.c
@@ -3,7 +3,7 @@
/** \file
* \ingroup bmesh
*
- * Fill discreet edge loop(s) with faces.
+ * Fill discrete edge loop(s) with faces.
*/
#include "MEM_guardedalloc.h"
diff --git a/source/blender/bmesh/tools/bmesh_bevel.c b/source/blender/bmesh/tools/bmesh_bevel.c
index 10bdc2c7294..5790d76936f 100644
--- a/source/blender/bmesh/tools/bmesh_bevel.c
+++ b/source/blender/bmesh/tools/bmesh_bevel.c
@@ -1859,7 +1859,7 @@ static void move_weld_profile_planes(BevVert *bv, BoundVert *bndv1, BoundVert *b
float l1 = normalize_v3(no);
/* "no" is new normal projection plane, but don't move if it is coplanar with both of the
- * projection dirs. */
+ * projection directions. */
float no2[3], no3[3];
cross_v3_v3v3(no2, d1, bndv1->profile.proj_dir);
float l2 = normalize_v3(no2);
@@ -5571,7 +5571,7 @@ static void bevel_build_cutoff(BevelParams *bp, BMesh *bm, BevVert *bv)
/* Add verts from each cutoff face. */
face_bmverts[i] = mesh_vert(bv->vmesh, i, 1, 0)->v;
}
- /* BLI_array_append(bmfaces, repface); */
+ // BLI_array_append(bmfaces, repface);
bev_create_ngon(bm, face_bmverts, n_bndv, bmfaces, NULL, bmedges, bp->mat_nr, true);
BLI_array_free(bmedges);
@@ -7106,7 +7106,7 @@ static void find_even_superellipse_chords(int n, float r, double *xvals, double
return;
}
if (r == PRO_CIRCLE_R) {
- double temp = (M_PI / 2) / n;
+ double temp = M_PI_2 / n;
/* Angle spacing. */
for (int i = 0; i <= n; i++) {
xvals[i] = sin(i * temp);
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc
index 77597e0db06..49e850b1979 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc
@@ -1408,7 +1408,7 @@ void DepsgraphNodeBuilder::build_particle_settings(ParticleSettings *particle_se
}
}
-/* Shapekeys */
+/* Shape-keys. */
void DepsgraphNodeBuilder::build_shapekeys(Key *key)
{
if (built_map_.checkIsBuiltAndTag(key)) {
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc
index faad053e30c..68c644cc422 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc
@@ -1598,6 +1598,14 @@ void DepsgraphRelationBuilder::build_driver_data(ID *id, FCurve *fcu)
add_relation(property_exit_key, parameters_key, "Driven Property -> Properties");
}
}
+
+ /* Assume drivers on a node tree affect the evaluated output of the node tree. In theory we could
+ * check if the driven value actually affects the output, i.e. if it drives a node that is linked
+ * to the output. */
+ if (GS(id_ptr->name) == ID_NT) {
+ ComponentKey ntree_output_key(id_ptr, NodeType::NTREE_OUTPUT);
+ add_relation(driver_key, ntree_output_key, "Drivers -> NTree Output");
+ }
}
void DepsgraphRelationBuilder::build_driver_variables(ID *id, FCurve *fcu)
diff --git a/source/blender/depsgraph/intern/depsgraph_tag.cc b/source/blender/depsgraph/intern/depsgraph_tag.cc
index b8c85430f06..f945e9b6fbc 100644
--- a/source/blender/depsgraph/intern/depsgraph_tag.cc
+++ b/source/blender/depsgraph/intern/depsgraph_tag.cc
@@ -483,7 +483,7 @@ void deg_graph_node_tag_zero(Main *bmain,
if (comp_node->type == NodeType::ANIMATION) {
continue;
}
- else if (comp_node->type == NodeType::COPY_ON_WRITE) {
+ if (comp_node->type == NodeType::COPY_ON_WRITE) {
id_node->is_cow_explicitly_tagged = true;
}
@@ -865,7 +865,7 @@ void DEG_ids_clear_recalc(Depsgraph *depsgraph, const bool backup)
if (!DEG_id_type_any_updated(depsgraph)) {
return;
}
- /* Go over all ID nodes nodes, clearing tags. */
+ /* Go over all ID nodes, clearing tags. */
for (deg::IDNode *id_node : deg_graph->id_nodes) {
if (backup) {
id_node->id_cow_recalc_backup |= id_node->id_cow->recalc;
diff --git a/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc b/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc
index 6346bab1fe8..19022d534b2 100644
--- a/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc
+++ b/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc
@@ -41,6 +41,7 @@
#include "DNA_ID.h"
#include "DNA_anim_types.h"
#include "DNA_armature_types.h"
+#include "DNA_gpencil_types.h"
#include "DNA_mesh_types.h"
#include "DNA_modifier_types.h"
#include "DNA_object_types.h"
@@ -733,6 +734,16 @@ void update_id_after_copy(const Depsgraph *depsgraph,
scene_setup_view_layers_after_remap(depsgraph, id_node, reinterpret_cast<Scene *>(id_cow));
break;
}
+ /* FIXME: This is a temporary fix to update the runtime pointers properly, see T96216. Should
+ * be removed at some point. */
+ case ID_GD: {
+ bGPdata *gpd_cow = (bGPdata *)id_cow;
+ bGPDlayer *gpl = (bGPDlayer *)(gpd_cow->layers.first);
+ if (gpl != nullptr && gpl->runtime.gpl_orig == nullptr) {
+ BKE_gpencil_data_update_orig_pointers((bGPdata *)id_orig, gpd_cow);
+ }
+ break;
+ }
default:
break;
}
diff --git a/source/blender/draw/engines/eevee/eevee_depth_of_field.c b/source/blender/draw/engines/eevee/eevee_depth_of_field.c
index ef4d88bd521..0d14a0c5f61 100644
--- a/source/blender/draw/engines/eevee/eevee_depth_of_field.c
+++ b/source/blender/draw/engines/eevee/eevee_depth_of_field.c
@@ -62,7 +62,7 @@ static float circle_to_polygon_radius(float sides_count, float theta)
cosf(theta - side_angle * floorf((sides_count * theta + M_PI) / (2.0f * M_PI)));
}
-/* Remap input angle to have homogenous spacing of points along a polygon edge.
+/* Remap input angle to have homogeneous spacing of points along a polygon edge.
* Expect theta to be in [0..2pi] range. */
static float circle_to_polygon_angle(float sides_count, float theta)
{
diff --git a/source/blender/draw/engines/eevee/eevee_lightprobes.c b/source/blender/draw/engines/eevee/eevee_lightprobes.c
index a20fe156eda..7029d015b22 100644
--- a/source/blender/draw/engines/eevee/eevee_lightprobes.c
+++ b/source/blender/draw/engines/eevee/eevee_lightprobes.c
@@ -613,7 +613,7 @@ void EEVEE_lightprobes_planar_data_from_object(Object *ob,
eplanar->clip_edge_y_neg = dot_v3v3(eplanar->clip_vec_y, vec);
/* Facing factors */
- float max_angle = max_ff(1e-2f, 1.0f - probe->falloff) * M_PI * 0.5f;
+ float max_angle = max_ff(1e-2f, 1.0f - probe->falloff) * M_PI_2;
float min_angle = 0.0f;
eplanar->facing_scale = 1.0f / max_ff(1e-8f, cosf(min_angle) - cosf(max_angle));
eplanar->facing_bias = -min_ff(1.0f - 1e-8f, cosf(max_angle)) * eplanar->facing_scale;
diff --git a/source/blender/draw/engines/eevee/eevee_lookdev.c b/source/blender/draw/engines/eevee/eevee_lookdev.c
index 0ef78d97a79..874c2815b8b 100644
--- a/source/blender/draw/engines/eevee/eevee_lookdev.c
+++ b/source/blender/draw/engines/eevee/eevee_lookdev.c
@@ -217,7 +217,7 @@ void EEVEE_lookdev_cache_init(EEVEE_Data *vedata,
float x_rot_matrix[3][3];
DRW_view_viewmat_get(NULL, view_matrix, false);
copy_m3_m4(view_rot_matrix, view_matrix);
- axis_angle_to_mat3_single(x_rot_matrix, 'X', M_PI / 2.0f);
+ axis_angle_to_mat3_single(x_rot_matrix, 'X', M_PI_2);
mul_m3_m3m3(view_rot_matrix, x_rot_matrix, view_rot_matrix);
mul_m3_m3m3(view_rot_matrix, g_data->studiolight_matrix, view_rot_matrix);
copy_m3_m3(studiolight_matrix, view_rot_matrix);
diff --git a/source/blender/draw/engines/eevee/shaders/effect_dof_bokeh_frag.glsl b/source/blender/draw/engines/eevee/shaders/effect_dof_bokeh_frag.glsl
index 051a08d25e6..d724b4d4609 100644
--- a/source/blender/draw/engines/eevee/shaders/effect_dof_bokeh_frag.glsl
+++ b/source/blender/draw/engines/eevee/shaders/effect_dof_bokeh_frag.glsl
@@ -35,7 +35,7 @@ float circle_to_polygon_radius(float sides_count, float theta)
cos(theta - side_angle * floor((sides_count * theta + M_PI) / M_2PI));
}
-/* Remap input angle to have homogenous spacing of points along a polygon edge.
+/* Remap input angle to have homogeneous spacing of points along a polygon edge.
* Expect theta to be in [0..2pi] range. */
float circle_to_polygon_angle(float sides_count, float theta)
{
diff --git a/source/blender/draw/engines/eevee/shaders/effect_dof_gather_frag.glsl b/source/blender/draw/engines/eevee/shaders/effect_dof_gather_frag.glsl
index f5c45d147e6..fe1ab395a54 100644
--- a/source/blender/draw/engines/eevee/shaders/effect_dof_gather_frag.glsl
+++ b/source/blender/draw/engines/eevee/shaders/effect_dof_gather_frag.glsl
@@ -12,7 +12,7 @@
#pragma BLENDER_REQUIRE(common_utiltex_lib.glsl)
#pragma BLENDER_REQUIRE(effect_dof_lib.glsl)
-/* Mipmapped input buffers, halfres but with padding to ensure mipmap alignement. */
+/* Mipmapped input buffers, halfres but with padding to ensure mipmap alignment. */
uniform sampler2D colorBuffer;
uniform sampler2D cocBuffer;
diff --git a/source/blender/draw/engines/eevee/shaders/effect_dof_scatter_vert.glsl b/source/blender/draw/engines/eevee/shaders/effect_dof_scatter_vert.glsl
index 59564890d7e..b05223e755d 100644
--- a/source/blender/draw/engines/eevee/shaders/effect_dof_scatter_vert.glsl
+++ b/source/blender/draw/engines/eevee/shaders/effect_dof_scatter_vert.glsl
@@ -103,7 +103,7 @@ void main()
color4 = colors[3] * weights[3];
/* Extend to cover at least the unit circle */
- const float extend = (cos(M_PI / 4.0) + 1.0) * 2.0;
+ const float extend = (cos(M_PI_4) + 1.0) * 2.0;
/* Crappy diagram
* ex 1
* | \
diff --git a/source/blender/draw/engines/eevee/shaders/effect_minmaxz_frag.glsl b/source/blender/draw/engines/eevee/shaders/effect_minmaxz_frag.glsl
index 8ef39a55921..ce455123987 100644
--- a/source/blender/draw/engines/eevee/shaders/effect_minmaxz_frag.glsl
+++ b/source/blender/draw/engines/eevee/shaders/effect_minmaxz_frag.glsl
@@ -4,7 +4,7 @@
* Adapted from http://rastergrid.com/blog/2010/10/hierarchical-z-map-based-occlusion-culling/
*
* Major simplification has been made since we pad the buffer to always be bigger than input to
- * avoid mipmapping misalignement.
+ * avoid mipmapping misalignment.
*/
#ifdef LAYERED
diff --git a/source/blender/draw/engines/eevee/shaders/effect_translucency_frag.glsl b/source/blender/draw/engines/eevee/shaders/effect_translucency_frag.glsl
index ba90f5ae531..831ed0a119a 100644
--- a/source/blender/draw/engines/eevee/shaders/effect_translucency_frag.glsl
+++ b/source/blender/draw/engines/eevee/shaders/effect_translucency_frag.glsl
@@ -40,7 +40,7 @@ float light_translucent_power_with_falloff(LightData ld, vec3 N, vec4 l_vector)
if (ld.l_type >= AREA_RECT) {
power = (ld.l_sizex * ld.l_sizey * 4.0 * M_PI) * (1.0 / 80.0);
if (ld.l_type == AREA_ELLIPSE) {
- power *= M_PI * 0.25;
+ power *= M_PI_4;
}
power *= 0.3 * 20.0 *
max(0.0, dot(-ld.l_forward, l_vector.xyz / l_vector.w)); /* XXX ad hoc, empirical */
diff --git a/source/blender/draw/engines/eevee/shaders/lookdev_world_frag.glsl b/source/blender/draw/engines/eevee/shaders/lookdev_world_frag.glsl
index 9077b414026..7ab532ea0fb 100644
--- a/source/blender/draw/engines/eevee/shaders/lookdev_world_frag.glsl
+++ b/source/blender/draw/engines/eevee/shaders/lookdev_world_frag.glsl
@@ -16,9 +16,9 @@ out vec4 FragColor;
vec3 background_transform_to_world(vec3 viewvec)
{
vec4 v = (ProjectionMatrix[3][3] == 0.0) ? vec4(viewvec, 1.0) : vec4(0.0, 0.0, 1.0, 1.0);
- vec4 co_homogenous = (ProjectionMatrixInverse * v);
+ vec4 co_homogeneous = (ProjectionMatrixInverse * v);
- vec4 co = vec4(co_homogenous.xyz / co_homogenous.w, 0.0);
+ vec4 co = vec4(co_homogeneous.xyz / co_homogeneous.w, 0.0);
return (ViewMatrixInverse * co).xyz;
}
diff --git a/source/blender/draw/engines/gpencil/gpencil_draw_data.c b/source/blender/draw/engines/gpencil/gpencil_draw_data.c
index 6c904745709..c3f96ecd0a2 100644
--- a/source/blender/draw/engines/gpencil/gpencil_draw_data.c
+++ b/source/blender/draw/engines/gpencil/gpencil_draw_data.c
@@ -387,7 +387,7 @@ void gpencil_light_pool_populate(GPENCIL_LightPool *lightpool, Object *ob)
normalize_m4_m4(mat, ob->obmat);
invert_m4(mat);
gp_light->type = GP_LIGHT_TYPE_SPOT;
- gp_light->spotsize = cosf(M_PI * 0.5f);
+ gp_light->spotsize = cosf(M_PI_2);
gp_light->spotblend = (1.0f - gp_light->spotsize) * 1.0f;
}
else if (la->type == LA_SUN) {
diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_common_lib.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_common_lib.glsl
index 36a52e05a4a..b4a26ec8103 100644
--- a/source/blender/draw/engines/gpencil/shaders/gpencil_common_lib.glsl
+++ b/source/blender/draw/engines/gpencil/shaders/gpencil_common_lib.glsl
@@ -442,7 +442,7 @@ void stroke_vertex()
if (is_dot) {
# ifdef GP_MATERIAL_BUFFER_LEN
int alignement = GP_FLAG(m) & GP_STROKE_ALIGNMENT;
- /* For one point strokes use object aligment. */
+ /* For one point strokes use object alignment. */
if (ma.x == -1 && ma2.x == -1 && alignement == GP_STROKE_ALIGNMENT_STROKE) {
alignement = GP_STROKE_ALIGNMENT_OBJECT;
}
diff --git a/source/blender/draw/engines/image/image_buffer_cache.hh b/source/blender/draw/engines/image/image_buffer_cache.hh
index ef11551c879..470e9f225b4 100644
--- a/source/blender/draw/engines/image/image_buffer_cache.hh
+++ b/source/blender/draw/engines/image/image_buffer_cache.hh
@@ -1,20 +1,5 @@
-/*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * Copyright 2022, Blender Foundation.
- */
+/* SPDX-License-Identifier: GPL-2.0-or-later
+ * Copyright 2022 Blender Foundation. */
/** \file
* \ingroup draw_engine
diff --git a/source/blender/draw/engines/overlay/overlay_wireframe.c b/source/blender/draw/engines/overlay/overlay_wireframe.c
index 2636d7876d5..b3c0c5da9b5 100644
--- a/source/blender/draw/engines/overlay/overlay_wireframe.c
+++ b/source/blender/draw/engines/overlay/overlay_wireframe.c
@@ -276,8 +276,12 @@ void OVERLAY_wireframe_cache_populate(OVERLAY_Data *vedata,
const bool is_sculpt_mode = ((ob->mode & OB_MODE_SCULPT) != 0) && (ob->sculpt != NULL);
const bool use_sculpt_pbvh = BKE_sculptsession_use_pbvh_draw(ob, draw_ctx->v3d) &&
!DRW_state_is_image_render();
+ const bool is_instance = (ob->base_flag & BASE_FROM_DUPLI);
+ const bool instance_parent_in_edit_mode = is_instance ? DRW_object_is_in_edit_mode(
+ DRW_object_get_dupli_parent(ob)) :
+ false;
const bool use_coloring = (use_wire && !is_edit_mode && !is_sculpt_mode &&
- !has_edit_mesh_cage);
+ !has_edit_mesh_cage && !instance_parent_in_edit_mode);
geom = DRW_cache_object_face_wireframe_get(ob);
if (geom || use_sculpt_pbvh) {
diff --git a/source/blender/draw/engines/workbench/workbench_data.c b/source/blender/draw/engines/workbench/workbench_data.c
index bf197986687..010f424b9da 100644
--- a/source/blender/draw/engines/workbench/workbench_data.c
+++ b/source/blender/draw/engines/workbench/workbench_data.c
@@ -275,7 +275,7 @@ void workbench_update_world_ubo(WORKBENCH_PrivateData *wpd)
copy_v2_v2(wd.viewport_size_inv, DRW_viewport_invert_size_get());
copy_v3_v3(wd.object_outline_color, wpd->shading.object_outline_color);
wd.object_outline_color[3] = 1.0f;
- wd.ui_scale = G_draw.block.sizePixel;
+ wd.ui_scale = DRW_state_is_image_render() ? 1.0f : G_draw.block.sizePixel;
wd.matcap_orientation = (wpd->shading.flag & V3D_SHADING_MATCAP_FLIP_X) != 0;
workbench_studiolight_data_update(wpd, &wd);
diff --git a/source/blender/draw/engines/workbench/workbench_effect_dof.c b/source/blender/draw/engines/workbench/workbench_effect_dof.c
index 6b64a9d7f09..58d49cf226e 100644
--- a/source/blender/draw/engines/workbench/workbench_effect_dof.c
+++ b/source/blender/draw/engines/workbench/workbench_effect_dof.c
@@ -31,22 +31,22 @@ static void square_to_circle(float x, float y, float *r, float *T)
if (x > -y) {
if (x > y) {
*r = x;
- *T = (M_PI / 4.0f) * (y / x);
+ *T = M_PI_4 * (y / x);
}
else {
*r = y;
- *T = (M_PI / 4.0f) * (2 - (x / y));
+ *T = M_PI_4 * (2 - (x / y));
}
}
else {
if (x < y) {
*r = -x;
- *T = (M_PI / 4.0f) * (4 + (y / x));
+ *T = M_PI_4 * (4 + (y / x));
}
else {
*r = -y;
if (y != 0) {
- *T = (M_PI / 4.0f) * (6 - (x / y));
+ *T = M_PI_4 * (6 - (x / y));
}
else {
*T = 0.0f;
diff --git a/source/blender/draw/intern/draw_cache_extract_mesh.cc b/source/blender/draw/intern/draw_cache_extract_mesh.cc
index dea3fa9b75a..e84f2c7a327 100644
--- a/source/blender/draw/intern/draw_cache_extract_mesh.cc
+++ b/source/blender/draw/intern/draw_cache_extract_mesh.cc
@@ -854,6 +854,7 @@ static void mesh_buffer_cache_create_requested_subdiv(MeshBatchCache *cache,
}
mesh_render_data_update_looptris(mr, MR_ITER_LOOPTRI, MR_DATA_LOOPTRI);
+ mesh_render_data_update_normals(mr, MR_DATA_TAN_LOOP_NOR);
mesh_render_data_update_loose_geom(mr, mbc, MR_ITER_LEDGE | MR_ITER_LVERT, MR_DATA_LOOSE_GEOM);
DRW_subdivide_loose_geom(subdiv_cache, mbc);
diff --git a/source/blender/draw/intern/draw_cache_impl_curves.cc b/source/blender/draw/intern/draw_cache_impl_curves.cc
index df1ac12605a..aea71d965d1 100644
--- a/source/blender/draw/intern/draw_cache_impl_curves.cc
+++ b/source/blender/draw/intern/draw_cache_impl_curves.cc
@@ -340,7 +340,7 @@ bool hair_ensure_procedural_data(Object *object,
HairBatchCache *cache = curves_batch_cache_get(curves);
*r_hair_cache = &cache->hair;
- const int steps = 2; /* TODO: don't hard-code? */
+ const int steps = 3; /* TODO: don't hard-code? */
(*r_hair_cache)->final[subdiv].strands_res = 1 << (steps + subdiv);
/* Refreshed on combing and simulation. */
diff --git a/source/blender/draw/intern/draw_common.c b/source/blender/draw/intern/draw_common.c
index 2897234f4dc..c7edf003346 100644
--- a/source/blender/draw/intern/draw_common.c
+++ b/source/blender/draw/intern/draw_common.c
@@ -135,7 +135,7 @@ void DRW_globals_update(void)
UI_GetThemeColor4fv(TH_CFRAME, gb->colorCurrentFrame);
- /* Metaball */
+ /* Meta-ball. */
UI_COLOR_RGBA_FROM_U8(0xA0, 0x30, 0x30, 0xFF, gb->colorMballRadius);
UI_COLOR_RGBA_FROM_U8(0xF0, 0xA0, 0xA0, 0xFF, gb->colorMballRadiusSelect);
UI_COLOR_RGBA_FROM_U8(0x30, 0xA0, 0x30, 0xFF, gb->colorMballStiffness);
diff --git a/source/blender/draw/intern/shaders/common_math_lib.glsl b/source/blender/draw/intern/shaders/common_math_lib.glsl
index 479f9cd1827..bc31649fd0f 100644
--- a/source/blender/draw/intern/shaders/common_math_lib.glsl
+++ b/source/blender/draw/intern/shaders/common_math_lib.glsl
@@ -6,6 +6,7 @@
#define M_PI 3.14159265358979323846 /* pi */
#define M_2PI 6.28318530717958647692 /* 2*pi */
#define M_PI_2 1.57079632679489661923 /* pi/2 */
+#define M_PI_4 0.78539816339744830962 /* pi/4 */
#define M_1_PI 0.318309886183790671538 /* 1/pi */
#define M_1_2PI 0.159154943091895335768 /* 1/(2*pi) */
#define M_1_PI2 0.101321183642337771443 /* 1/(pi^2) */
@@ -93,7 +94,7 @@ vec2 sqr(vec2 a) { return a * a; }
vec3 sqr(vec3 a) { return a * a; }
vec4 sqr(vec4 a) { return a * a; }
-/* Use manual powers for fixed powers. pow() can have unpredicatble results on some implementations.
+/* Use manual powers for fixed powers. pow() can have unpredictable results on some implementations.
* (see T87369, T87541) */
float pow6(float x) { return sqr(sqr(x) * x); }
float pow8(float x) { return sqr(sqr(sqr(x))); }
diff --git a/source/blender/editors/animation/anim_channels_defines.c b/source/blender/editors/animation/anim_channels_defines.c
index edb6d188ab8..445d3715658 100644
--- a/source/blender/editors/animation/anim_channels_defines.c
+++ b/source/blender/editors/animation/anim_channels_defines.c
@@ -203,7 +203,7 @@ static void acf_generic_channel_color(bAnimContext *ac, bAnimListElem *ale, floa
rgb_uchar_to_float(r_color, cp);
}
else {
- /* FIXME: what happens when the indention is 1 greater than what it should be
+ /* FIXME: what happens when the indentation is 1 greater than what it should be
* (due to grouping)? */
int colOfs = 10 - 10 * indent;
UI_GetThemeColorShade3fv(TH_SHADE2, colOfs, r_color);
@@ -252,44 +252,44 @@ static void acf_generic_channel_backdrop(bAnimContext *ac,
immUnbindProgram();
}
-/* Indention + Offset ------------------------------------------- */
+/* Indentation + Offset ------------------------------------------- */
-/* indention level is always the value in the name */
-static short acf_generic_indention_0(bAnimContext *UNUSED(ac), bAnimListElem *UNUSED(ale))
+/* indentation level is always the value in the name */
+static short acf_generic_indentation_0(bAnimContext *UNUSED(ac), bAnimListElem *UNUSED(ale))
{
return 0;
}
-static short acf_generic_indention_1(bAnimContext *UNUSED(ac), bAnimListElem *UNUSED(ale))
+static short acf_generic_indentation_1(bAnimContext *UNUSED(ac), bAnimListElem *UNUSED(ale))
{
return 1;
}
#if 0 /* XXX not used */
-static short acf_generic_indention_2(bAnimContext *ac, bAnimListElem *ale)
+static short acf_generic_indentation_2(bAnimContext *ac, bAnimListElem *ale)
{
return 2;
}
#endif
-/* indention which varies with the grouping status */
-static short acf_generic_indention_flexible(bAnimContext *UNUSED(ac), bAnimListElem *ale)
+/* indentation which varies with the grouping status */
+static short acf_generic_indentation_flexible(bAnimContext *UNUSED(ac), bAnimListElem *ale)
{
short indent = 0;
- /* grouped F-Curves need extra level of indention */
+ /* grouped F-Curves need extra level of indentation */
if (ale->type == ANIMTYPE_FCURVE) {
FCurve *fcu = (FCurve *)ale->data;
- /* TODO: we need some way of specifying that the indention color should be one less. */
+ /* TODO: we need some way of specifying that the indentation color should be one less. */
if (fcu->grp) {
indent++;
}
}
- /* no indention */
+ /* no indentation */
return indent;
}
-/* basic offset for channels derived from indention */
+/* basic offset for channels derived from indentation */
static short acf_generic_basic_offset(bAnimContext *ac, bAnimListElem *ale)
{
const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale);
@@ -352,7 +352,7 @@ static short acf_generic_group_offset(bAnimContext *ac, bAnimListElem *ale)
}
}
- /* offset is just the normal type - i.e. based on indention */
+ /* offset is just the normal type - i.e. based on indentation */
return offset;
}
@@ -525,15 +525,15 @@ static void *acf_summary_setting_ptr(bAnimListElem *ale,
return NULL;
}
-/* all animation summary (DopeSheet only) type define */
+/** All animation summary (dope-sheet only) type define. */
static bAnimChannelType ACF_SUMMARY = {
"Summary", /* type name */
ACHANNEL_ROLE_EXPANDER, /* role */
- acf_summary_color, /* backdrop color */
- acf_summary_backdrop, /* backdrop */
- acf_generic_indention_0, /* indent level */
- NULL, /* offset */
+ acf_summary_color, /* backdrop color */
+ acf_summary_backdrop, /* backdrop */
+ acf_generic_indentation_0, /* indent level */
+ NULL, /* offset */
acf_summary_name, /* name */
NULL, /* name prop */
@@ -634,14 +634,14 @@ static void *acf_scene_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings set
}
}
-/* scene type define */
+/** Scene type define. */
static bAnimChannelType ACF_SCENE = {
"Scene", /* type name */
ACHANNEL_ROLE_EXPANDER, /* role */
acf_generic_root_color, /* backdrop color */
acf_generic_root_backdrop, /* backdrop */
- acf_generic_indention_0, /* indent level */
+ acf_generic_indentation_0, /* indent level */
NULL, /* offset */
acf_generic_idblock_name, /* name */
@@ -810,14 +810,14 @@ static void *acf_object_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings se
}
}
-/* object type define */
+/** Object type define. */
static bAnimChannelType ACF_OBJECT = {
"Object", /* type name */
ACHANNEL_ROLE_EXPANDER, /* role */
acf_generic_root_color, /* backdrop color */
acf_generic_root_backdrop, /* backdrop */
- acf_generic_indention_0, /* indent level */
+ acf_generic_indentation_0, /* indent level */
NULL, /* offset */
acf_object_name, /* name */
@@ -987,15 +987,15 @@ static void *acf_group_setting_ptr(bAnimListElem *ale,
return GET_ACF_FLAG_PTR(agrp->flag, type);
}
-/* group type define */
+/** Group type define. */
static bAnimChannelType ACF_GROUP = {
"Group", /* type name */
ACHANNEL_ROLE_CHANNEL, /* role */
- acf_group_color, /* backdrop color */
- acf_group_backdrop, /* backdrop */
- acf_generic_indention_0, /* indent level */
- acf_generic_group_offset, /* offset */
+ acf_group_color, /* backdrop color */
+ acf_group_backdrop, /* backdrop */
+ acf_generic_indentation_0, /* indent level */
+ acf_generic_group_offset, /* offset */
acf_group_name, /* name */
acf_group_name_prop, /* name prop */
@@ -1111,14 +1111,14 @@ static void *acf_fcurve_setting_ptr(bAnimListElem *ale,
return GET_ACF_FLAG_PTR(fcu->flag, type);
}
-/* fcurve type define */
+/** F-Curve type define. */
static bAnimChannelType ACF_FCURVE = {
"F-Curve", /* type name */
ACHANNEL_ROLE_CHANNEL, /* role */
acf_generic_channel_color, /* backdrop color */
acf_generic_channel_backdrop, /* backdrop */
- acf_generic_indention_flexible,
+ acf_generic_indentation_flexible,
/* indent level */ /* XXX rename this to f-curves only? */
acf_generic_group_offset, /* offset */
@@ -1231,14 +1231,14 @@ static int acf_nla_controls_icon(bAnimListElem *UNUSED(ale))
return ICON_NLA;
}
-/* NLA Control FCurves Expander type define */
+/** NLA Control F-Curves expander type define. */
static bAnimChannelType ACF_NLACONTROLS = {
"NLA Controls Expander", /* type name */
ACHANNEL_ROLE_EXPANDER, /* role */
acf_nla_controls_color, /* backdrop color */
acf_nla_controls_backdrop, /* backdrop */
- acf_generic_indention_0, /* indent level */
+ acf_generic_indentation_0, /* indent level */
acf_generic_group_offset, /* offset */
acf_nla_controls_name, /* name */
@@ -1271,14 +1271,14 @@ static void acf_nla_curve_name(bAnimListElem *ale, char *name)
}
}
-/* NLA Control F-Curve type define */
+/** NLA Control F-Curve type define. */
static bAnimChannelType ACF_NLACURVE = {
"NLA Control F-Curve", /* type name */
ACHANNEL_ROLE_CHANNEL, /* role */
acf_generic_channel_color, /* backdrop color */
acf_generic_channel_backdrop, /* backdrop */
- acf_generic_indention_1, /* indent level */
+ acf_generic_indentation_1, /* indent level */
acf_generic_group_offset, /* offset */
acf_nla_curve_name, /* name */
@@ -1361,14 +1361,14 @@ static void *acf_fillactd_setting_ptr(bAnimListElem *ale,
}
}
-/* object action expander type define */
+/** Object action expander type define. */
static bAnimChannelType ACF_FILLACTD = {
"Ob-Action Filler", /* type name */
ACHANNEL_ROLE_EXPANDER, /* role */
acf_generic_dataexpand_color, /* backdrop color */
acf_generic_dataexpand_backdrop, /* backdrop */
- acf_generic_indention_1, /* indent level */
+ acf_generic_indentation_1, /* indent level */
acf_generic_basic_offset, /* offset */
acf_generic_idblock_name, /* name */
@@ -1446,14 +1446,14 @@ static void *acf_filldrivers_setting_ptr(bAnimListElem *ale,
}
}
-/* drivers expander type define */
+/** Drivers expander type define. */
static bAnimChannelType ACF_FILLDRIVERS = {
"Drivers Filler", /* type name */
ACHANNEL_ROLE_EXPANDER, /* role */
acf_generic_dataexpand_color, /* backdrop color */
acf_generic_dataexpand_backdrop, /* backdrop */
- acf_generic_indention_1, /* indent level */
+ acf_generic_indentation_1, /* indent level */
acf_generic_basic_offset, /* offset */
acf_filldrivers_name, /* name */
@@ -1525,14 +1525,14 @@ static void *acf_dsmat_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings set
}
}
-/* material expander type define */
+/** Material expander type define. */
static bAnimChannelType ACF_DSMAT = {
"Material Data Expander", /* type name */
ACHANNEL_ROLE_EXPANDER, /* role */
acf_generic_dataexpand_color, /* backdrop color */
acf_generic_dataexpand_backdrop, /* backdrop */
- acf_generic_indention_1, /* indent level */
+ acf_generic_indentation_1, /* indent level */
acf_generic_basic_offset, /* offset */
acf_generic_idblock_name, /* name */
@@ -1606,14 +1606,14 @@ static void *acf_dslight_setting_ptr(bAnimListElem *ale,
}
}
-/* light expander type define */
+/** Light expander type define. */
static bAnimChannelType ACF_DSLIGHT = {
"Light Expander", /* type name */
ACHANNEL_ROLE_EXPANDER, /* role */
acf_generic_dataexpand_color, /* backdrop color */
acf_generic_dataexpand_backdrop, /* backdrop */
- acf_generic_indention_1, /* indent level */
+ acf_generic_indentation_1, /* indent level */
acf_generic_basic_offset, /* offset */
acf_generic_idblock_name, /* name */
@@ -1637,7 +1637,7 @@ static int acf_dstex_icon(bAnimListElem *UNUSED(ale))
/* FIXME: soon to be obsolete? */
static short acf_dstex_offset(bAnimContext *UNUSED(ac), bAnimListElem *UNUSED(ale))
{
- return 14; /* XXX: simply include this in indention instead? */
+ return 14; /* XXX: simply include this in indentation instead? */
}
/* Get the appropriate flag(s) for the setting when it is valid. */
@@ -1692,14 +1692,14 @@ static void *acf_dstex_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings set
}
}
-/* texture expander type define */
+/** Texture expander type define. */
static bAnimChannelType ACF_DSTEX = {
"Texture Data Expander", /* type name */
ACHANNEL_ROLE_EXPANDER, /* role */
acf_generic_dataexpand_color, /* backdrop color */
acf_generic_dataexpand_backdrop, /* backdrop */
- acf_generic_indention_1, /* indent level */
+ acf_generic_indentation_1, /* indent level */
acf_dstex_offset, /* offset */
acf_generic_idblock_name, /* name */
@@ -1775,14 +1775,14 @@ static void *acf_dscachefile_setting_ptr(bAnimListElem *ale,
}
}
-/* CacheFile expander type define. */
+/** CacheFile expander type define.. */
static bAnimChannelType ACF_DSCACHEFILE = {
"Cache File Expander", /* type name */
ACHANNEL_ROLE_EXPANDER, /* role */
acf_generic_dataexpand_color, /* backdrop color */
acf_generic_dataexpand_backdrop, /* backdrop */
- acf_generic_indention_1, /* indent level */
+ acf_generic_indentation_1, /* indent level */
acf_generic_basic_offset, /* offset */
acf_generic_idblock_name, /* name */
@@ -1858,14 +1858,14 @@ static void *acf_dscam_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings set
}
}
-/* camera expander type define */
+/** Camera expander type define. */
static bAnimChannelType ACF_DSCAM = {
"Camera Expander", /* type name */
ACHANNEL_ROLE_EXPANDER, /* role */
acf_generic_dataexpand_color, /* backdrop color */
acf_generic_dataexpand_backdrop, /* backdrop */
- acf_generic_indention_1, /* indent level */
+ acf_generic_indentation_1, /* indent level */
acf_generic_basic_offset, /* offset */
acf_generic_idblock_name, /* name */
@@ -1947,14 +1947,14 @@ static void *acf_dscur_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings set
}
}
-/* curve expander type define */
+/** Curve expander type define. */
static bAnimChannelType ACF_DSCUR = {
"Curve Expander", /* type name */
ACHANNEL_ROLE_EXPANDER, /* role */
acf_generic_dataexpand_color, /* backdrop color */
acf_generic_dataexpand_backdrop, /* backdrop */
- acf_generic_indention_1, /* indent level */
+ acf_generic_indentation_1, /* indent level */
acf_generic_basic_offset, /* offset */
acf_generic_idblock_name, /* name */
@@ -2045,14 +2045,14 @@ static void *acf_dsskey_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings se
}
}
-/* shapekey expander type define */
+/** Shape-key expander type define. */
static bAnimChannelType ACF_DSSKEY = {
"Shape Key Expander", /* type name */
ACHANNEL_ROLE_EXPANDER, /* role */
acf_generic_dataexpand_color, /* backdrop color */
acf_generic_dataexpand_backdrop, /* backdrop */
- acf_generic_indention_1, /* indent level */
+ acf_generic_indentation_1, /* indent level */
acf_generic_basic_offset, /* offset */
acf_generic_idblock_name, /* name */
@@ -2124,14 +2124,14 @@ static void *acf_dswor_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings set
}
}
-/* world expander type define */
+/** World expander type define. */
static bAnimChannelType ACF_DSWOR = {
"World Expander", /* type name */
ACHANNEL_ROLE_EXPANDER, /* role */
acf_generic_dataexpand_color, /* backdrop color */
acf_generic_dataexpand_backdrop, /* backdrop */
- acf_generic_indention_1, /* indent level */
+ acf_generic_indentation_1, /* indent level */
acf_generic_basic_offset, /* offset */
acf_generic_idblock_name, /* name */
@@ -2203,14 +2203,14 @@ static void *acf_dspart_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings se
}
}
-/* particle expander type define */
+/** Particle expander type define. */
static bAnimChannelType ACF_DSPART = {
"Particle Data Expander", /* type name */
ACHANNEL_ROLE_EXPANDER, /* role */
acf_generic_dataexpand_color, /* backdrop color */
acf_generic_dataexpand_backdrop, /* backdrop */
- acf_generic_indention_1, /* indent level */
+ acf_generic_indentation_1, /* indent level */
acf_generic_basic_offset, /* offset */
acf_generic_idblock_name, /* name */
@@ -2284,14 +2284,14 @@ static void *acf_dsmball_setting_ptr(bAnimListElem *ale,
}
}
-/* metaball expander type define */
+/** Meta-ball expander type define. */
static bAnimChannelType ACF_DSMBALL = {
"Metaball Expander", /* type name */
ACHANNEL_ROLE_EXPANDER, /* role */
acf_generic_dataexpand_color, /* backdrop color */
acf_generic_dataexpand_backdrop, /* backdrop */
- acf_generic_indention_1, /* indent level */
+ acf_generic_indentation_1, /* indent level */
acf_generic_basic_offset, /* offset */
acf_generic_idblock_name, /* name */
@@ -2363,14 +2363,14 @@ static void *acf_dsarm_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings set
}
}
-/* metaball expander type define */
+/** Armature expander type define. */
static bAnimChannelType ACF_DSARM = {
"Armature Expander", /* type name */
ACHANNEL_ROLE_EXPANDER, /* role */
acf_generic_dataexpand_color, /* backdrop color */
acf_generic_dataexpand_backdrop, /* backdrop */
- acf_generic_indention_1, /* indent level */
+ acf_generic_indentation_1, /* indent level */
acf_generic_basic_offset, /* offset */
acf_generic_idblock_name, /* name */
@@ -2455,14 +2455,14 @@ static void *acf_dsntree_setting_ptr(bAnimListElem *ale,
}
}
-/* node tree expander type define */
+/** Node tree expander type define. */
static bAnimChannelType ACF_DSNTREE = {
"Node Tree Expander", /* type name */
ACHANNEL_ROLE_EXPANDER, /* role */
acf_generic_dataexpand_color, /* backdrop color */
acf_generic_dataexpand_backdrop, /* backdrop */
- acf_generic_indention_1, /* indent level */
+ acf_generic_indentation_1, /* indent level */
acf_dsntree_offset, /* offset */
acf_generic_idblock_name, /* name */
@@ -2536,14 +2536,14 @@ static void *acf_dslinestyle_setting_ptr(bAnimListElem *ale,
}
}
-/* node tree expander type define */
+/** Line Style expander type define. */
static bAnimChannelType ACF_DSLINESTYLE = {
"Line Style Expander", /* type name */
ACHANNEL_ROLE_EXPANDER, /* role */
acf_generic_dataexpand_color, /* backdrop color */
acf_generic_dataexpand_backdrop, /* backdrop */
- acf_generic_indention_1, /* indent level */
+ acf_generic_indentation_1, /* indent level */
acf_generic_basic_offset, /* offset */
acf_generic_idblock_name, /* name */
@@ -2615,14 +2615,14 @@ static void *acf_dsmesh_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings se
}
}
-/* node tree expander type define */
+/** Mesh expander type define. */
static bAnimChannelType ACF_DSMESH = {
"Mesh Expander", /* type name */
ACHANNEL_ROLE_EXPANDER, /* role */
acf_generic_dataexpand_color, /* backdrop color */
acf_generic_dataexpand_backdrop, /* backdrop */
- acf_generic_indention_1,
+ acf_generic_indentation_1,
/* indent level */ /* XXX this only works for compositing */
acf_generic_basic_offset, /* offset */
@@ -2695,14 +2695,14 @@ static void *acf_dslat_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings set
}
}
-/* node tree expander type define */
+/** Lattice expander type define. */
static bAnimChannelType ACF_DSLAT = {
"Lattice Expander", /* type name */
ACHANNEL_ROLE_EXPANDER, /* role */
acf_generic_dataexpand_color, /* backdrop color */
acf_generic_dataexpand_backdrop, /* backdrop */
- acf_generic_indention_1,
+ acf_generic_indentation_1,
/* indent level */ /* XXX this only works for compositing */
acf_generic_basic_offset, /* offset */
@@ -2775,14 +2775,14 @@ static void *acf_dsspk_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings set
}
}
-/* speaker expander type define */
+/** Speaker expander type define. */
static bAnimChannelType ACF_DSSPK = {
"Speaker Expander", /* type name */
ACHANNEL_ROLE_EXPANDER, /* role */
acf_generic_dataexpand_color, /* backdrop color */
acf_generic_dataexpand_backdrop, /* backdrop */
- acf_generic_indention_1, /* indent level */
+ acf_generic_indentation_1, /* indent level */
acf_generic_basic_offset, /* offset */
acf_generic_idblock_name, /* name */
@@ -2856,14 +2856,14 @@ static void *acf_dscurves_setting_ptr(bAnimListElem *ale,
}
}
-/* Curves expander type define */
+/** Curves expander type define. */
static bAnimChannelType ACF_DSHAIR = {
"Curves Expander", /* type name */
ACHANNEL_ROLE_EXPANDER, /* role */
acf_generic_dataexpand_color, /* backdrop color */
acf_generic_dataexpand_backdrop, /* backdrop */
- acf_generic_indention_1, /* indent level */
+ acf_generic_indentation_1, /* indent level */
acf_generic_basic_offset, /* offset */
acf_generic_idblock_name, /* name */
@@ -2937,14 +2937,14 @@ static void *acf_dspointcloud_setting_ptr(bAnimListElem *ale,
}
}
-/* pointcloud expander type define */
+/** Point-cloud expander type define. */
static bAnimChannelType ACF_DSPOINTCLOUD = {
"PointCloud Expander", /* type name */
ACHANNEL_ROLE_EXPANDER, /* role */
acf_generic_dataexpand_color, /* backdrop color */
acf_generic_dataexpand_backdrop, /* backdrop */
- acf_generic_indention_1, /* indent level */
+ acf_generic_indentation_1, /* indent level */
acf_generic_basic_offset, /* offset */
acf_generic_idblock_name, /* name */
@@ -3018,14 +3018,14 @@ static void *acf_dsvolume_setting_ptr(bAnimListElem *ale,
}
}
-/* volume expander type define */
+/** Volume expander type define. */
static bAnimChannelType ACF_DSVOLUME = {
"Volume Expander", /* type name */
ACHANNEL_ROLE_EXPANDER, /* role */
acf_generic_dataexpand_color, /* backdrop color */
acf_generic_dataexpand_backdrop, /* backdrop */
- acf_generic_indention_1, /* indent level */
+ acf_generic_indentation_1, /* indent level */
acf_generic_basic_offset, /* offset */
acf_generic_idblock_name, /* name */
@@ -3097,13 +3097,14 @@ static void *acf_dssimulation_setting_ptr(bAnimListElem *ale,
}
}
+/** Simulation expander type define. */
static bAnimChannelType ACF_DSSIMULATION = {
"Simulation Expander", /* type name */
ACHANNEL_ROLE_EXPANDER, /* role */
acf_generic_dataexpand_color, /* backdrop color */
acf_generic_dataexpand_backdrop, /* backdrop */
- acf_generic_indention_1, /* indent level */
+ acf_generic_indentation_1, /* indent level */
acf_generic_basic_offset, /* offset */
acf_generic_idblock_name, /* name */
@@ -3177,14 +3178,14 @@ static void *acf_dsgpencil_setting_ptr(bAnimListElem *ale,
}
}
-/* grease pencil expander type define */
+/** Grease-pencil expander type define. */
static bAnimChannelType ACF_DSGPENCIL = {
"GPencil DS Expander", /* type name */
ACHANNEL_ROLE_EXPANDER, /* role */
acf_generic_dataexpand_color, /* backdrop color */
acf_generic_dataexpand_backdrop, /* backdrop */
- acf_generic_indention_1, /* indent level */
+ acf_generic_indentation_1, /* indent level */
acf_generic_basic_offset, /* offset */
acf_generic_idblock_name, /* name */
@@ -3258,14 +3259,14 @@ static void *acf_dsmclip_setting_ptr(bAnimListElem *ale,
}
}
-/* world expander type define */
+/** Movie-clip expander type define. */
static bAnimChannelType ACF_DSMCLIP = {
"Movieclip Expander", /* type name */
ACHANNEL_ROLE_EXPANDER, /* role */
acf_generic_dataexpand_color, /* backdrop color */
acf_generic_dataexpand_backdrop, /* backdrop */
- acf_generic_indention_1, /* indent level */
+ acf_generic_indentation_1, /* indent level */
acf_generic_basic_offset, /* offset */
acf_generic_idblock_name, /* name */
@@ -3373,14 +3374,14 @@ static void *acf_shapekey_setting_ptr(bAnimListElem *ale,
}
}
-/* shapekey expander type define */
+/** Shape-key expander type define. */
static bAnimChannelType ACF_SHAPEKEY = {
"Shape Key", /* type name */
ACHANNEL_ROLE_CHANNEL, /* role */
acf_generic_channel_color, /* backdrop color */
acf_generic_channel_backdrop, /* backdrop */
- acf_generic_indention_0, /* indent level */
+ acf_generic_indentation_0, /* indent level */
acf_generic_basic_offset, /* offset */
acf_shapekey_name, /* name */
@@ -3453,15 +3454,15 @@ static void *acf_gpd_setting_ptr(bAnimListElem *ale,
return GET_ACF_FLAG_PTR(gpd->flag, type);
}
-/* gpencil datablock type define */
+/** Grease-pencil data-block type define. */
static bAnimChannelType ACF_GPD = {
"GPencil Datablock", /* type name */
ACHANNEL_ROLE_EXPANDER, /* role */
- acf_gpd_color, /* backdrop color */
- acf_group_backdrop, /* backdrop */
- acf_generic_indention_0, /* indent level */
- acf_generic_group_offset, /* offset */
+ acf_gpd_color, /* backdrop color */
+ acf_group_backdrop, /* backdrop */
+ acf_generic_indentation_0, /* indent level */
+ acf_generic_group_offset, /* offset */
acf_generic_idblock_name, /* name */
acf_generic_idfill_name_prop, /* name prop */
@@ -3552,15 +3553,15 @@ static void *acf_gpl_setting_ptr(bAnimListElem *ale,
return GET_ACF_FLAG_PTR(gpl->flag, type);
}
-/* grease pencil layer type define */
+/** Grease-pencil layer type define. */
static bAnimChannelType ACF_GPL = {
"GPencil Layer", /* type name */
ACHANNEL_ROLE_CHANNEL, /* role */
- acf_gpencil_channel_color, /* backdrop color */
- acf_generic_channel_backdrop, /* backdrop */
- acf_generic_indention_flexible, /* indent level */
- acf_generic_group_offset, /* offset */
+ acf_gpencil_channel_color, /* backdrop color */
+ acf_generic_channel_backdrop, /* backdrop */
+ acf_generic_indentation_flexible, /* indent level */
+ acf_generic_group_offset, /* offset */
acf_gpl_name, /* name */
acf_gpl_name_prop, /* name prop */
@@ -3634,15 +3635,15 @@ static void *acf_mask_setting_ptr(bAnimListElem *ale,
return GET_ACF_FLAG_PTR(mask->flag, type);
}
-/* mask datablock type define */
+/** Mask data-block type define. */
static bAnimChannelType ACF_MASKDATA = {
"Mask Datablock", /* type name */
ACHANNEL_ROLE_EXPANDER, /* role */
- acf_mask_color, /* backdrop color */
- acf_group_backdrop, /* backdrop */
- acf_generic_indention_0, /* indent level */
- acf_generic_group_offset, /* offset */
+ acf_mask_color, /* backdrop color */
+ acf_group_backdrop, /* backdrop */
+ acf_generic_indentation_0, /* indent level */
+ acf_generic_group_offset, /* offset */
acf_generic_idblock_name, /* name */
acf_generic_idfill_name_prop, /* name prop */
@@ -3730,15 +3731,15 @@ static void *acf_masklay_setting_ptr(bAnimListElem *ale,
return GET_ACF_FLAG_PTR(masklay->flag, type);
}
-/* grease pencil layer type define */
+/** Mask layer type define. */
static bAnimChannelType ACF_MASKLAYER = {
"Mask Layer", /* type name */
ACHANNEL_ROLE_CHANNEL, /* role */
- acf_generic_channel_color, /* backdrop color */
- acf_generic_channel_backdrop, /* backdrop */
- acf_generic_indention_flexible, /* indent level */
- acf_generic_group_offset, /* offset */
+ acf_generic_channel_color, /* backdrop color */
+ acf_generic_channel_backdrop, /* backdrop */
+ acf_generic_indentation_flexible, /* indent level */
+ acf_generic_group_offset, /* offset */
acf_masklay_name, /* name */
acf_masklay_name_prop, /* name prop */
@@ -3870,14 +3871,14 @@ static void *acf_nlatrack_setting_ptr(bAnimListElem *ale,
return GET_ACF_FLAG_PTR(nlt->flag, type);
}
-/* nla track type define */
+/** NLA track type define. */
static bAnimChannelType ACF_NLATRACK = {
"NLA Track", /* type name */
ACHANNEL_ROLE_CHANNEL, /* role */
- acf_nlatrack_color, /* backdrop color */
- acf_generic_channel_backdrop, /* backdrop */
- acf_generic_indention_flexible, /* indent level */
+ acf_nlatrack_color, /* backdrop color */
+ acf_generic_channel_backdrop, /* backdrop */
+ acf_generic_indentation_flexible, /* indent level */
acf_generic_group_offset,
/* offset */ /* XXX? */
@@ -4056,10 +4057,10 @@ static bAnimChannelType ACF_NLAACTION = {
"NLA Active Action", /* type name */
ACHANNEL_ROLE_CHANNEL, /* role */
- acf_nlaaction_color, /* backdrop color (NOTE: the backdrop handles this too,
- * since it needs special hacks). */
- acf_nlaaction_backdrop, /* backdrop */
- acf_generic_indention_flexible, /* indent level */
+ acf_nlaaction_color, /* backdrop color (NOTE: the backdrop handles this too,
+ * since it needs special hacks). */
+ acf_nlaaction_backdrop, /* backdrop */
+ acf_generic_indentation_flexible, /* indent level */
acf_generic_group_offset,
/* offset */ /* XXX? */
diff --git a/source/blender/editors/animation/anim_channels_edit.c b/source/blender/editors/animation/anim_channels_edit.c
index 3a57287cd60..df418b204f9 100644
--- a/source/blender/editors/animation/anim_channels_edit.c
+++ b/source/blender/editors/animation/anim_channels_edit.c
@@ -490,7 +490,7 @@ static void anim_flush_channel_setting_up(bAnimContext *ac,
}
/* Go backwards in the list, until the highest-ranking element
- * (by indention has been covered). */
+ * (by indentation has been covered). */
int prevLevel = matchLevel;
for (bAnimListElem *ale = match->prev; ale; ale = ale->prev) {
const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale);
@@ -539,7 +539,7 @@ static void anim_flush_channel_setting_down(bAnimContext *ac,
bAnimListElem *const match,
const int matchLevel)
{
- /* go forwards in the list, until the lowest-ranking element (by indention has been covered) */
+ /* go forwards in the list, until the lowest-ranking element (by indentation has been covered) */
for (bAnimListElem *ale = match->next; ale; ale = ale->next) {
const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale);
diff --git a/source/blender/editors/animation/anim_intern.h b/source/blender/editors/animation/anim_intern.h
index e7277c51cd3..8d8d624c69b 100644
--- a/source/blender/editors/animation/anim_intern.h
+++ b/source/blender/editors/animation/anim_intern.h
@@ -14,49 +14,80 @@ extern ListBase builtin_keyingsets;
/* Operator Define Prototypes ------------------- */
-/* Main Keyframe Management operators:
- * These handle keyframes management from various spaces. They only make use of
- * Keying Sets.
- */
+/* -------------------------------------------------------------------- */
+/** \name Main Keyframe Management operators
+ *
+ * These handle keyframes management from various spaces.
+ * They only make use of Keying Sets.
+ * \{ */
+
void ANIM_OT_keyframe_insert(struct wmOperatorType *ot);
void ANIM_OT_keyframe_delete(struct wmOperatorType *ot);
void ANIM_OT_keyframe_insert_by_name(struct wmOperatorType *ot);
void ANIM_OT_keyframe_delete_by_name(struct wmOperatorType *ot);
-/* Main Keyframe Management operators:
- * These handle keyframes management from various spaces. They will handle the menus
- * required for each space.
- */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Main Keyframe Management operators
+ *
+ * These handle keyframes management from various spaces.
+ * They will handle the menus required for each space.
+ * \{ */
+
void ANIM_OT_keyframe_insert_menu(struct wmOperatorType *ot);
void ANIM_OT_keyframe_delete_v3d(struct wmOperatorType *ot);
void ANIM_OT_keyframe_clear_v3d(struct wmOperatorType *ot);
-/* Keyframe management operators for UI buttons (RMB menu). */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Keyframe management operators for UI buttons (RMB menu)
+ * \{ */
+
void ANIM_OT_keyframe_insert_button(struct wmOperatorType *ot);
void ANIM_OT_keyframe_delete_button(struct wmOperatorType *ot);
void ANIM_OT_keyframe_clear_button(struct wmOperatorType *ot);
-/* .......... */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name KeyingSet management operators for UI buttons (RMB menu)
+ * \{ */
-/* KeyingSet management operators for UI buttons (RMB menu) */
void ANIM_OT_keyingset_button_add(struct wmOperatorType *ot);
void ANIM_OT_keyingset_button_remove(struct wmOperatorType *ot);
-/* KeyingSet management operators for RNA collections/UI buttons */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name KeyingSet management operators for RNA collections/UI buttons
+ * \{ */
+
void ANIM_OT_keying_set_add(struct wmOperatorType *ot);
void ANIM_OT_keying_set_remove(struct wmOperatorType *ot);
void ANIM_OT_keying_set_path_add(struct wmOperatorType *ot);
void ANIM_OT_keying_set_path_remove(struct wmOperatorType *ot);
-/* KeyingSet general operators */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name KeyingSet general operators
+ * \{ */
+
void ANIM_OT_keying_set_active_set(struct wmOperatorType *ot);
-/* .......... */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Driver management operators for UI buttons (RMB menu)
+ * \{ */
-/* Driver management operators for UI buttons (RMB menu) */
void ANIM_OT_driver_button_add(struct wmOperatorType *ot);
void ANIM_OT_driver_button_remove(struct wmOperatorType *ot);
void ANIM_OT_driver_button_edit(struct wmOperatorType *ot);
void ANIM_OT_copy_driver_button(struct wmOperatorType *ot);
void ANIM_OT_paste_driver_button(struct wmOperatorType *ot);
+
+/** \} */
diff --git a/source/blender/editors/animation/anim_ops.c b/source/blender/editors/animation/anim_ops.c
index 1e8f46fd490..5b0c5eac11b 100644
--- a/source/blender/editors/animation/anim_ops.c
+++ b/source/blender/editors/animation/anim_ops.c
@@ -233,7 +233,7 @@ static bool use_sequencer_snapping(bContext *C)
Scene *scene = CTX_data_scene(C);
short snap_flag = SEQ_tool_settings_snap_flag_get(scene);
- return (scene->toolsettings->snap_flag & SCE_SNAP_SEQ) &&
+ return (scene->toolsettings->snap_flag_seq & SCE_SNAP) &&
(snap_flag & SEQ_SNAP_CURRENT_FRAME_TO_STRIPS);
}
diff --git a/source/blender/editors/animation/drivers.c b/source/blender/editors/animation/drivers.c
index 6ae82a754aa..e1e974ff119 100644
--- a/source/blender/editors/animation/drivers.c
+++ b/source/blender/editors/animation/drivers.c
@@ -979,7 +979,7 @@ static int add_driver_button_menu_exec(bContext *C, wmOperator *op)
/* XXX: We assume that it's fine to use the same set of properties,
* since they're actually the same. */
- WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, op->ptr);
+ WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, op->ptr, NULL);
return OPERATOR_FINISHED;
}
diff --git a/source/blender/editors/animation/fmodifier_ui.c b/source/blender/editors/animation/fmodifier_ui.c
index 8da96e4f42b..bdfec49fe42 100644
--- a/source/blender/editors/animation/fmodifier_ui.c
+++ b/source/blender/editors/animation/fmodifier_ui.c
@@ -411,7 +411,7 @@ static void generator_panel_draw(const bContext *C, Panel *panel)
uiLayout *first_row = uiLayoutRow(col, true);
uiItemFullR(first_row, ptr, prop, 0, 0, 0, IFACE_("y = (Ax + B)"), ICON_NONE);
uiItemFullR(first_row, ptr, prop, 1, 0, 0, "", ICON_NONE);
- for (int i = 2; i < data->arraysize - 1; i++) {
+ for (int i = 2; i < data->arraysize - 1; i += 2) {
/* \u2715 is the multiplication symbol. */
uiLayout *row = uiLayoutRow(col, true);
uiItemFullR(row, ptr, prop, i, 0, 0, IFACE_("\u2715 (Ax + B)"), ICON_NONE);
diff --git a/source/blender/editors/animation/keyframes_keylist.cc b/source/blender/editors/animation/keyframes_keylist.cc
index 0b795fea278..3356ef4d47d 100644
--- a/source/blender/editors/animation/keyframes_keylist.cc
+++ b/source/blender/editors/animation/keyframes_keylist.cc
@@ -807,8 +807,11 @@ static void add_bezt_to_keyblocks_list(AnimKeylist *keylist, BezTriple *bezt, co
continue;
}
- /* Normal sequence */
- BLI_assert(is_cfra_eq(col->cfra, bezt[0].vec[1][0]));
+ /* In normal situations all keyframes are sorted. However, while keys are transformed, they
+ * may change order and then this assertion no longer holds. The effect is that the drawing
+ * isn't perfect during the transform; the "constant value" bars aren't updated until the
+ * transformation is confirmed. */
+ // BLI_assert(is_cfra_eq(col->cfra, bezt[0].vec[1][0]));
compute_keyblock_data(&block, bezt, bezt + 1);
diff --git a/source/blender/editors/animation/keyframing.c b/source/blender/editors/animation/keyframing.c
index a4845de7d7d..0f93d728c8c 100644
--- a/source/blender/editors/animation/keyframing.c
+++ b/source/blender/editors/animation/keyframing.c
@@ -244,7 +244,7 @@ FCurve *ED_action_fcurve_ensure(struct Main *bmain,
return fcu;
}
-/* Helper for update_autoflags_fcurve() */
+/** Helper for #update_autoflags_fcurve(). */
static void update_autoflags_fcurve_direct(FCurve *fcu, PropertyRNA *prop)
{
/* set additional flags for the F-Curve (i.e. only integer values) */
@@ -304,7 +304,8 @@ void update_autoflags_fcurve(FCurve *fcu, bContext *C, ReportList *reports, Poin
/* ************************************************** */
/* KEYFRAME INSERTION */
-/* Move the point where a key is about to be inserted to be inside the main cycle range.
+/**
+ * Move the point where a key is about to be inserted to be inside the main cycle range.
* Returns the type of the cycle if it is enabled and valid.
*/
static eFCU_Cycle_Type remap_cyclic_keyframe_location(FCurve *fcu, float *px, float *py)
@@ -345,7 +346,7 @@ static eFCU_Cycle_Type remap_cyclic_keyframe_location(FCurve *fcu, float *px, fl
return type;
}
-/* Used to make curves newly added to a cyclic Action cycle with the correct period. */
+/** Used to make curves newly added to a cyclic Action cycle with the correct period. */
static void make_new_fcurve_cyclic(const bAction *act, FCurve *fcu)
{
/* The curve must contain one (newly-added) keyframe. */
@@ -652,11 +653,13 @@ enum {
KEYNEEDED_DELNEXT,
} /*eKeyNeededStatus*/;
-/* This helper function determines whether a new keyframe is needed */
-/* Cases where keyframes should not be added:
- * 1. Keyframe to be added between two keyframes with similar values
- * 2. Keyframe to be added on frame where two keyframes are already situated
- * 3. Keyframe lies at point that intersects the linear line between two keyframes
+/**
+ * This helper function determines whether a new keyframe is needed.
+ *
+ * Cases where keyframes should not be added:
+ * 1. Keyframe to be added between two keyframes with similar values.
+ * 2. Keyframe to be added on frame where two keyframes are already situated.
+ * 3. Keyframe lies at point that intersects the linear line between two keyframes.
*/
static short new_key_needed(FCurve *fcu, float cFrame, float nValue)
{
@@ -769,7 +772,7 @@ static short new_key_needed(FCurve *fcu, float cFrame, float nValue)
/* ------------------ RNA Data-Access Functions ------------------ */
-/* Try to read value using RNA-properties obtained already */
+/** Try to read value using RNA-properties obtained already. */
static float *setting_get_rna_values(
PointerRNA *ptr, PropertyRNA *prop, float *buffer, int buffer_size, int *r_count)
{
@@ -844,7 +847,8 @@ enum {
VISUALKEY_SCA,
};
-/* This helper function determines if visual-keyframing should be used when
+/**
+ * This helper function determines if visual-keyframing should be used when
* inserting keyframes for the given channel. As visual-keyframing only works
* on Object and Pose-Channel blocks, this should only get called for those
* blocktypes, when using "standard" keying but 'Visual Keying' option in Auto-Keying
@@ -1012,7 +1016,8 @@ static bool visualkey_can_use(PointerRNA *ptr, PropertyRNA *prop)
return false;
}
-/* This helper function extracts the value to use for visual-keyframing
+/**
+ * This helper function extracts the value to use for visual-keyframing
* In the event that it is not possible to perform visual keying, try to fall-back
* to using the default method. Assumes that all data it has been passed is valid.
*/
@@ -1305,7 +1310,7 @@ bool insert_keyframe_direct(ReportList *reports,
return insert_keyframe_value(reports, &ptr, prop, fcu, anim_eval_context, curval, keytype, flag);
}
-/* Find or create the FCurve based on the given path, and insert the specified value into it. */
+/** Find or create the #FCurve based on the given path, and insert the specified value into it. */
static bool insert_keyframe_fcurve_value(Main *bmain,
ReportList *reports,
PointerRNA *ptr,
@@ -1829,9 +1834,10 @@ enum {
COMMONKEY_MODE_DELETE,
} /*eCommonModifyKey_Modes*/;
-/* Polling callback for use with ANIM_*_keyframe() operators
+/**
+ * Polling callback for use with `ANIM_*_keyframe()` operators
* This is based on the standard ED_operator_areaactive callback,
- * except that it does special checks for a few spacetypes too...
+ * except that it does special checks for a few space-types too.
*/
static bool modify_key_op_poll(bContext *C)
{
@@ -1957,7 +1963,8 @@ void ANIM_OT_keyframe_insert_by_name(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* keyingset to use (idname) */
- prop = RNA_def_string_file_path(ot->srna, "type", "Type", MAX_ID_NAME - 2, "", "");
+ prop = RNA_def_string(
+ ot->srna, "type", NULL, MAX_ID_NAME - 2, "Keying Set", "The Keying Set to use");
RNA_def_property_flag(prop, PROP_HIDDEN);
ot->prop = prop;
}
@@ -2117,7 +2124,8 @@ void ANIM_OT_keyframe_delete_by_name(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* keyingset to use (idname) */
- prop = RNA_def_string_file_path(ot->srna, "type", "Type", MAX_ID_NAME - 2, "", "");
+ prop = RNA_def_string(
+ ot->srna, "type", NULL, MAX_ID_NAME - 2, "Keying Set", "The Keying Set to use");
RNA_def_property_flag(prop, PROP_HIDDEN);
ot->prop = prop;
}
@@ -2840,13 +2848,12 @@ static bool object_frame_has_keyframe(Object *ob, float frame, short filter)
}
}
- /* try shapekey keyframes (if available, and allowed by filter) */
+ /* Try shape-key keyframes (if available, and allowed by filter). */
if (!(filter & ANIMFILTER_KEYS_LOCAL) && !(filter & ANIMFILTER_KEYS_NOSKEY)) {
Key *key = BKE_key_from_object(ob);
- /* shapekeys can have keyframes ('Relative Shape Keys')
- * or depend on time (old 'Absolute Shape Keys')
- */
+ /* Shape-keys can have keyframes ('Relative Shape Keys')
+ * or depend on time (old 'Absolute Shape Keys'). */
/* 1. test for relative (with keyframes) */
if (id_frame_has_keyframe((ID *)key, frame, filter)) {
diff --git a/source/blender/editors/animation/keyingsets.c b/source/blender/editors/animation/keyingsets.c
index 6fcdd21bad8..dcf8835c911 100644
--- a/source/blender/editors/animation/keyingsets.c
+++ b/source/blender/editors/animation/keyingsets.c
@@ -715,55 +715,54 @@ const EnumPropertyItem *ANIM_keying_sets_enum_itemf(bContext *C,
PropertyRNA *UNUSED(prop),
bool *r_free)
{
- Scene *scene = CTX_data_scene(C);
KeyingSet *ks;
EnumPropertyItem *item = NULL, item_tmp = {0};
int totitem = 0;
int i = 0;
- if (C == NULL) {
- return DummyRNA_DEFAULT_items;
- }
+ if (C != NULL) {
+ Scene *scene = CTX_data_scene(C);
+ /* active Keying Set
+ * - only include entry if it exists
+ */
+ if (scene->active_keyingset) {
+ /* active Keying Set */
+ item_tmp.identifier = "__ACTIVE__";
+ item_tmp.name = "Active Keying Set";
+ item_tmp.value = i;
+ RNA_enum_item_add(&item, &totitem, &item_tmp);
- /* active Keying Set
- * - only include entry if it exists
- */
- if (scene->active_keyingset) {
- /* active Keying Set */
- item_tmp.identifier = "__ACTIVE__";
- item_tmp.name = "Active Keying Set";
- item_tmp.value = i;
- RNA_enum_item_add(&item, &totitem, &item_tmp);
-
- /* separator */
- RNA_enum_item_add_separator(&item, &totitem);
- }
+ /* separator */
+ RNA_enum_item_add_separator(&item, &totitem);
+ }
- i++;
+ i++;
- /* user-defined Keying Sets
- * - these are listed in the order in which they were defined for the active scene
- */
- if (scene->keyingsets.first) {
- for (ks = scene->keyingsets.first; ks; ks = ks->next, i++) {
- if (ANIM_keyingset_context_ok_poll(C, ks)) {
- item_tmp.identifier = ks->idname;
- item_tmp.name = ks->name;
- item_tmp.description = ks->description;
- item_tmp.value = i;
- RNA_enum_item_add(&item, &totitem, &item_tmp);
+ /* user-defined Keying Sets
+ * - these are listed in the order in which they were defined for the active scene
+ */
+ if (scene->keyingsets.first) {
+ for (ks = scene->keyingsets.first; ks; ks = ks->next, i++) {
+ if (ANIM_keyingset_context_ok_poll(C, ks)) {
+ item_tmp.identifier = ks->idname;
+ item_tmp.name = ks->name;
+ item_tmp.description = ks->description;
+ item_tmp.value = i;
+ RNA_enum_item_add(&item, &totitem, &item_tmp);
+ }
}
- }
- /* separator */
- RNA_enum_item_add_separator(&item, &totitem);
+ /* separator */
+ RNA_enum_item_add_separator(&item, &totitem);
+ }
}
/* builtin Keying Sets */
i = -1;
for (ks = builtin_keyingsets.first; ks; ks = ks->next, i--) {
- /* only show KeyingSet if context is suitable */
- if (ANIM_keyingset_context_ok_poll(C, ks)) {
+ /* Only show #KeyingSet if context is suitable or if there is no context which is needed
+ * to support key-bindings to be assigned since key bindings are not context aware. */
+ if ((C == NULL) || ANIM_keyingset_context_ok_poll(C, ks)) {
item_tmp.identifier = ks->idname;
item_tmp.name = ks->name;
item_tmp.description = ks->description;
diff --git a/source/blender/editors/asset/intern/asset_ops.cc b/source/blender/editors/asset/intern/asset_ops.cc
index 1d484f9ce85..f0768ebc907 100644
--- a/source/blender/editors/asset/intern/asset_ops.cc
+++ b/source/blender/editors/asset/intern/asset_ops.cc
@@ -754,7 +754,7 @@ static int asset_bundle_install_exec(bContext *C, wmOperator *op)
cat_service->prepare_to_merge_on_write();
const int operator_result = WM_operator_name_call(
- C, "WM_OT_save_mainfile", WM_OP_EXEC_DEFAULT, op->ptr);
+ C, "WM_OT_save_mainfile", WM_OP_EXEC_DEFAULT, op->ptr, nullptr);
WM_cursor_wait(false);
if (operator_result != OPERATOR_FINISHED) {
diff --git a/source/blender/editors/curve/editcurve.c b/source/blender/editors/curve/editcurve.c
index a33fbb29f85..2dcddd01670 100644
--- a/source/blender/editors/curve/editcurve.c
+++ b/source/blender/editors/curve/editcurve.c
@@ -4863,6 +4863,12 @@ bool ED_curve_editnurb_select_pick(
BKE_curve_nurb_active_set(cu, nu);
}
+ /* Change active material on object. */
+ if (nu->mat_nr != obedit->actcol - 1) {
+ obedit->actcol = nu->mat_nr + 1;
+ WM_event_add_notifier(C, NC_MATERIAL | ND_SHADING_LINKS, NULL);
+ }
+
if (vc.view_layer->basact != basact) {
ED_object_base_activate(C, basact);
}
@@ -4900,7 +4906,7 @@ bool ed_editnurb_spin(
copy_m3_m4(bmat, obedit->obmat);
invert_m3_m3(imat, bmat);
- axis_angle_to_mat3(cmat, axis, M_PI / 4.0);
+ axis_angle_to_mat3(cmat, axis, M_PI_4);
mul_m3_m3m3(tmat, cmat, bmat);
mul_m3_m3m3(rotmat, imat, tmat);
@@ -4952,7 +4958,7 @@ bool ed_editnurb_spin(
/* It is challenging to create a good approximation of a circle with uniform knots vector
* (which is forced in Blender for cyclic NURBS curves). Here a NURBS circle is constructed
* by connecting four Bezier arcs. */
- nu->flagv |= CU_NURB_CYCLIC | CU_NURB_BEZIER;
+ nu->flagv |= CU_NURB_CYCLIC | CU_NURB_BEZIER | CU_NURB_ENDPOINT;
BKE_nurb_knot_calc_v(nu);
}
}
diff --git a/source/blender/editors/curve/editcurve_add.c b/source/blender/editors/curve/editcurve_add.c
index d7201495f75..ba5a7409ba7 100644
--- a/source/blender/editors/curve/editcurve_add.c
+++ b/source/blender/editors/curve/editcurve_add.c
@@ -292,7 +292,7 @@ Nurb *ED_curve_add_nurbs_primitive(
nu->pntsv = 1;
nu->orderu = 3;
nu->bp = (BPoint *)MEM_callocN(sizeof(BPoint) * nu->pntsu, "addNurbprim6");
- nu->flagu = CU_NURB_CYCLIC | CU_NURB_BEZIER;
+ nu->flagu = CU_NURB_CYCLIC | CU_NURB_BEZIER | CU_NURB_ENDPOINT;
bp = nu->bp;
for (a = 0; a < 8; a++) {
@@ -407,7 +407,7 @@ Nurb *ED_curve_add_nurbs_primitive(
mul_m4_v3(mat, bp->vec);
bp++;
}
- nu->flagu = CU_NURB_BEZIER;
+ nu->flagu = CU_NURB_BEZIER | CU_NURB_ENDPOINT;
BKE_nurb_knot_calc_u(nu);
BLI_addtail(editnurb, nu); /* temporal for spin */
diff --git a/source/blender/editors/gpencil/annotate_paint.c b/source/blender/editors/gpencil/annotate_paint.c
index 1a7b034f2f8..338f6be4c89 100644
--- a/source/blender/editors/gpencil/annotate_paint.c
+++ b/source/blender/editors/gpencil/annotate_paint.c
@@ -22,6 +22,7 @@
#include "PIL_time.h"
+#include "BKE_callbacks.h"
#include "BKE_colortools.h"
#include "BKE_context.h"
#include "BKE_global.h"
@@ -1509,6 +1510,9 @@ static void annotation_paint_initstroke(tGPsdata *p,
Scene *scene = p->scene;
ToolSettings *ts = scene->toolsettings;
+ /* Call to the annotation pre handler to notify python the annotation starts. */
+ BKE_callback_exec_id_depsgraph(p->bmain, &p->gpd->id, p->depsgraph, BKE_CB_EVT_ANNOTATION_PRE);
+
/* get active layer (or add a new one if non-existent) */
p->gpl = BKE_gpencil_layer_active_get(p->gpd);
if (p->gpl == NULL) {
@@ -1675,6 +1679,9 @@ static void annotation_paint_strokeend(tGPsdata *p)
annotation_stroke_newfrombuffer(p);
}
+ /* Call to the annotation post handler to notify python the annotation is done. */
+ BKE_callback_exec_id_depsgraph(p->bmain, &p->gpd->id, p->depsgraph, BKE_CB_EVT_ANNOTATION_POST);
+
/* clean up buffer now */
annotation_session_validatebuffer(p);
}
@@ -2477,7 +2484,7 @@ static int annotation_draw_modal(bContext *C, wmOperator *op, const wmEvent *eve
* - Since this operator is non-modal, we can just call it here, and keep going...
* - This operator is especially useful when animating
*/
- WM_operator_name_call(C, "GPENCIL_OT_blank_frame_add", WM_OP_EXEC_DEFAULT, NULL);
+ WM_operator_name_call(C, "GPENCIL_OT_blank_frame_add", WM_OP_EXEC_DEFAULT, NULL, event);
estate = OPERATOR_RUNNING_MODAL;
}
else {
diff --git a/source/blender/editors/gpencil/gpencil_edit.c b/source/blender/editors/gpencil/gpencil_edit.c
index d734fb2678e..8506e90191f 100644
--- a/source/blender/editors/gpencil/gpencil_edit.c
+++ b/source/blender/editors/gpencil/gpencil_edit.c
@@ -1928,7 +1928,7 @@ static int gpencil_blank_frame_add_exec(bContext *C, wmOperator *op)
if (ELEM(NULL, gpd, active_gpl)) {
/* Let's just be lazy, and call the "Add New Layer" operator,
* which sets everything up as required. */
- WM_operator_name_call(C, "GPENCIL_OT_layer_add", WM_OP_EXEC_DEFAULT, NULL);
+ WM_operator_name_call(C, "GPENCIL_OT_layer_add", WM_OP_EXEC_DEFAULT, NULL, NULL);
}
/* Go through each layer, adding a frame after the active one
@@ -5430,9 +5430,10 @@ static int gpencil_stroke_normalize_exec(bContext *C, wmOperator *op)
if (ED_gpencil_stroke_can_use(C, gps) == false) {
continue;
}
-
- bool selected = (is_curve_edit) ? gps->editcurve->flag |= GP_CURVE_SELECT :
- (gps->flag & GP_STROKE_SELECT);
+ bool is_curve_ready = (gps->editcurve != NULL);
+ bool selected = (is_curve_edit && is_curve_ready) ?
+ (gps->editcurve->flag & GP_CURVE_SELECT) :
+ (gps->flag & GP_STROKE_SELECT);
if (!selected) {
continue;
}
@@ -5445,7 +5446,7 @@ static int gpencil_stroke_normalize_exec(bContext *C, wmOperator *op)
}
/* Loop all Polyline points. */
- if (!is_curve_edit) {
+ if (!is_curve_edit || !is_curve_ready) {
for (int i = 0; i < gps->totpoints; i++) {
bGPDspoint *pt = &gps->points[i];
if (mode == GP_NORMALIZE_THICKNESS) {
diff --git a/source/blender/editors/gpencil/gpencil_vertex_ops.c b/source/blender/editors/gpencil/gpencil_vertex_ops.c
index f49523925bc..c0888968a2d 100644
--- a/source/blender/editors/gpencil/gpencil_vertex_ops.c
+++ b/source/blender/editors/gpencil/gpencil_vertex_ops.c
@@ -959,7 +959,7 @@ static int gpencil_material_to_vertex_exec(bContext *C, wmOperator *op)
/* Clean unused materials. */
if (remove) {
WM_operator_name_call(
- C, "OBJECT_OT_material_slot_remove_unused", WM_OP_INVOKE_REGION_WIN, NULL);
+ C, "OBJECT_OT_material_slot_remove_unused", WM_OP_INVOKE_REGION_WIN, NULL, NULL);
}
return OPERATOR_FINISHED;
diff --git a/source/blender/editors/include/ED_anim_api.h b/source/blender/editors/include/ED_anim_api.h
index 4b6f5e4cac6..4cae8bdab18 100644
--- a/source/blender/editors/include/ED_anim_api.h
+++ b/source/blender/editors/include/ED_anim_api.h
@@ -51,8 +51,9 @@ struct PropertyRNA;
/** \name Context
* \{ */
-/* This struct defines a structure used for animation-specific
- * 'context' information
+/**
+ * This struct defines a structure used for animation-specific
+ * 'context' information.
*/
typedef struct bAnimContext {
/** data to be filtered for use in animation editor */
@@ -118,8 +119,9 @@ typedef enum eAnimCont_Types {
/** \name Channels
* \{ */
-/* This struct defines a structure used for quick and uniform access for
- * channels of animation data
+/**
+ * This struct defines a structure used for quick and uniform access for
+ * channels of animation data.
*/
typedef struct bAnimListElem {
struct bAnimListElem *next, *prev;
@@ -257,7 +259,8 @@ typedef enum eAnim_KeyType {
ALE_GROUP, /* Action Group summary */
} eAnim_KeyType;
-/* Flags for specifying the types of updates (i.e. recalculation/refreshing) that
+/**
+ * Flags for specifying the types of updates (i.e. recalculation/refreshing) that
* needs to be performed to the data contained in a channel following editing.
* For use with ANIM_animdata_update()
*/
@@ -379,13 +382,13 @@ typedef enum eAnimFilter_Flags {
#define EXPANDED_DRVD(adt) ((adt->flag & ADT_DRIVERS_COLLAPSED) == 0)
/* Actions (also used for Dopesheet) */
-/* Action Channel Group */
+/** Action Channel Group. */
#define EDITABLE_AGRP(agrp) (((agrp)->flag & AGRP_PROTECTED) == 0)
#define EXPANDED_AGRP(ac, agrp) \
(((!(ac) || ((ac)->spacetype != SPACE_GRAPH)) && ((agrp)->flag & AGRP_EXPANDED)) || \
(((ac) && ((ac)->spacetype == SPACE_GRAPH)) && ((agrp)->flag & AGRP_EXPANDED_G)))
#define SEL_AGRP(agrp) (((agrp)->flag & AGRP_SELECTED) || ((agrp)->flag & AGRP_ACTIVE))
-/* F-Curve Channels */
+/** F-Curve Channels. */
#define EDITABLE_FCU(fcu) ((fcu->flag & FCURVE_PROTECTED) == 0)
#define SEL_FCU(fcu) (fcu->flag & FCURVE_SELECTED)
@@ -394,16 +397,16 @@ typedef enum eAnimFilter_Flags {
#define SEL_SHAPEKEY(kb) (kb->flag & KEYBLOCK_SEL)
/* Grease Pencil only */
-/* Grease Pencil datablock settings */
+/** Grease Pencil data-block settings. */
#define EXPANDED_GPD(gpd) (gpd->flag & GP_DATA_EXPAND)
-/* Grease Pencil Layer settings */
+/** Grease Pencil Layer settings. */
#define EDITABLE_GPL(gpl) ((gpl->flag & GP_LAYER_LOCKED) == 0)
#define SEL_GPL(gpl) (gpl->flag & GP_LAYER_SELECT)
/* Mask Only */
-/* Grease Pencil datablock settings */
+/** Grease Pencil data-block settings. */
#define EXPANDED_MASK(mask) (mask->flag & MASK_ANIMF_EXPAND)
-/* Grease Pencil Layer settings */
+/** Grease Pencil Layer settings. */
#define EDITABLE_MASK(masklay) ((masklay->flag & MASK_LAYERFLAG_LOCKED) == 0)
#define SEL_MASKLAY(masklay) (masklay->flag & SELECT)
@@ -426,20 +429,20 @@ typedef enum eAnimFilter_Flags {
/** \name Channel Defines
* \{ */
-/* channel heights */
+/** Channel heights. */
#define ACHANNEL_FIRST_TOP(ac) \
(UI_view2d_scale_get_y(&(ac)->region->v2d) * -UI_TIME_SCRUB_MARGIN_Y - ACHANNEL_SKIP)
#define ACHANNEL_HEIGHT(ac) (0.8f * (ac)->yscale_fac * U.widget_unit)
#define ACHANNEL_SKIP (0.1f * U.widget_unit)
#define ACHANNEL_STEP(ac) (ACHANNEL_HEIGHT(ac) + ACHANNEL_SKIP)
-/* Additional offset to give some room at the end. */
+/** Additional offset to give some room at the end. */
#define ACHANNEL_TOT_HEIGHT(ac, item_amount) \
(-ACHANNEL_FIRST_TOP(ac) + ACHANNEL_STEP(ac) * (item_amount + 1))
-/* channel widths */
+/** Channel widths. */
#define ACHANNEL_NAMEWIDTH (10 * U.widget_unit)
-/* channel toggle-buttons */
+/** Channel toggle-buttons. */
#define ACHANNEL_BUTTON_WIDTH (0.8f * U.widget_unit)
/** \} */
@@ -448,7 +451,7 @@ typedef enum eAnimFilter_Flags {
/** \name NLA Channel Defines
* \{ */
-/* NLA channel heights */
+/** NLA channel heights */
#define NLACHANNEL_FIRST_TOP(ac) \
(UI_view2d_scale_get_y(&(ac)->region->v2d) * -UI_TIME_SCRUB_MARGIN_Y - NLACHANNEL_SKIP)
#define NLACHANNEL_HEIGHT(snla) \
@@ -456,14 +459,14 @@ typedef enum eAnimFilter_Flags {
(1.2f * U.widget_unit))
#define NLACHANNEL_SKIP (0.1f * U.widget_unit)
#define NLACHANNEL_STEP(snla) (NLACHANNEL_HEIGHT(snla) + NLACHANNEL_SKIP)
-/* Additional offset to give some room at the end. */
+/** Additional offset to give some room at the end. */
#define NLACHANNEL_TOT_HEIGHT(ac, item_amount) \
(-NLACHANNEL_FIRST_TOP(ac) + NLACHANNEL_STEP(((SpaceNla *)(ac)->sl)) * (item_amount + 1))
-/* channel widths */
+/** Channel widths */
#define NLACHANNEL_NAMEWIDTH (10 * U.widget_unit)
-/* channel toggle-buttons */
+/** Channel toggle-buttons */
#define NLACHANNEL_BUTTON_WIDTH (0.8f * U.widget_unit)
/** \} */
@@ -521,7 +524,7 @@ void ANIM_animdata_freelist(ListBase *anim_data);
/** \name Drawing TypeInfo
* \{ */
-/* role or level of animchannel in the hierarchy */
+/** Role or level of anim-channel in the hierarchy. */
typedef enum eAnimChannel_Role {
/** datablock expander - a "composite" channel type */
ACHANNEL_ROLE_EXPANDER = -1,
@@ -561,7 +564,7 @@ typedef enum eAnimChannel_Settings {
ACHANNEL_SETTING_ALWAYS_VISIBLE = 8,
} eAnimChannel_Settings;
-/* Drawing, mouse handling, and flag setting behavior... */
+/** Drawing, mouse handling, and flag setting behavior. */
typedef struct bAnimChannelType {
/* -- Type data -- */
/* name of the channel type, for debugging */
@@ -570,30 +573,31 @@ typedef struct bAnimChannelType {
eAnimChannel_Role channel_role;
/* -- Drawing -- */
- /* get RGB color that is used to draw the majority of the backdrop */
+ /** Get RGB color that is used to draw the majority of the backdrop. */
void (*get_backdrop_color)(bAnimContext *ac, bAnimListElem *ale, float r_color[3]);
- /* draw backdrop strip for channel */
+ /** Draw backdrop strip for channel. */
void (*draw_backdrop)(bAnimContext *ac, bAnimListElem *ale, float yminc, float ymaxc);
- /* get depth of indention (relative to the depth channel is nested at) */
+ /** Get depth of indentation (relative to the depth channel is nested at). */
short (*get_indent_level)(bAnimContext *ac, bAnimListElem *ale);
- /* get offset in pixels for the start of the channel (in addition to the indent depth) */
+ /** Get offset in pixels for the start of the channel (in addition to the indent depth). */
short (*get_offset)(bAnimContext *ac, bAnimListElem *ale);
- /* get name (for channel lists) */
+ /** Get name (for channel lists). */
void (*name)(bAnimListElem *ale, char *name);
- /* get RNA property+pointer for editing the name */
+ /** Get RNA property+pointer for editing the name. */
bool (*name_prop)(bAnimListElem *ale, struct PointerRNA *ptr, struct PropertyRNA **prop);
- /* get icon (for channel lists) */
+ /** Get icon (for channel lists). */
int (*icon)(bAnimListElem *ale);
/* -- Settings -- */
- /* check if the given setting is valid in the current context */
+ /** Check if the given setting is valid in the current context. */
bool (*has_setting)(bAnimContext *ac, bAnimListElem *ale, eAnimChannel_Settings setting);
- /* get the flag used for this setting */
+ /** Get the flag used for this setting. */
int (*setting_flag)(bAnimContext *ac, eAnimChannel_Settings setting, bool *neg);
- /* get the pointer to int/short where data is stored,
- * with type being sizeof(ptr_data) which should be fine for runtime use...
- * - assume that setting has been checked to be valid for current context
+ /**
+ * Get the pointer to int/short where data is stored,
+ * with type being `sizeof(ptr_data)` which should be fine for runtime use.
+ * - assume that setting has been checked to be valid for current context.
*/
void *(*setting_ptr)(bAnimListElem *ale, eAnimChannel_Settings setting, short *type);
} bAnimChannelType;
@@ -720,11 +724,11 @@ bool ANIM_remove_empty_action_from_animdata(struct AnimData *adt);
/* flags for Current Frame Drawing */
typedef enum eAnimEditDraw_CurrentFrame {
- /* plain time indicator with no special indicators */
+ /** Plain time indicator with no special indicators. */
/* DRAWCFRA_PLAIN = 0, */ /* UNUSED */
- /* time indication in seconds or frames */
+ /** Time indication in seconds or frames. */
DRAWCFRA_UNIT_SECONDS = (1 << 0),
- /* draw indicator extra wide (for timeline) */
+ /** Draw indicator extra wide (for timeline). */
DRAWCFRA_WIDE = (1 << 1),
} eAnimEditDraw_CurrentFrame;
@@ -784,9 +788,9 @@ struct NlaTrack *ANIM_nla_context_track(const struct bContext *C);
struct NlaStrip *ANIM_nla_context_strip(const struct bContext *C);
struct FCurve *ANIM_graph_context_fcurve(const struct bContext *C);
-/* Needed for abstraction between the graph editor and the NLA editor. */
+/** Needed for abstraction between the graph editor and the NLA editor. */
typedef bool (*PanelTypePollFn)(const struct bContext *C, struct PanelType *pt);
-/* Avoid including "UI_interface.h" here. */
+/** Avoid including `UI_interface.h` here. */
typedef void (*uiListPanelIDFromDataFunc)(void *data_link, char *r_idname);
/**
@@ -912,20 +916,21 @@ void ED_nla_postop_refresh(bAnimContext *ac);
/* anim_draw.c */
-/* flags for conversion mapping */
+/** Flags for conversion mapping. */
typedef enum eAnimUnitConv_Flags {
- /* restore to original internal values */
+ /** Restore to original internal values. */
ANIM_UNITCONV_RESTORE = (1 << 0),
- /* ignore handles (i.e. only touch main keyframes) */
+ /** Ignore handles (i.e. only touch main keyframes). */
ANIM_UNITCONV_ONLYKEYS = (1 << 1),
- /* only touch selected BezTriples */
+ /** Only touch selected BezTriples. */
ANIM_UNITCONV_ONLYSEL = (1 << 2),
- /* only touch selected vertices */
+ /** Only touch selected vertices. */
ANIM_UNITCONV_SELVERTS = (1 << 3),
/* ANIM_UNITCONV_SKIPKNOTS = (1 << 4), */ /* UNUSED */
- /* Scale FCurve i a way it fits to -1..1 space */
+ /** Scale FCurve i a way it fits to -1..1 space. */
ANIM_UNITCONV_NORMALIZE = (1 << 5),
- /* Only when normalization is used: use scale factor from previous run,
+ /**
+ * Only when normalization is used: use scale factor from previous run,
* prevents curves from jumping all over the place when tweaking them.
*/
ANIM_UNITCONV_NORMALIZE_FREEZE = (1 << 6),
@@ -953,10 +958,11 @@ float ANIM_unit_mapping_get_factor(
*/
#define BEZKEYTYPE(bezt) ((bezt)->hide)
-/* set/clear/toggle macro
- * - channel - channel with a 'flag' member that we're setting
- * - smode - 0=clear, 1=set, 2=invert
- * - sflag - bitflag to set
+/**
+ * Set/Clear/Toggle macro.
+ * \param channel: Channel with a 'flag' member that we're setting.
+ * \param smode: 0=clear, 1=set, 2=invert.
+ * \param sflag: bit-flag to set.
*/
#define ACHANNEL_SET_FLAG(channel, smode, sflag) \
{ \
@@ -972,10 +978,11 @@ float ANIM_unit_mapping_get_factor(
} \
((void)0)
-/* set/clear/toggle macro, where the flag is negative
- * - channel - channel with a 'flag' member that we're setting
- * - smode - 0=clear, 1=set, 2=invert
- * - sflag - bitflag to set
+/**
+ * Set/Clear/Toggle macro, where the flag is negative.
+ * \param channel: channel with a 'flag' member that we're setting.
+ * \param smode: 0=clear, 1=set, 2=invert.
+ * \param sflag: Bit-flag to set.
*/
#define ACHANNEL_SET_FLAG_NEG(channel, smode, sflag) \
{ \
@@ -1067,13 +1074,13 @@ void ED_drivers_editor_init(struct bContext *C, struct ScrArea *area);
/* ************************************************ */
typedef enum eAnimvizCalcRange {
- /* Update motion paths at the current frame only. */
+ /** Update motion paths at the current frame only. */
ANIMVIZ_CALC_RANGE_CURRENT_FRAME,
- /* Try to limit updates to a close neighborhood of the current frame. */
+ /** Try to limit updates to a close neighborhood of the current frame. */
ANIMVIZ_CALC_RANGE_CHANGED,
- /* Update an entire range of the motion paths. */
+ /** Update an entire range of the motion paths. */
ANIMVIZ_CALC_RANGE_FULL,
} eAnimvizCalcRange;
diff --git a/source/blender/editors/include/ED_screen_types.h b/source/blender/editors/include/ED_screen_types.h
index 86fb5251ff3..21bb412d072 100644
--- a/source/blender/editors/include/ED_screen_types.h
+++ b/source/blender/editors/include/ED_screen_types.h
@@ -13,7 +13,9 @@ extern "C" {
/* ----------------------------------------------------- */
-/* for animplayer */
+/**
+ * For animation playback operator, stored in #bScreen.animtimer.customdata.
+ */
typedef struct ScreenAnimData {
ARegion *region; /* do not read from this, only for comparing if region exists */
short redraws;
@@ -24,7 +26,7 @@ typedef struct ScreenAnimData {
bool from_anim_edit; /* playback was invoked from animation editor */
} ScreenAnimData;
-/* for animplayer */
+/** #ScreenAnimData.flag */
enum {
/* user-setting - frame range is played backwards */
ANIMPLAY_FLAG_REVERSE = (1 << 0),
diff --git a/source/blender/editors/include/ED_uvedit.h b/source/blender/editors/include/ED_uvedit.h
index cf4d023ccdf..40a57a321d8 100644
--- a/source/blender/editors/include/ED_uvedit.h
+++ b/source/blender/editors/include/ED_uvedit.h
@@ -223,7 +223,7 @@ void uvedit_edge_select_set_noflush(const struct Scene *scene,
* Updates selection state for UVs based on the select mode and sticky mode. Similar to
* #EDBM_selectmode_set.
*/
-void ED_uvedit_selectmode_clean(struct Scene *scene, struct Object *obedit);
+void ED_uvedit_selectmode_clean(const struct Scene *scene, struct Object *obedit);
void ED_uvedit_selectmode_clean_multi(struct bContext *C);
/**
@@ -231,16 +231,16 @@ void ED_uvedit_selectmode_clean_multi(struct bContext *C);
*
* Flushes selections upwards as dictated by the UV select mode.
*/
-void ED_uvedit_selectmode_flush(struct Scene *scene, struct BMEditMesh *em);
+void ED_uvedit_selectmode_flush(const struct Scene *scene, struct BMEditMesh *em);
/**
* Mode independent UV de-selection flush.
*/
-void uvedit_deselect_flush(struct Scene *scene, struct BMEditMesh *em);
+void uvedit_deselect_flush(const struct Scene *scene, struct BMEditMesh *em);
/**
* Mode independent UV selection flush.
*/
-void uvedit_select_flush(struct Scene *scene, struct BMEditMesh *em);
+void uvedit_select_flush(const struct Scene *scene, struct BMEditMesh *em);
bool ED_uvedit_nearest_uv(const struct Scene *scene,
struct Object *obedit,
@@ -254,15 +254,15 @@ bool ED_uvedit_nearest_uv_multi(const struct Scene *scene,
float *dist_sq,
float r_uv[2]);
-struct BMFace **ED_uvedit_selected_faces(struct Scene *scene,
+struct BMFace **ED_uvedit_selected_faces(const struct Scene *scene,
struct BMesh *bm,
int len_max,
int *r_faces_len);
-struct BMLoop **ED_uvedit_selected_edges(struct Scene *scene,
+struct BMLoop **ED_uvedit_selected_edges(const struct Scene *scene,
struct BMesh *bm,
int len_max,
int *r_edges_len);
-struct BMLoop **ED_uvedit_selected_verts(struct Scene *scene,
+struct BMLoop **ED_uvedit_selected_verts(const struct Scene *scene,
struct BMesh *bm,
int len_max,
int *r_verts_len);
diff --git a/source/blender/editors/include/ED_view3d.h b/source/blender/editors/include/ED_view3d.h
index b1435e76eb2..d2ff5637a13 100644
--- a/source/blender/editors/include/ED_view3d.h
+++ b/source/blender/editors/include/ED_view3d.h
@@ -646,7 +646,7 @@ bool ED_view3d_win_to_3d_on_plane_int(const struct ARegion *region,
*
* \param region: The region (used for the window width and height).
* \param xy_delta: 2D difference (in pixels) such as `event->mval[0] - other_x`.
- * \param zfac: The depth result typically calculated by by #ED_view3d_calc_zfac
+ * \param zfac: The depth result typically calculated by #ED_view3d_calc_zfac
* (see it's doc-string for details).
* \param r_out: The resulting world-space delta.
*/
@@ -661,7 +661,7 @@ void ED_view3d_win_to_delta(const struct ARegion *region,
* the origin in this case is close to zero coordinate.
*
* \param region: The region (used for the window width and height).
- * \param mval: The area relative 2d location (such as event->mval converted to floats).
+ * \param mval: The area relative 2d location (such as `event->mval` converted to float).
* \param r_out: The resulting normalized world-space direction vector.
*/
void ED_view3d_win_to_origin(const struct ARegion *region, const float mval[2], float r_out[3]);
@@ -675,7 +675,7 @@ void ED_view3d_win_to_origin(const struct ARegion *region, const float mval[2],
* the mouse cursor as a normalized vector.
*
* \param region: The region (used for the window width and height).
- * \param mval: The area relative 2d location (such as event->mval converted to floats).
+ * \param mval: The area relative 2d location (such as `event->mval` converted to float).
* \param r_out: The resulting normalized world-space direction vector.
*/
void ED_view3d_win_to_vector(const struct ARegion *region, const float mval[2], float r_out[3]);
diff --git a/source/blender/editors/interface/interface_anim.c b/source/blender/editors/interface/interface_anim.c
index 46baf3033ff..e838ce37d8e 100644
--- a/source/blender/editors/interface/interface_anim.c
+++ b/source/blender/editors/interface/interface_anim.c
@@ -299,13 +299,13 @@ void ui_but_anim_autokey(bContext *C, uiBut *but, Scene *scene, float cfra)
void ui_but_anim_copy_driver(bContext *C)
{
/* this operator calls UI_context_active_but_prop_get */
- WM_operator_name_call(C, "ANIM_OT_copy_driver_button", WM_OP_INVOKE_DEFAULT, NULL);
+ WM_operator_name_call(C, "ANIM_OT_copy_driver_button", WM_OP_INVOKE_DEFAULT, NULL, NULL);
}
void ui_but_anim_paste_driver(bContext *C)
{
/* this operator calls UI_context_active_but_prop_get */
- WM_operator_name_call(C, "ANIM_OT_paste_driver_button", WM_OP_INVOKE_DEFAULT, NULL);
+ WM_operator_name_call(C, "ANIM_OT_paste_driver_button", WM_OP_INVOKE_DEFAULT, NULL, NULL);
}
void ui_but_anim_decorate_cb(bContext *C, void *arg_but, void *UNUSED(arg_dummy))
@@ -331,7 +331,7 @@ void ui_but_anim_decorate_cb(bContext *C, void *arg_but, void *UNUSED(arg_dummy)
wmOperatorType *ot = WM_operatortype_find("ANIM_OT_keyframe_delete_button", false);
WM_operator_properties_create_ptr(&props_ptr, ot);
RNA_boolean_set(&props_ptr, "all", but_anim->rnaindex == -1);
- WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &props_ptr);
+ WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &props_ptr, NULL);
WM_operator_properties_free(&props_ptr);
}
else {
@@ -339,7 +339,7 @@ void ui_but_anim_decorate_cb(bContext *C, void *arg_but, void *UNUSED(arg_dummy)
wmOperatorType *ot = WM_operatortype_find("ANIM_OT_keyframe_insert_button", false);
WM_operator_properties_create_ptr(&props_ptr, ot);
RNA_boolean_set(&props_ptr, "all", but_anim->rnaindex == -1);
- WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &props_ptr);
+ WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &props_ptr, NULL);
WM_operator_properties_free(&props_ptr);
}
diff --git a/source/blender/editors/interface/interface_context_menu.c b/source/blender/editors/interface/interface_context_menu.c
index 07efcdcbe38..4d30d6731a2 100644
--- a/source/blender/editors/interface/interface_context_menu.c
+++ b/source/blender/editors/interface/interface_context_menu.c
@@ -1036,7 +1036,7 @@ bool ui_popup_context_menu_for_button(bContext *C, uiBut *but, const wmEvent *ev
/* We do have a shortcut, but only keyboard ones are editable that way... */
if (kmi) {
- if (ISKEYBOARD(kmi->type)) {
+ if (ISKEYBOARD(kmi->type) || ISNDOF_BUTTON(kmi->type)) {
#if 0 /* would rather use a block but, but gets weirdly positioned... */
uiDefBlockBut(block,
menu_change_shortcut,
diff --git a/source/blender/editors/interface/interface_draw.c b/source/blender/editors/interface/interface_draw.c
index 9a51aa5cb9d..decd8c03d70 100644
--- a/source/blender/editors/interface/interface_draw.c
+++ b/source/blender/editors/interface/interface_draw.c
@@ -411,6 +411,8 @@ static void histogram_draw_one(float r,
immVertex2f(pos_attr, x2, y + (data[i] * h));
}
immEnd();
+
+ GPU_line_width(1.0f);
}
else {
/* under the curve */
diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c
index 8262be163b7..a8b21bebb2b 100644
--- a/source/blender/editors/interface/interface_handlers.c
+++ b/source/blender/editors/interface/interface_handlers.c
@@ -1007,7 +1007,7 @@ static void ui_apply_but_funcs_after(bContext *C)
if (after.optype) {
WM_operator_name_call_ptr_with_depends_on_cursor(
- C, after.optype, after.opcontext, (after.opptr) ? &opptr : NULL, after.drawstr);
+ C, after.optype, after.opcontext, (after.opptr) ? &opptr : NULL, NULL, after.drawstr);
}
if (after.opptr) {
@@ -3930,7 +3930,7 @@ static void ui_do_but_textedit(
}
#ifdef WITH_INPUT_IME
- if (event->type == WM_IME_COMPOSITE_START || event->type == WM_IME_COMPOSITE_EVENT) {
+ if (ELEM(event->type, WM_IME_COMPOSITE_START, WM_IME_COMPOSITE_EVENT)) {
changed = true;
if (event->type == WM_IME_COMPOSITE_START && but->selend > but->selsta) {
@@ -4190,6 +4190,7 @@ static void ui_but_extra_operator_icon_apply(bContext *C, uiBut *but, uiButExtra
op_icon->optype_params->optype,
op_icon->optype_params->opcontext,
op_icon->optype_params->opptr,
+ NULL,
NULL);
/* Force recreation of extra operator icons (pseudo update). */
@@ -9394,7 +9395,9 @@ static int ui_list_activate_hovered_row(bContext *C,
}
}
- const int *mouse_xy = (event->val == KM_CLICK_DRAG) ? event->prev_click_xy : event->xy;
+ int mouse_xy[2];
+ WM_event_drag_start_xy(event, mouse_xy);
+
uiBut *listrow = ui_list_row_find_mouse_over(region, mouse_xy);
if (listrow) {
wmOperatorType *custom_activate_optype = ui_list->dyn_data->custom_activate_optype;
@@ -9421,7 +9424,9 @@ static bool ui_list_is_hovering_draggable_but(bContext *C,
const wmEvent *event)
{
/* On a tweak event, uses the coordinates from where tweaking was started. */
- const int *mouse_xy = (event->val == KM_CLICK_DRAG) ? event->prev_click_xy : event->xy;
+ int mouse_xy[2];
+ WM_event_drag_start_xy(event, mouse_xy);
+
const uiBut *hovered_but = ui_but_find_mouse_over_ex(region, mouse_xy, false, NULL, NULL);
if (list->dyn_data->custom_drag_optype) {
diff --git a/source/blender/editors/interface/interface_ops.c b/source/blender/editors/interface/interface_ops.c
index 0722584c7d8..1d1bb85bd36 100644
--- a/source/blender/editors/interface/interface_ops.c
+++ b/source/blender/editors/interface/interface_ops.c
@@ -1673,7 +1673,7 @@ static int edittranslation_exec(bContext *C, wmOperator *op)
RNA_string_set(&ptr, "rna_prop", rna_prop.strinfo);
RNA_string_set(&ptr, "rna_enum", rna_enum.strinfo);
RNA_string_set(&ptr, "rna_ctxt", rna_ctxt.strinfo);
- const int ret = WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &ptr);
+ const int ret = WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &ptr, NULL);
/* Clean up */
if (but_label.strinfo) {
diff --git a/source/blender/editors/interface/interface_region_popup.c b/source/blender/editors/interface/interface_region_popup.c
index c37d8ec7a2b..2f2556225b5 100644
--- a/source/blender/editors/interface/interface_region_popup.c
+++ b/source/blender/editors/interface/interface_region_popup.c
@@ -557,6 +557,7 @@ uiBlock *ui_popup_block_refresh(bContext *C,
#ifdef DEBUG
wmEvent *event_back = window->eventstate;
+ wmEvent *event_last_back = window->event_last_handled;
#endif
/* create ui block */
@@ -740,6 +741,7 @@ uiBlock *ui_popup_block_refresh(bContext *C,
#ifdef DEBUG
window->eventstate = event_back;
+ window->event_last_handled = event_last_back;
#endif
return block;
diff --git a/source/blender/editors/interface/interface_template_search_menu.cc b/source/blender/editors/interface/interface_template_search_menu.cc
index 160cc909036..8e4b2baed53 100644
--- a/source/blender/editors/interface/interface_template_search_menu.cc
+++ b/source/blender/editors/interface/interface_template_search_menu.cc
@@ -951,7 +951,7 @@ static void menu_search_exec_fn(bContext *C, void *UNUSED(arg1), void *arg2)
case MenuSearch_Item::Type::Operator: {
CTX_store_set(C, item->op.context);
WM_operator_name_call_ptr_with_depends_on_cursor(
- C, item->op.type, item->op.opcontext, item->op.opptr, item->drawstr);
+ C, item->op.type, item->op.opcontext, item->op.opptr, nullptr, item->drawstr);
CTX_store_set(C, nullptr);
break;
}
diff --git a/source/blender/editors/interface/interface_template_search_operator.c b/source/blender/editors/interface/interface_template_search_operator.c
index 4783a3f2ac6..41de2ab197d 100644
--- a/source/blender/editors/interface/interface_template_search_operator.c
+++ b/source/blender/editors/interface/interface_template_search_operator.c
@@ -38,7 +38,7 @@ static void operator_search_exec_fn(bContext *C, void *UNUSED(arg1), void *arg2)
wmOperatorType *ot = arg2;
if (ot) {
- WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, NULL);
+ WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, NULL, NULL);
}
}
diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c
index 801477bb28a..9d19eb9ba9c 100644
--- a/source/blender/editors/interface/interface_templates.c
+++ b/source/blender/editors/interface/interface_templates.c
@@ -686,7 +686,7 @@ static void template_id_cb(bContext *C, void *arg_litem, void *arg_event)
idptr = RNA_property_pointer_get(&template_ui->ptr, template_ui->prop);
RNA_property_pointer_set(&template_ui->ptr, template_ui->prop, idptr, NULL);
RNA_property_update(C, &template_ui->ptr, template_ui->prop);
- undo_push_label = "Override Data-Block";
+ undo_push_label = "Make Local";
}
break;
case UI_ID_ALONE:
@@ -1004,7 +1004,7 @@ static void template_ID(const bContext *C,
UI_but_flag_enable(but, UI_BUT_REDALERT);
}
- if (id->lib) {
+ if (ID_IS_LINKED(id)) {
if (id->tag & LIB_TAG_INDIRECT) {
but = uiDefIconBut(block,
UI_BTYPE_BUT,
@@ -2013,7 +2013,7 @@ static void constraint_reorder(bContext *C, Panel *panel, int new_index)
RNA_int_set(&props_ptr, "index", new_index);
/* Set owner to #EDIT_CONSTRAINT_OWNER_OBJECT or #EDIT_CONSTRAINT_OWNER_BONE. */
RNA_enum_set(&props_ptr, "owner", constraint_from_bone ? 1 : 0);
- WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &props_ptr);
+ WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &props_ptr, NULL);
WM_operator_properties_free(&props_ptr);
}
@@ -5653,7 +5653,7 @@ static void do_running_jobs(bContext *C, void *UNUSED(arg), int event)
WM_jobs_stop(CTX_wm_manager(C), CTX_wm_screen(C), NULL);
break;
case B_STOPANIM:
- WM_operator_name_call(C, "SCREEN_OT_animation_play", WM_OP_INVOKE_SCREEN, NULL);
+ WM_operator_name_call(C, "SCREEN_OT_animation_play", WM_OP_INVOKE_SCREEN, NULL, NULL);
break;
case B_STOPCOMPO:
WM_jobs_stop(CTX_wm_manager(C), CTX_data_scene(C), NULL);
diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c
index d1f3843c643..35cf952b5ce 100644
--- a/source/blender/editors/interface/interface_widgets.c
+++ b/source/blender/editors/interface/interface_widgets.c
@@ -3319,6 +3319,8 @@ static void ui_draw_separator(const rcti *rect, const uiWidgetColors *wcol)
/** \name Button Draw Callbacks
* \{ */
+#define NUM_BUT_PADDING_FACTOR 0.425f
+
static void widget_numbut_draw(
uiWidgetColors *wcol, rcti *rect, const float zoom, int state, int roundboxalign, bool emboss)
{
@@ -3413,11 +3415,10 @@ static void widget_numbut_draw(
}
if (!(state & UI_STATE_TEXT_INPUT)) {
- const float textofs = 0.425f * BLI_rcti_size_y(rect);
+ const float text_padding = NUM_BUT_PADDING_FACTOR * BLI_rcti_size_y(rect);
- /* text space */
- rect->xmin += textofs;
- rect->xmax -= textofs;
+ rect->xmin += text_padding;
+ rect->xmax -= text_padding;
}
}
@@ -3745,7 +3746,6 @@ static void widget_numslider(
/* Backdrop first. */
const float ofs = widget_radius_from_zoom(zoom, wcol);
- const float toffs = ofs * 0.75f;
round_box_edges(&wtb, roundboxalign, rect, ofs);
wtb.draw_outline = false;
@@ -3838,8 +3838,9 @@ static void widget_numslider(
/* Add space at either side of the button so text aligns with number-buttons
* (which have arrow icons). */
if (!(state & UI_STATE_TEXT_INPUT)) {
- rect->xmax -= toffs;
- rect->xmin += toffs;
+ const float text_padding = NUM_BUT_PADDING_FACTOR * BLI_rcti_size_y(rect);
+ rect->xmax -= text_padding;
+ rect->xmin += text_padding;
}
}
diff --git a/source/blender/editors/interface/view2d_ops.c b/source/blender/editors/interface/view2d_ops.c
index 28a025ee581..0b4d00a7def 100644
--- a/source/blender/editors/interface/view2d_ops.c
+++ b/source/blender/editors/interface/view2d_ops.c
@@ -270,7 +270,7 @@ static int view_pan_modal(bContext *C, wmOperator *op, const wmEvent *event)
view_pan_exit(op);
WM_cursor_modal_restore(CTX_wm_window(C));
- WM_operator_name_call(C, "VIEW2D_OT_zoom", WM_OP_INVOKE_DEFAULT, NULL);
+ WM_operator_name_call(C, "VIEW2D_OT_zoom", WM_OP_INVOKE_DEFAULT, NULL, event);
return OPERATOR_FINISHED;
}
#endif
diff --git a/source/blender/editors/mask/mask_edit.c b/source/blender/editors/mask/mask_edit.c
index 819ffd96b1c..b2d49bcc642 100644
--- a/source/blender/editors/mask/mask_edit.c
+++ b/source/blender/editors/mask/mask_edit.c
@@ -111,7 +111,7 @@ void ED_operatortypes_mask(void)
WM_operatortype_append(MASK_OT_parent_set);
WM_operatortype_append(MASK_OT_parent_clear);
- /* shapekeys */
+ /* Shape-keys. */
WM_operatortype_append(MASK_OT_shape_key_insert);
WM_operatortype_append(MASK_OT_shape_key_clear);
WM_operatortype_append(MASK_OT_shape_key_feather_reset);
diff --git a/source/blender/editors/mask/mask_editaction.c b/source/blender/editors/mask/mask_editaction.c
index 8bb6e8a71db..8a23a53a5d2 100644
--- a/source/blender/editors/mask/mask_editaction.c
+++ b/source/blender/editors/mask/mask_editaction.c
@@ -30,8 +30,8 @@
/* ***************************************** */
/* NOTE ABOUT THIS FILE:
* This file contains code for editing Mask data in the Action Editor
- * as a 'keyframes', so that a user can adjust the timing of Mask shapekeys.
- * Therefore, this file mostly contains functions for selecting Mask frames (shapekeys).
+ * as a 'keyframes', so that a user can adjust the timing of Mask shape-keys.
+ * Therefore, this file mostly contains functions for selecting Mask frames (shape-keys).
*/
/* ***************************************** */
/* Generics - Loopers */
diff --git a/source/blender/editors/mesh/editmesh_extrude_spin_gizmo.c b/source/blender/editors/mesh/editmesh_extrude_spin_gizmo.c
index 8d75e2aaf37..687f06c8dcf 100644
--- a/source/blender/editors/mesh/editmesh_extrude_spin_gizmo.c
+++ b/source/blender/editors/mesh/editmesh_extrude_spin_gizmo.c
@@ -44,7 +44,7 @@
# include "BKE_editmesh.h"
#endif
-static const float dial_angle_partial = M_PI / 2;
+static const float dial_angle_partial = M_PI_2;
static const float dial_angle_partial_margin = 0.92f;
#define ORTHO_AXIS_OFFSET 2
diff --git a/source/blender/editors/mesh/editmesh_rip.c b/source/blender/editors/mesh/editmesh_rip.c
index a8d62d90698..6b4edea498e 100644
--- a/source/blender/editors/mesh/editmesh_rip.c
+++ b/source/blender/editors/mesh/editmesh_rip.c
@@ -1017,7 +1017,7 @@ static int edbm_rip_invoke(bContext *C, wmOperator *op, const wmEvent *event)
if (bm->totfacesel) {
/* highly nifty but hard to support since the operator can fail and we're left
* with modified selection */
- // WM_operator_name_call(C, "MESH_OT_region_to_loop", WM_OP_INVOKE_DEFAULT, NULL);
+ // WM_operator_name_call(C, "MESH_OT_region_to_loop", WM_OP_INVOKE_DEFAULT, NULL, event);
continue;
}
error_face_selected = false;
diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c
index 2577218d6a9..6b3f50549ef 100644
--- a/source/blender/editors/mesh/editmesh_tools.c
+++ b/source/blender/editors/mesh/editmesh_tools.c
@@ -4349,7 +4349,7 @@ static Base *mesh_separate_tagged(
Base *base_new = ED_object_add_duplicate(bmain, scene, view_layer, base_old, dupflag);
/* normally would call directly after but in this case delay recalc */
- /* DAG_relations_tag_update(bmain); */
+ // DAG_relations_tag_update(bmain);
/* new in 2.5 */
BKE_object_material_array_assign(bmain,
@@ -4423,7 +4423,7 @@ static Base *mesh_separate_arrays(Main *bmain,
Base *base_new = ED_object_add_duplicate(bmain, scene, view_layer, base_old, dupflag);
/* normally would call directly after but in this case delay recalc */
- /* DAG_relations_tag_update(bmain); */
+ // DAG_relations_tag_update(bmain);
/* new in 2.5 */
BKE_object_material_array_assign(bmain,
diff --git a/source/blender/editors/mesh/editmesh_undo.c b/source/blender/editors/mesh/editmesh_undo.c
index 97f67060c82..9c7d712a739 100644
--- a/source/blender/editors/mesh/editmesh_undo.c
+++ b/source/blender/editors/mesh/editmesh_undo.c
@@ -591,7 +591,8 @@ static void *undomesh_from_editmesh(UndoMesh *um, BMEditMesh *em, Key *key, Undo
um->me.key = NULL;
}
- /* BM_mesh_validate(em->bm); */ /* for troubleshooting */
+ /* Uncomment for troubleshooting. */
+ // BM_mesh_validate(em->bm);
BM_mesh_bm_to_me(
NULL,
@@ -602,6 +603,7 @@ static void *undomesh_from_editmesh(UndoMesh *um, BMEditMesh *em, Key *key, Undo
.calc_object_remap = false,
.update_shapekey_indices = false,
.cd_mask_extra = {.vmask = CD_MASK_SHAPE_KEYINDEX},
+ .active_shapekey_to_mvert = true,
}));
um->selectmode = em->selectmode;
diff --git a/source/blender/editors/mesh/meshtools.c b/source/blender/editors/mesh/meshtools.c
index f3782c17845..d57471b658c 100644
--- a/source/blender/editors/mesh/meshtools.c
+++ b/source/blender/editors/mesh/meshtools.c
@@ -137,22 +137,22 @@ static void join_mesh_single(Depsgraph *depsgraph,
mul_m4_v3(cmat, mvert->co);
}
- /* For each shapekey in destination mesh:
+ /* For each shape-key in destination mesh:
* - if there's a matching one, copy it across
* (will need to transform vertices into new space...).
* - otherwise, just copy own coordinates of mesh
* (no need to transform vertex coordinates into new space).
*/
if (key) {
- /* if this mesh has any shapekeys, check first, otherwise just copy coordinates */
+ /* if this mesh has any shape-keys, check first, otherwise just copy coordinates */
LISTBASE_FOREACH (KeyBlock *, kb, &key->block) {
- /* get pointer to where to write data for this mesh in shapekey's data array */
+ /* get pointer to where to write data for this mesh in shape-key's data array */
float(*cos)[3] = ((float(*)[3])kb->data) + *vertofs;
- /* check if this mesh has such a shapekey */
+ /* Check if this mesh has such a shape-key. */
KeyBlock *okb = me->key ? BKE_keyblock_find_name(me->key, kb->name) : NULL;
if (okb) {
- /* copy this mesh's shapekey to the destination shapekey
+ /* copy this mesh's shape-key to the destination shape-key
* (need to transform first) */
float(*ocos)[3] = okb->data;
for (a = 0; a < me->totvert; a++, cos++, ocos++) {
@@ -161,7 +161,7 @@ static void join_mesh_single(Depsgraph *depsgraph,
}
}
else {
- /* copy this mesh's vertex coordinates to the destination shapekey */
+ /* Copy this mesh's vertex coordinates to the destination shape-key. */
for (a = 0, mvert = *mvert_pp; a < me->totvert; a++, cos++, mvert++) {
copy_v3_v3(*cos, mvert->co);
}
@@ -170,26 +170,26 @@ static void join_mesh_single(Depsgraph *depsgraph,
}
}
else {
- /* for each shapekey in destination mesh:
+ /* for each shape-key in destination mesh:
* - if it was an 'original', copy the appropriate data from nkey
* - otherwise, copy across plain coordinates (no need to transform coordinates)
*/
if (key) {
LISTBASE_FOREACH (KeyBlock *, kb, &key->block) {
- /* get pointer to where to write data for this mesh in shapekey's data array */
+ /* get pointer to where to write data for this mesh in shape-key's data array */
float(*cos)[3] = ((float(*)[3])kb->data) + *vertofs;
- /* check if this was one of the original shapekeys */
+ /* Check if this was one of the original shape-keys. */
KeyBlock *okb = nkey ? BKE_keyblock_find_name(nkey, kb->name) : NULL;
if (okb) {
- /* copy this mesh's shapekey to the destination shapekey */
+ /* copy this mesh's shape-key to the destination shape-key */
float(*ocos)[3] = okb->data;
for (a = 0; a < me->totvert; a++, cos++, ocos++) {
copy_v3_v3(*cos, *ocos);
}
}
else {
- /* copy base-coordinates to the destination shapekey */
+ /* Copy base-coordinates to the destination shape-key. */
for (a = 0, mvert = *mvert_pp; a < me->totvert; a++, cos++, mvert++) {
copy_v3_v3(*cos, mvert->co);
}
@@ -365,7 +365,7 @@ int ED_mesh_join_objects_exec(bContext *C, wmOperator *op)
join_parent = true;
}
- /* check for shapekeys */
+ /* Check for shape-keys. */
if (me->key) {
haskey++;
}
@@ -428,10 +428,10 @@ int ED_mesh_join_objects_exec(bContext *C, wmOperator *op)
/* increase id->us : will be lowered later */
}
- /* - if destination mesh had shapekeys, move them somewhere safe, and set up placeholders
- * with arrays that are large enough to hold shapekey data for all meshes
- * - if destination mesh didn't have shapekeys, but we encountered some in the meshes we're
- * joining, set up a new keyblock and assign to the mesh
+ /* - If destination mesh had shape-keys, move them somewhere safe, and set up placeholders
+ * with arrays that are large enough to hold shape-key data for all meshes.
+ * - If destination mesh didn't have shape-keys, but we encountered some in the meshes we're
+ * joining, set up a new key-block and assign to the mesh.
*/
if (key) {
/* make a duplicate copy that will only be used here... (must remember to free it!) */
@@ -518,8 +518,8 @@ int ED_mesh_join_objects_exec(bContext *C, wmOperator *op)
}
}
- /* if this mesh has shapekeys,
- * check if destination mesh already has matching entries too */
+ /* If this mesh has shape-keys,
+ * check if destination mesh already has matching entries too. */
if (me->key && key) {
/* for remapping KeyBlock.relative */
int *index_map = MEM_mallocN(sizeof(int) * me->key->totkey, __func__);
@@ -713,7 +713,7 @@ int ED_mesh_join_objects_exec(bContext *C, wmOperator *op)
/* other mesh users */
BKE_objects_materials_test_all(bmain, (ID *)me);
- /* free temp copy of destination shapekeys (if applicable) */
+ /* Free temporary copy of destination shape-keys (if applicable). */
if (nkey) {
/* We can assume nobody is using that ID currently. */
BKE_id_free_ex(bmain, nkey, LIB_ID_FREE_NO_UI_USER, false);
diff --git a/source/blender/editors/object/object_add.cc b/source/blender/editors/object/object_add.cc
index 7befad3b8d7..b8ffaf87118 100644
--- a/source/blender/editors/object/object_add.cc
+++ b/source/blender/editors/object/object_add.cc
@@ -3385,7 +3385,8 @@ Base *ED_object_add_duplicate(
const int remap_flag = BKE_object_is_in_editmode(ob) ? ID_REMAP_FORCE_OBDATA_IN_EDITMODE : 0;
BKE_libblock_relink_to_newid(bmain, &ob->id, remap_flag);
- /* DAG_relations_tag_update(bmain); */ /* caller must do */
+ /* Correct but the caller must do this. */
+ // DAG_relations_tag_update(bmain);
if (ob->data != nullptr) {
DEG_id_tag_update_ex(bmain, (ID *)ob->data, ID_RECALC_EDITORS);
diff --git a/source/blender/editors/object/object_modes.c b/source/blender/editors/object/object_modes.c
index 8e9e8558016..cc6aa34d39d 100644
--- a/source/blender/editors/object/object_modes.c
+++ b/source/blender/editors/object/object_modes.c
@@ -158,7 +158,7 @@ bool ED_object_mode_compat_set(bContext *C, Object *ob, eObjectMode mode, Report
if (!ELEM(ob->mode, mode, OB_MODE_OBJECT)) {
const char *opstring = object_mode_op_string(ob->mode);
- WM_operator_name_call(C, opstring, WM_OP_EXEC_REGION_WIN, NULL);
+ WM_operator_name_call(C, opstring, WM_OP_EXEC_REGION_WIN, NULL, NULL);
ok = ELEM(ob->mode, mode, OB_MODE_OBJECT);
if (!ok) {
wmOperatorType *ot = WM_operatortype_find(opstring, false);
@@ -209,7 +209,7 @@ bool ED_object_mode_set_ex(bContext *C, eObjectMode mode, bool use_undo, ReportL
if (!use_undo) {
wm->op_undo_depth++;
}
- WM_operator_name_call_ptr(C, ot, WM_OP_EXEC_REGION_WIN, NULL);
+ WM_operator_name_call_ptr(C, ot, WM_OP_EXEC_REGION_WIN, NULL, NULL);
if (!use_undo) {
wm->op_undo_depth--;
}
diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c
index ee3bc3cba76..9343f4a3b34 100644
--- a/source/blender/editors/screen/screen_ops.c
+++ b/source/blender/editors/screen/screen_ops.c
@@ -1421,7 +1421,7 @@ static int area_dupli_invoke(bContext *C, wmOperator *op, const wmEvent *event)
area->winy,
SPACE_EMPTY,
false,
- true,
+ false,
false,
WIN_ALIGN_ABSOLUTE);
diff --git a/source/blender/editors/sculpt_paint/curves_sculpt_ops.cc b/source/blender/editors/sculpt_paint/curves_sculpt_ops.cc
index 12c03804981..47bf7a28352 100644
--- a/source/blender/editors/sculpt_paint/curves_sculpt_ops.cc
+++ b/source/blender/editors/sculpt_paint/curves_sculpt_ops.cc
@@ -7,10 +7,12 @@
#include "BKE_bvhutils.h"
#include "BKE_context.h"
#include "BKE_curves.hh"
+#include "BKE_geometry_set.hh"
#include "BKE_lib_id.h"
#include "BKE_mesh.h"
#include "BKE_mesh_runtime.h"
#include "BKE_paint.h"
+#include "BKE_spline.hh"
#include "WM_api.h"
#include "WM_toolsystem.h"
@@ -66,6 +68,7 @@ bool CURVES_SCULPT_mode_poll_view3d(bContext *C)
namespace blender::ed::sculpt_paint {
using blender::bke::CurvesGeometry;
+using blender::fn::CPPType;
/* -------------------------------------------------------------------- */
/** \name * SCULPT_CURVES_OT_brush_stroke
@@ -133,14 +136,7 @@ class DeleteOperation : public CurvesSculptStrokeOperation {
return false;
});
- /* Just reset positions instead of actually removing the curves. This is just a prototype. */
- threading::parallel_for(curves_to_remove.index_range(), 512, [&](const IndexRange range) {
- for (const int curve_i : curves_to_remove.slice(range)) {
- for (const int point_i : curves.range_for_curve(curve_i)) {
- positions[point_i] = {0.0f, 0.0f, 0.0f};
- }
- }
- });
+ curves.remove_curves(curves_to_remove);
curves.tag_positions_changed();
DEG_id_tag_update(&curves_id.id, ID_RECALC_GEOMETRY);
@@ -150,15 +146,22 @@ class DeleteOperation : public CurvesSculptStrokeOperation {
}
};
-class MoveOperation : public CurvesSculptStrokeOperation {
+/**
+ * Moves individual points under the brush and does a length preservation step afterwards.
+ */
+class CombOperation : public CurvesSculptStrokeOperation {
private:
- Vector<int64_t> points_to_move_indices_;
- IndexMask points_to_move_;
float2 last_mouse_position_;
public:
void on_stroke_extended(bContext *C, const StrokeExtension &stroke_extension) override
{
+ BLI_SCOPED_DEFER([&]() { last_mouse_position_ = stroke_extension.mouse_position; });
+
+ if (stroke_extension.is_first) {
+ return;
+ }
+
Scene &scene = *CTX_data_scene(C);
Object &object = *CTX_data_active_object(C);
ARegion *region = CTX_wm_region(C);
@@ -168,6 +171,10 @@ class MoveOperation : public CurvesSculptStrokeOperation {
CurvesSculpt &curves_sculpt = *scene.toolsettings->curves_sculpt;
Brush &brush = *BKE_paint_brush(&curves_sculpt.paint);
const float brush_radius = BKE_brush_size_get(&scene, &brush);
+ const float brush_strength = BKE_brush_alpha_get(&scene, &brush);
+
+ const float4x4 ob_mat = object.obmat;
+ const float4x4 ob_imat = ob_mat.inverted();
float4x4 projection;
ED_view3d_ob_project_mat_get(rv3d, &object, projection.values);
@@ -176,39 +183,312 @@ class MoveOperation : public CurvesSculptStrokeOperation {
CurvesGeometry &curves = CurvesGeometry::wrap(curves_id.geometry);
MutableSpan<float3> positions = curves.positions();
- if (stroke_extension.is_first) {
- /* Find point indices to move. */
- points_to_move_ = index_mask_ops::find_indices_based_on_predicate(
- curves.points_range(), 512, points_to_move_indices_, [&](const int64_t point_i) {
- const float3 position = positions[point_i];
- float2 screen_position;
- ED_view3d_project_float_v2_m4(region, position, screen_position, projection.values);
- const float distance = len_v2v2(screen_position, stroke_extension.mouse_position);
- return distance <= brush_radius;
- });
- }
- else {
- /* Move points based on mouse movement. */
- const float2 mouse_diff = stroke_extension.mouse_position - last_mouse_position_;
- threading::parallel_for(points_to_move_.index_range(), 512, [&](const IndexRange range) {
- for (const int point_i : points_to_move_.slice(range)) {
+ const float2 mouse_prev = last_mouse_position_;
+ const float2 mouse_cur = stroke_extension.mouse_position;
+ const float2 mouse_diff = mouse_cur - mouse_prev;
+ const float mouse_diff_len = math::length(mouse_diff);
+
+ threading::parallel_for(curves.curves_range(), 256, [&](const IndexRange curves_range) {
+ for (const int curve_i : curves_range) {
+ const IndexRange curve_points = curves.range_for_curve(curve_i);
+ /* Compute lengths of the segments. Those are used to make sure that the lengths don't
+ * change. */
+ Vector<float, 16> segment_lengths(curve_points.size() - 1);
+ for (const int segment_i : IndexRange(curve_points.size() - 1)) {
+ const float3 &p1 = positions[curve_points[segment_i]];
+ const float3 &p2 = positions[curve_points[segment_i] + 1];
+ const float length = math::distance(p1, p2);
+ segment_lengths[segment_i] = length;
+ }
+ bool curve_changed = false;
+ for (const int point_i : curve_points.drop_front(1)) {
const float3 old_position = positions[point_i];
+
+ /* Find the position of the point in screen space. */
float2 old_position_screen;
ED_view3d_project_float_v2_m4(
region, old_position, old_position_screen, projection.values);
- const float2 new_position_screen = old_position_screen + mouse_diff;
+
+ /* Project the point onto the line drawn by the mouse. Note, it's projected on the
+ * infinite line, not only on the line segment. */
+ float2 old_position_screen_proj;
+ /* t is 0 when the point is closest to the previous mouse position and 1 when it's
+ * closest to the current mouse position. */
+ const float t = closest_to_line_v2(
+ old_position_screen_proj, old_position_screen, mouse_prev, mouse_cur);
+
+ /* Compute the distance to the mouse line segment. */
+ const float2 old_position_screen_proj_segment = mouse_prev +
+ std::clamp(t, 0.0f, 1.0f) * mouse_diff;
+ const float distance_screen = math::distance(old_position_screen,
+ old_position_screen_proj_segment);
+ if (distance_screen > brush_radius) {
+ /* Ignore the point because it's too far away. */
+ continue;
+ }
+ /* Compute a falloff that is based on how far along the point along the last stroke
+ * segment is. */
+ const float t_overshoot = brush_radius / mouse_diff_len;
+ const float t_falloff = 1.0f - std::max(t, 0.0f) / (1.0f + t_overshoot);
+ /* A falloff that is based on how far away the point is from the stroke. */
+ const float radius_falloff = pow2f(1.0f - distance_screen / brush_radius);
+ /* Combine the different falloffs and brush strength. */
+ const float weight = brush_strength * t_falloff * radius_falloff;
+
+ /* Offset the old point position in screen space and transform it back into 3D space. */
+ const float2 new_position_screen = old_position_screen + mouse_diff * weight;
float3 new_position;
- ED_view3d_win_to_3d(v3d, region, old_position, new_position_screen, new_position);
+ ED_view3d_win_to_3d(
+ v3d, region, ob_mat * old_position, new_position_screen, new_position);
+ new_position = ob_imat * new_position;
positions[point_i] = new_position;
+
+ curve_changed = true;
+ }
+ if (!curve_changed) {
+ continue;
}
- });
+ /* Ensure that the length of each segment stays the same. */
+ for (const int segment_i : IndexRange(curve_points.size() - 1)) {
+ const float3 &p1 = positions[curve_points[segment_i]];
+ float3 &p2 = positions[curve_points[segment_i] + 1];
+ const float3 direction = math::normalize(p2 - p1);
+ const float desired_length = segment_lengths[segment_i];
+ p2 = p1 + direction * desired_length;
+ }
+ }
+ });
+
+ curves.tag_positions_changed();
+ DEG_id_tag_update(&curves_id.id, ID_RECALC_GEOMETRY);
+ ED_region_tag_redraw(region);
+ }
+};
+
+/**
+ * Drags the tip point of each curve and resamples the rest of the curve.
+ */
+class SnakeHookOperation : public CurvesSculptStrokeOperation {
+ private:
+ float2 last_mouse_position_;
- curves.tag_positions_changed();
- DEG_id_tag_update(&curves_id.id, ID_RECALC_GEOMETRY);
- ED_region_tag_redraw(region);
+ public:
+ void on_stroke_extended(bContext *C, const StrokeExtension &stroke_extension) override
+ {
+ BLI_SCOPED_DEFER([&]() { last_mouse_position_ = stroke_extension.mouse_position; });
+
+ if (stroke_extension.is_first) {
+ return;
}
- last_mouse_position_ = stroke_extension.mouse_position;
+ Scene &scene = *CTX_data_scene(C);
+ Object &object = *CTX_data_active_object(C);
+ ARegion *region = CTX_wm_region(C);
+ View3D *v3d = CTX_wm_view3d(C);
+ RegionView3D *rv3d = CTX_wm_region_view3d(C);
+
+ CurvesSculpt &curves_sculpt = *scene.toolsettings->curves_sculpt;
+ Brush &brush = *BKE_paint_brush(&curves_sculpt.paint);
+ const float brush_radius = BKE_brush_size_get(&scene, &brush);
+ const float brush_strength = BKE_brush_alpha_get(&scene, &brush);
+
+ const float4x4 ob_mat = object.obmat;
+ const float4x4 ob_imat = ob_mat.inverted();
+
+ float4x4 projection;
+ ED_view3d_ob_project_mat_get(rv3d, &object, projection.values);
+
+ Curves &curves_id = *static_cast<Curves *>(object.data);
+ CurvesGeometry &curves = CurvesGeometry::wrap(curves_id.geometry);
+ MutableSpan<float3> positions = curves.positions();
+
+ const float2 mouse_prev = last_mouse_position_;
+ const float2 mouse_cur = stroke_extension.mouse_position;
+ const float2 mouse_diff = mouse_cur - mouse_prev;
+
+ threading::parallel_for(curves.curves_range(), 256, [&](const IndexRange curves_range) {
+ for (const int curve_i : curves_range) {
+ const IndexRange curve_points = curves.range_for_curve(curve_i);
+ const int last_point_i = curve_points.last();
+
+ const float3 old_position = positions[last_point_i];
+
+ float2 old_position_screen;
+ ED_view3d_project_float_v2_m4(
+ region, old_position, old_position_screen, projection.values);
+
+ const float distance_screen = math::distance(old_position_screen, mouse_prev);
+ if (distance_screen > brush_radius) {
+ continue;
+ }
+
+ const float radius_falloff = pow2f(1.0f - distance_screen / brush_radius);
+ const float weight = brush_strength * radius_falloff;
+
+ const float2 new_position_screen = old_position_screen + mouse_diff * weight;
+ float3 new_position;
+ ED_view3d_win_to_3d(v3d, region, ob_mat * old_position, new_position_screen, new_position);
+ new_position = ob_imat * new_position;
+
+ this->move_last_point_and_resample(positions, curve_points, new_position);
+ }
+ });
+
+ curves.tag_positions_changed();
+ DEG_id_tag_update(&curves_id.id, ID_RECALC_GEOMETRY);
+ ED_region_tag_redraw(region);
+ }
+
+ void move_last_point_and_resample(MutableSpan<float3> positions,
+ const IndexRange curve_points,
+ const float3 &new_last_point_position) const
+ {
+ Vector<float> old_lengths;
+ old_lengths.append(0.0f);
+ /* Used to (1) normalize the segment sizes over time and (2) support making zero-length
+ * segments */
+ const float extra_length = 0.001f;
+ for (const int segment_i : IndexRange(curve_points.size() - 1)) {
+ const float3 &p1 = positions[curve_points[segment_i]];
+ const float3 &p2 = positions[curve_points[segment_i] + 1];
+ const float length = math::distance(p1, p2);
+ old_lengths.append(old_lengths.last() + length + extra_length);
+ }
+ Vector<float> point_factors;
+ for (float &old_length : old_lengths) {
+ point_factors.append(old_length / old_lengths.last());
+ }
+
+ PolySpline new_spline;
+ new_spline.resize(curve_points.size());
+ MutableSpan<float3> new_spline_positions = new_spline.positions();
+ for (const int i : IndexRange(curve_points.size() - 1)) {
+ new_spline_positions[i] = positions[curve_points[i]];
+ }
+ new_spline_positions.last() = new_last_point_position;
+ new_spline.mark_cache_invalid();
+
+ for (const int i : IndexRange(curve_points.size())) {
+ const float factor = point_factors[i];
+ const Spline::LookupResult lookup = new_spline.lookup_evaluated_factor(factor);
+ const float index_factor = lookup.evaluated_index + lookup.factor;
+ float3 p;
+ new_spline.sample_with_index_factors<float3>(
+ new_spline_positions, {&index_factor, 1}, {&p, 1});
+ positions[curve_points[i]] = p;
+ }
+ }
+};
+
+/**
+ * Resamples the curves to a shorter length.
+ */
+class ShrinkOperation : public CurvesSculptStrokeOperation {
+ private:
+ float2 last_mouse_position_;
+
+ public:
+ void on_stroke_extended(bContext *C, const StrokeExtension &stroke_extension) override
+ {
+ BLI_SCOPED_DEFER([&]() { last_mouse_position_ = stroke_extension.mouse_position; });
+
+ if (stroke_extension.is_first) {
+ return;
+ }
+
+ Scene &scene = *CTX_data_scene(C);
+ Object &object = *CTX_data_active_object(C);
+ ARegion *region = CTX_wm_region(C);
+ View3D *v3d = CTX_wm_view3d(C);
+ RegionView3D *rv3d = CTX_wm_region_view3d(C);
+
+ CurvesSculpt &curves_sculpt = *scene.toolsettings->curves_sculpt;
+ Brush &brush = *BKE_paint_brush(&curves_sculpt.paint);
+ const float brush_radius = BKE_brush_size_get(&scene, &brush);
+ const float brush_strength = BKE_brush_alpha_get(&scene, &brush);
+
+ const float4x4 ob_mat = object.obmat;
+ const float4x4 ob_imat = ob_mat.inverted();
+
+ float4x4 projection;
+ ED_view3d_ob_project_mat_get(rv3d, &object, projection.values);
+
+ Curves &curves_id = *static_cast<Curves *>(object.data);
+ CurvesGeometry &curves = CurvesGeometry::wrap(curves_id.geometry);
+ MutableSpan<float3> positions = curves.positions();
+
+ const float2 mouse_prev = last_mouse_position_;
+ const float2 mouse_cur = stroke_extension.mouse_position;
+ const float2 mouse_diff = mouse_cur - mouse_prev;
+
+ threading::parallel_for(curves.curves_range(), 256, [&](const IndexRange curves_range) {
+ for (const int curve_i : curves_range) {
+ const IndexRange curve_points = curves.range_for_curve(curve_i);
+ const int last_point_i = curve_points.last();
+
+ const float3 old_tip_position = positions[last_point_i];
+
+ float2 old_tip_position_screen;
+ ED_view3d_project_float_v2_m4(
+ region, old_tip_position, old_tip_position_screen, projection.values);
+
+ const float distance_screen = math::distance(old_tip_position_screen, mouse_prev);
+ if (distance_screen > brush_radius) {
+ continue;
+ }
+
+ const float radius_falloff = pow2f(1.0f - distance_screen / brush_radius);
+ const float weight = brush_strength * radius_falloff;
+
+ const float2 offset_tip_position_screen = old_tip_position_screen + weight * mouse_diff;
+ float3 offset_tip_position;
+ ED_view3d_win_to_3d(v3d,
+ region,
+ ob_mat * old_tip_position,
+ offset_tip_position_screen,
+ offset_tip_position);
+ offset_tip_position = ob_imat * offset_tip_position;
+ const float shrink_length = math::distance(offset_tip_position, old_tip_position);
+
+ this->shrink_curve(positions, curve_points, shrink_length);
+ }
+ });
+
+ curves.tag_positions_changed();
+ DEG_id_tag_update(&curves_id.id, ID_RECALC_GEOMETRY);
+ ED_region_tag_redraw(region);
+ }
+
+ void shrink_curve(MutableSpan<float3> positions,
+ const IndexRange curve_points,
+ const float shrink_length) const
+ {
+ PolySpline spline;
+ spline.resize(curve_points.size());
+ MutableSpan<float3> spline_positions = spline.positions();
+ spline_positions.copy_from(positions.slice(curve_points));
+ spline.mark_cache_invalid();
+ const float old_length = spline.length();
+ const float new_length = std::max(0.0f, old_length - shrink_length);
+ const float length_factor = new_length / old_length;
+
+ Vector<float> old_point_lengths;
+ old_point_lengths.append(0.0f);
+ for (const int i : spline_positions.index_range().drop_back(1)) {
+ const float3 &p1 = spline_positions[i];
+ const float3 &p2 = spline_positions[i + 1];
+ const float length = math::distance(p1, p2);
+ old_point_lengths.append(old_point_lengths.last() + length);
+ }
+
+ for (const int i : spline_positions.index_range()) {
+ const float eval_length = old_point_lengths[i] * length_factor;
+ const Spline::LookupResult lookup = spline.lookup_evaluated_length(eval_length);
+ const float index_factor = lookup.evaluated_index + lookup.factor;
+ float3 p;
+ spline.sample_with_index_factors<float3>(spline_positions, {&index_factor, 1}, {&p, 1});
+ positions[curve_points[i]] = p;
+ }
}
};
@@ -233,7 +513,7 @@ class AddOperation : public CurvesSculptStrokeOperation {
};
public:
- ~AddOperation()
+ ~AddOperation() override
{
if (old_kdtree_ != nullptr) {
BLI_kdtree_3d_free(old_kdtree_);
@@ -651,12 +931,16 @@ static std::unique_ptr<CurvesSculptStrokeOperation> start_brush_operation(bConte
CurvesSculpt &curves_sculpt = *scene.toolsettings->curves_sculpt;
Brush &brush = *BKE_paint_brush(&curves_sculpt.paint);
switch (brush.curves_sculpt_tool) {
- case CURVES_SCULPT_TOOL_TEST1:
- return std::make_unique<MoveOperation>();
- case CURVES_SCULPT_TOOL_TEST2:
+ case CURVES_SCULPT_TOOL_COMB:
+ return std::make_unique<CombOperation>();
+ case CURVES_SCULPT_TOOL_DELETE:
return std::make_unique<DeleteOperation>();
- case CURVES_SCULPT_TOOL_TEST3:
+ case CURVES_SCULPT_TOOL_SNAKE_HOOK:
+ return std::make_unique<SnakeHookOperation>();
+ case CURVES_SCULPT_TOOL_TEST1:
return std::make_unique<AddOperation>();
+ case CURVES_SCULPT_TOOL_TEST2:
+ return std::make_unique<ShrinkOperation>();
}
BLI_assert_unreachable();
return {};
diff --git a/source/blender/editors/sculpt_paint/paint_curve.c b/source/blender/editors/sculpt_paint/paint_curve.c
index 57c8bd58549..22d6626ab16 100644
--- a/source/blender/editors/sculpt_paint/paint_curve.c
+++ b/source/blender/editors/sculpt_paint/paint_curve.c
@@ -680,7 +680,7 @@ static int paintcurve_draw_exec(bContext *C, wmOperator *UNUSED(op))
return OPERATOR_PASS_THROUGH;
}
- return WM_operator_name_call(C, name, WM_OP_INVOKE_DEFAULT, NULL);
+ return WM_operator_name_call(C, name, WM_OP_INVOKE_DEFAULT, NULL, NULL);
}
void PAINTCURVE_OT_draw(wmOperatorType *ot)
diff --git a/source/blender/editors/sculpt_paint/paint_stroke.c b/source/blender/editors/sculpt_paint/paint_stroke.c
index ae7570d21a1..1705e36363e 100644
--- a/source/blender/editors/sculpt_paint/paint_stroke.c
+++ b/source/blender/editors/sculpt_paint/paint_stroke.c
@@ -1000,6 +1000,10 @@ bool paint_space_stroke_enabled(Brush *br, ePaintMode mode)
return true;
}
+ if (mode == PAINT_MODE_SCULPT_CURVES) {
+ return false;
+ }
+
return paint_supports_dynamic_size(br, mode);
}
diff --git a/source/blender/editors/sculpt_paint/sculpt_cloth.c b/source/blender/editors/sculpt_paint/sculpt_cloth.c
index 80ba7601cb1..a4cfb611138 100644
--- a/source/blender/editors/sculpt_paint/sculpt_cloth.c
+++ b/source/blender/editors/sculpt_paint/sculpt_cloth.c
@@ -1502,7 +1502,7 @@ static int sculpt_cloth_filter_modal(bContext *C, wmOperator *op, const wmEvent
return OPERATOR_RUNNING_MODAL;
}
- const float len = event->prev_click_xy[0] - event->xy[0];
+ const float len = event->prev_press_xy[0] - event->xy[0];
filter_strength = filter_strength * -len * 0.001f * UI_DPI_FAC;
SCULPT_vertex_random_access_ensure(ss);
diff --git a/source/blender/editors/sculpt_paint/sculpt_detail.c b/source/blender/editors/sculpt_paint/sculpt_detail.c
index 0f1f7c57287..dd8921d575f 100644
--- a/source/blender/editors/sculpt_paint/sculpt_detail.c
+++ b/source/blender/editors/sculpt_paint/sculpt_detail.c
@@ -408,7 +408,7 @@ static void sculpt_detail_size_set_radial_control(bContext *C)
RNA_string_set(&props_ptr, "data_path_primary", "tool_settings.sculpt.detail_size");
}
- WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &props_ptr);
+ WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &props_ptr, NULL);
WM_operator_properties_free(&props_ptr);
}
diff --git a/source/blender/editors/sculpt_paint/sculpt_filter_color.c b/source/blender/editors/sculpt_paint/sculpt_filter_color.c
index 93e2d721962..377f1e0ed32 100644
--- a/source/blender/editors/sculpt_paint/sculpt_filter_color.c
+++ b/source/blender/editors/sculpt_paint/sculpt_filter_color.c
@@ -215,7 +215,7 @@ static int sculpt_color_filter_modal(bContext *C, wmOperator *op, const wmEvent
return OPERATOR_RUNNING_MODAL;
}
- const float len = event->prev_click_xy[0] - event->xy[0];
+ const float len = event->prev_press_xy[0] - event->xy[0];
filter_strength = filter_strength * -len * 0.001f;
float fill_color[3];
diff --git a/source/blender/editors/sculpt_paint/sculpt_filter_mesh.c b/source/blender/editors/sculpt_paint/sculpt_filter_mesh.c
index ac2c83d3a9c..b73e182fcab 100644
--- a/source/blender/editors/sculpt_paint/sculpt_filter_mesh.c
+++ b/source/blender/editors/sculpt_paint/sculpt_filter_mesh.c
@@ -606,7 +606,7 @@ static int sculpt_mesh_filter_modal(bContext *C, wmOperator *op, const wmEvent *
return OPERATOR_RUNNING_MODAL;
}
- const float len = event->prev_click_xy[0] - event->xy[0];
+ const float len = event->prev_press_xy[0] - event->xy[0];
filter_strength = filter_strength * -len * 0.001f * UI_DPI_FAC;
SCULPT_vertex_random_access_ensure(ss);
diff --git a/source/blender/editors/sculpt_paint/sculpt_undo.c b/source/blender/editors/sculpt_paint/sculpt_undo.c
index f3f47f71f60..2ec553c63c7 100644
--- a/source/blender/editors/sculpt_paint/sculpt_undo.c
+++ b/source/blender/editors/sculpt_paint/sculpt_undo.c
@@ -31,6 +31,7 @@
#include "BKE_key.h"
#include "BKE_main.h"
#include "BKE_mesh.h"
+#include "BKE_mesh_runtime.h"
#include "BKE_multires.h"
#include "BKE_object.h"
#include "BKE_paint.h"
@@ -528,6 +529,8 @@ static void sculpt_undo_geometry_restore_data(SculptUndoNodeGeometry *geometry,
&geometry->pdata, &mesh->pdata, CD_MASK_MESH.pmask, CD_DUPLICATE, geometry->totpoly);
BKE_mesh_update_customdata_pointers(mesh, false);
+
+ BKE_mesh_runtime_clear_cache(mesh);
}
static void sculpt_undo_geometry_free_data(SculptUndoNodeGeometry *geometry)
diff --git a/source/blender/editors/space_action/action_select.c b/source/blender/editors/space_action/action_select.c
index 65815983767..b972ccbaf89 100644
--- a/source/blender/editors/space_action/action_select.c
+++ b/source/blender/editors/space_action/action_select.c
@@ -511,8 +511,12 @@ static int actkeys_box_select_invoke(bContext *C, wmOperator *op, const wmEvent
}
bool tweak = RNA_boolean_get(op->ptr, "tweak");
- if (tweak && actkeys_is_key_at_position(&ac, event->mval[0], event->mval[1])) {
- return OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH;
+ if (tweak) {
+ int mval[2];
+ WM_event_drag_start_mval(event, ac.region, mval);
+ if (actkeys_is_key_at_position(&ac, mval[0], mval[1])) {
+ return OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH;
+ }
}
return WM_gesture_box_invoke(C, op, event);
diff --git a/source/blender/editors/space_buttons/buttons_ops.c b/source/blender/editors/space_buttons/buttons_ops.c
index e215b7c7992..3de181fa540 100644
--- a/source/blender/editors/space_buttons/buttons_ops.c
+++ b/source/blender/editors/space_buttons/buttons_ops.c
@@ -295,7 +295,7 @@ static int file_browse_invoke(bContext *C, wmOperator *op, const wmEvent *event)
WM_operator_properties_create_ptr(&props_ptr, ot);
RNA_string_set(&props_ptr, "filepath", str);
- WM_operator_name_call_ptr(C, ot, WM_OP_EXEC_DEFAULT, &props_ptr);
+ WM_operator_name_call_ptr(C, ot, WM_OP_EXEC_DEFAULT, &props_ptr, NULL);
WM_operator_properties_free(&props_ptr);
MEM_freeN(str);
diff --git a/source/blender/editors/space_console/console_ops.c b/source/blender/editors/space_console/console_ops.c
index a24eae6a0ce..17fbef23eac 100644
--- a/source/blender/editors/space_console/console_ops.c
+++ b/source/blender/editors/space_console/console_ops.c
@@ -469,10 +469,10 @@ static int console_indent_or_autocomplete_exec(bContext *C, wmOperator *UNUSED(o
}
if (text_before_cursor) {
- WM_operator_name_call(C, "CONSOLE_OT_autocomplete", WM_OP_INVOKE_DEFAULT, NULL);
+ WM_operator_name_call(C, "CONSOLE_OT_autocomplete", WM_OP_INVOKE_DEFAULT, NULL, NULL);
}
else {
- WM_operator_name_call(C, "CONSOLE_OT_indent", WM_OP_EXEC_DEFAULT, NULL);
+ WM_operator_name_call(C, "CONSOLE_OT_indent", WM_OP_EXEC_DEFAULT, NULL, NULL);
}
return OPERATOR_FINISHED;
}
@@ -1070,7 +1070,7 @@ static int console_paste_exec(bContext *C, wmOperator *UNUSED(op))
}
if (buf_next != buf_str) {
- WM_operator_name_call(C, "CONSOLE_OT_execute", WM_OP_EXEC_DEFAULT, NULL);
+ WM_operator_name_call(C, "CONSOLE_OT_execute", WM_OP_EXEC_DEFAULT, NULL, NULL);
ci = console_history_verify(C);
}
diff --git a/source/blender/editors/space_console/space_console.c b/source/blender/editors/space_console/space_console.c
index d051f14d264..8e33f7fa97f 100644
--- a/source/blender/editors/space_console/space_console.c
+++ b/source/blender/editors/space_console/space_console.c
@@ -189,7 +189,7 @@ static void console_main_region_draw(const bContext *C, ARegion *region)
View2D *v2d = &region->v2d;
if (BLI_listbase_is_empty(&sc->scrollback)) {
- WM_operator_name_call((bContext *)C, "CONSOLE_OT_banner", WM_OP_EXEC_DEFAULT, NULL);
+ WM_operator_name_call((bContext *)C, "CONSOLE_OT_banner", WM_OP_EXEC_DEFAULT, NULL, NULL);
}
/* clear and setup matrix */
diff --git a/source/blender/editors/space_file/file_ops.c b/source/blender/editors/space_file/file_ops.c
index c859cad1c27..578288ca289 100644
--- a/source/blender/editors/space_file/file_ops.c
+++ b/source/blender/editors/space_file/file_ops.c
@@ -2221,7 +2221,7 @@ static int file_smoothscroll_invoke(bContext *C, wmOperator *UNUSED(op), const w
RNA_int_set(&op_ptr, "deltax", deltax);
RNA_int_set(&op_ptr, "deltay", deltay);
- WM_operator_name_call(C, "VIEW2D_OT_pan", WM_OP_EXEC_DEFAULT, &op_ptr);
+ WM_operator_name_call(C, "VIEW2D_OT_pan", WM_OP_EXEC_DEFAULT, &op_ptr, event);
WM_operator_properties_free(&op_ptr);
ED_region_tag_redraw(region);
@@ -2580,7 +2580,7 @@ void file_directory_enter_handle(bContext *C, void *UNUSED(arg_unused), void *UN
BLI_strncpy(params->dir, lastdir, sizeof(params->dir));
}
- WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &ptr);
+ WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &ptr, NULL);
WM_operator_properties_free(&ptr);
}
}
diff --git a/source/blender/editors/space_file/filelist.c b/source/blender/editors/space_file/filelist.c
index daa4b53803f..363e19a8905 100644
--- a/source/blender/editors/space_file/filelist.c
+++ b/source/blender/editors/space_file/filelist.c
@@ -339,7 +339,7 @@ typedef struct FileListEntryPreview {
char path[FILE_MAX];
uint flags;
int index;
-
+ int attributes; /* from FileDirEntry. */
int icon_id;
} FileListEntryPreview;
@@ -1623,8 +1623,10 @@ static void filelist_cache_preview_runf(TaskPool *__restrict pool, void *taskdat
IMB_thumb_path_lock(preview->path);
/* Always generate biggest preview size for now, it's simpler and avoids having to re-generate
- * in case user switch to a bigger preview size. */
- ImBuf *imbuf = IMB_thumb_manage(preview->path, THB_LARGE, source);
+ * in case user switch to a bigger preview size. Do not create preview when file is offline. */
+ ImBuf *imbuf = (preview->attributes & FILE_ATTR_OFFLINE) ?
+ IMB_thumb_read(preview->path, THB_LARGE) :
+ IMB_thumb_manage(preview->path, THB_LARGE, source);
IMB_thumb_path_unlock(preview->path);
if (imbuf) {
preview->icon_id = BKE_icon_imbuf_create(imbuf);
@@ -1704,11 +1706,6 @@ static void filelist_cache_previews_push(FileList *filelist, FileDirEntry *entry
BLI_assert(cache->flags & FLC_PREVIEWS_ACTIVE);
- if (!entry->preview_icon_id && (entry->attributes & FILE_ATTR_OFFLINE)) {
- entry->flags |= FILE_ENTRY_INVALID_PREVIEW;
- return;
- }
-
if (entry->preview_icon_id) {
return;
}
@@ -1735,6 +1732,7 @@ static void filelist_cache_previews_push(FileList *filelist, FileDirEntry *entry
FileListEntryPreview *preview = MEM_mallocN(sizeof(*preview), __func__);
preview->index = index;
preview->flags = entry->typeflag;
+ preview->attributes = entry->attributes;
preview->icon_id = 0;
if (preview_in_memory) {
@@ -3462,8 +3460,7 @@ static void filelist_readjob_main_recursive(Main *bmain, FileList *filelist)
// files->entry->nr = totbl + 1;
files->entry->poin = id;
fake = id->flag & LIB_FAKEUSER;
- if (idcode == ID_MA || idcode == ID_TE || idcode == ID_LA || idcode == ID_WO ||
- idcode == ID_IM) {
+ if (ELEM(idcode, ID_MA, ID_TE, ID_LA, ID_WO, ID_IM)) {
files->typeflag |= FILE_TYPE_IMAGE;
}
# if 0
diff --git a/source/blender/editors/space_file/filesel.c b/source/blender/editors/space_file/filesel.c
index f6629061878..011506368ee 100644
--- a/source/blender/editors/space_file/filesel.c
+++ b/source/blender/editors/space_file/filesel.c
@@ -515,19 +515,15 @@ void ED_fileselect_activate_by_id(SpaceFile *sfile, ID *asset_id, const bool def
FileSelectParams *params = ED_fileselect_get_active_params(sfile);
struct FileList *files = sfile->files;
- const int num_files_filtered = filelist_files_ensure(files);
- for (int file_index = 0; file_index < num_files_filtered; ++file_index) {
- const FileDirEntry *file = filelist_file_ex(files, file_index, false);
-
- if (filelist_file_get_id(file) != asset_id) {
- continue;
- }
-
- params->active_file = file_index;
- filelist_entry_select_set(files, file, FILE_SEL_ADD, FILE_SEL_SELECTED, CHECK_ALL);
- break;
+ const int file_index = filelist_file_find_id(files, asset_id);
+ const FileDirEntry *file = filelist_file_ex(files, file_index, true);
+ if (file == NULL) {
+ return;
}
+ params->active_file = file_index;
+ filelist_entry_select_set(files, file, FILE_SEL_ADD, FILE_SEL_SELECTED, CHECK_ALL);
+
WM_main_add_notifier(NC_ASSET | NA_ACTIVATED, NULL);
WM_main_add_notifier(NC_ASSET | NA_SELECTED, NULL);
}
@@ -1129,8 +1125,8 @@ int file_select_match(struct SpaceFile *sfile, const char *pattern, char *matche
*/
for (int i = 0; i < n; i++) {
FileDirEntry *file = filelist_file(sfile->files, i);
- /* Do not check whether file is a file or dir here! Causes T44243
- * (we do accept dirs at this stage). */
+ /* Do not check whether file is a file or dir here! Causes: T44243
+ * (we do accept directories at this stage). */
if (fnmatch(pattern, file->relpath, 0) == 0) {
filelist_entry_select_set(sfile->files, file, FILE_SEL_ADD, FILE_SEL_SELECTED, CHECK_ALL);
if (!match) {
diff --git a/source/blender/editors/space_file/fsmenu.c b/source/blender/editors/space_file/fsmenu.c
index 988ba7728f1..847bf89bba8 100644
--- a/source/blender/editors/space_file/fsmenu.c
+++ b/source/blender/editors/space_file/fsmenu.c
@@ -29,6 +29,7 @@
* because 'near' is disabled through BLI_windstuff. */
# include "BLI_winstuff.h"
# include <shlobj.h>
+# include <shlwapi.h>
#endif
#include "UI_interface_icons.h"
@@ -642,14 +643,29 @@ void fsmenu_read_system(struct FSMenu *fsmenu, int read_bookmarks)
tmps[3] = '\0';
name = NULL;
- /* Flee from horrible win querying hover floppy drives! */
+ /* Skip over floppy disks A & B. */
if (i > 1) {
- /* Try to get a friendly drive description. */
- SHFILEINFOW shFile = {0};
+ /* Friendly volume descriptions without using SHGetFileInfoW (T85689). */
BLI_strncpy_wchar_from_utf8(wline, tmps, 4);
- if (SHGetFileInfoW(wline, 0, &shFile, sizeof(SHFILEINFOW), SHGFI_DISPLAYNAME)) {
- BLI_strncpy_wchar_as_utf8(line, shFile.szDisplayName, FILE_MAXDIR);
- name = line;
+ IShellFolder *desktop;
+ if (SHGetDesktopFolder(&desktop) == S_OK) {
+ PIDLIST_RELATIVE volume;
+ if (desktop->lpVtbl->ParseDisplayName(
+ desktop, NULL, NULL, wline, NULL, &volume, NULL) == S_OK) {
+ STRRET volume_name;
+ volume_name.uType = STRRET_WSTR;
+ if (desktop->lpVtbl->GetDisplayNameOf(
+ desktop, volume, SHGDN_FORADDRESSBAR, &volume_name) == S_OK) {
+ wchar_t *volume_name_wchar;
+ if (StrRetToStrW(&volume_name, volume, &volume_name_wchar) == S_OK) {
+ BLI_strncpy_wchar_as_utf8(line, volume_name_wchar, FILE_MAXDIR);
+ name = line;
+ CoTaskMemFree(volume_name_wchar);
+ }
+ }
+ CoTaskMemFree(volume);
+ }
+ desktop->lpVtbl->Release(desktop);
}
}
if (name == NULL) {
diff --git a/source/blender/editors/space_graph/graph_select.c b/source/blender/editors/space_graph/graph_select.c
index 2ed684c6e97..39b980ac4c3 100644
--- a/source/blender/editors/space_graph/graph_select.c
+++ b/source/blender/editors/space_graph/graph_select.c
@@ -799,7 +799,9 @@ static int graphkeys_box_select_invoke(bContext *C, wmOperator *op, const wmEven
}
if (RNA_boolean_get(op->ptr, "tweak")) {
- tNearestVertInfo *under_mouse = find_nearest_fcurve_vert(&ac, event->mval);
+ int mval[2];
+ WM_event_drag_start_mval(event, ac.region, mval);
+ tNearestVertInfo *under_mouse = find_nearest_fcurve_vert(&ac, mval);
bool mouse_is_over_element = under_mouse != NULL;
if (under_mouse) {
MEM_freeN(under_mouse);
diff --git a/source/blender/editors/space_graph/space_graph.c b/source/blender/editors/space_graph/space_graph.c
index 22427675ff3..f041f2d1d3b 100644
--- a/source/blender/editors/space_graph/space_graph.c
+++ b/source/blender/editors/space_graph/space_graph.c
@@ -295,16 +295,14 @@ static void graph_main_region_draw_overlay(const bContext *C, ARegion *region)
/* draw entirely, view changes should be handled here */
const SpaceGraph *sipo = CTX_wm_space_graph(C);
- /* Driver Editor's X axis is not time. */
- if (sipo->mode == SIPO_MODE_DRIVERS) {
- return;
- }
-
const Scene *scene = CTX_data_scene(C);
View2D *v2d = &region->v2d;
- /* scrubbing region */
- ED_time_scrub_draw_current_frame(region, scene, sipo->flag & SIPO_DRAWTIME);
+ /* Driver Editor's X axis is not time. */
+ if (sipo->mode != SIPO_MODE_DRIVERS) {
+ /* scrubbing region */
+ ED_time_scrub_draw_current_frame(region, scene, sipo->flag & SIPO_DRAWTIME);
+ }
/* scrollers */
/* FIXME: args for scrollers depend on the type of data being shown. */
diff --git a/source/blender/editors/space_image/image_buttons.c b/source/blender/editors/space_image/image_buttons.c
index 6f3d40abce1..0af32a717a4 100644
--- a/source/blender/editors/space_image/image_buttons.c
+++ b/source/blender/editors/space_image/image_buttons.c
@@ -718,22 +718,6 @@ static void rna_update_cb(bContext *C, void *arg_cb, void *UNUSED(arg))
RNA_property_update(C, &cb->ptr, cb->prop);
}
-static bool image_has_alpha(Image *ima, ImageUser *iuser)
-{
- ImBuf *ibuf = BKE_image_acquire_ibuf(ima, iuser, NULL);
- if (ibuf == NULL) {
- return false;
- }
-
- int imtype = BKE_image_ftype_to_imtype(ibuf->ftype, &ibuf->foptions);
- char valid_channels = BKE_imtype_valid_channels(imtype, false);
- bool has_alpha = (valid_channels & IMA_CHAN_FLAG_ALPHA) != 0;
-
- BKE_image_release_ibuf(ima, ibuf, NULL);
-
- return has_alpha;
-}
-
void uiTemplateImage(uiLayout *layout,
bContext *C,
PointerRNA *ptr,
@@ -943,7 +927,7 @@ void uiTemplateImage(uiLayout *layout,
if (compact == 0) {
if (ima->source != IMA_SRC_GENERATED) {
- if (image_has_alpha(ima, iuser)) {
+ if (BKE_image_has_alpha(ima)) {
uiLayout *sub = uiLayoutColumn(col, false);
uiItemR(sub, &imaptr, "alpha_mode", 0, IFACE_("Alpha"), ICON_NONE);
diff --git a/source/blender/editors/space_image/image_draw.c b/source/blender/editors/space_image/image_draw.c
index cc86852e0d1..342f2df0020 100644
--- a/source/blender/editors/space_image/image_draw.c
+++ b/source/blender/editors/space_image/image_draw.c
@@ -541,7 +541,10 @@ void draw_image_cache(const bContext *C, ARegion *region)
int num_segments = 0;
int *points = NULL;
+ BLI_mutex_lock(image->runtime.cache_mutex);
IMB_moviecache_get_cache_segments(image->cache, IMB_PROXY_NONE, 0, &num_segments, &points);
+ BLI_mutex_unlock(image->runtime.cache_mutex);
+
ED_region_cache_draw_cached_segments(
region, num_segments, points, sfra + sima->iuser.offset, efra + sima->iuser.offset);
}
diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c
index aed4a2ccabd..6a16efdb413 100644
--- a/source/blender/editors/space_image/image_ops.c
+++ b/source/blender/editors/space_image/image_ops.c
@@ -2155,7 +2155,7 @@ static int image_save_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
-static int image_save_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
+static int image_save_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
Image *ima = image_from_context(C);
ImageUser *iuser = image_user_from_context(C);
@@ -2163,7 +2163,7 @@ static int image_save_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(
/* Not writable formats or images without a file-path will go to "Save As". */
if (!BKE_image_has_packedfile(ima) &&
(!BKE_image_has_filepath(ima) || !image_file_format_writable(ima, iuser))) {
- WM_operator_name_call(C, "IMAGE_OT_save_as", WM_OP_INVOKE_DEFAULT, NULL);
+ WM_operator_name_call(C, "IMAGE_OT_save_as", WM_OP_INVOKE_DEFAULT, NULL, event);
return OPERATOR_CANCELLED;
}
return image_save_exec(C, op);
diff --git a/source/blender/editors/space_image/image_undo.c b/source/blender/editors/space_image/image_undo.c
index e9997fe8d42..c3a48abcae1 100644
--- a/source/blender/editors/space_image/image_undo.c
+++ b/source/blender/editors/space_image/image_undo.c
@@ -557,7 +557,8 @@ static void uhandle_restore_list(ListBase *undo_handles, bool use_init)
if (changed) {
BKE_image_mark_dirty(image, ibuf);
- BKE_image_free_gputextures(image); /* force OpenGL reload */
+ /* TODO(jbakker): only mark areas that are actually updated to improve performance. */
+ BKE_image_partial_update_mark_full_update(image);
if (ibuf->rect_float) {
ibuf->userflags |= IB_RECT_INVALID; /* force recreate of char rect */
diff --git a/source/blender/editors/space_info/info_report.c b/source/blender/editors/space_info/info_report.c
index 603c7c9ad37..ba11c5b2958 100644
--- a/source/blender/editors/space_info/info_report.c
+++ b/source/blender/editors/space_info/info_report.c
@@ -101,7 +101,7 @@ static int report_replay_exec(bContext *C, wmOperator *UNUSED(op))
if ((report->type & report_mask) && (report->type & RPT_OPERATOR_ALL | RPT_PROPERTY_ALL) &&
(report->flag & SELECT)) {
console_history_add_str(sc, report->message, 0);
- WM_operator_name_call(C, "CONSOLE_OT_execute", WM_OP_EXEC_DEFAULT, NULL);
+ WM_operator_name_call(C, "CONSOLE_OT_execute", WM_OP_EXEC_DEFAULT, NULL, NULL);
ED_area_tag_redraw(CTX_wm_area(C));
}
diff --git a/source/blender/editors/space_nla/nla_edit.c b/source/blender/editors/space_nla/nla_edit.c
index e94221fab04..eeeadb6e60a 100644
--- a/source/blender/editors/space_nla/nla_edit.c
+++ b/source/blender/editors/space_nla/nla_edit.c
@@ -1192,12 +1192,12 @@ static int nlaedit_duplicate_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
-static int nlaedit_duplicate_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
+static int nlaedit_duplicate_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
nlaedit_duplicate_exec(C, op);
RNA_enum_set(op->ptr, "mode", TFM_TRANSLATION);
- WM_operator_name_call(C, "TRANSFORM_OT_transform", WM_OP_INVOKE_REGION_WIN, op->ptr);
+ WM_operator_name_call(C, "TRANSFORM_OT_transform", WM_OP_INVOKE_REGION_WIN, op->ptr, event);
return OPERATOR_FINISHED;
}
diff --git a/source/blender/editors/space_nla/nla_select.c b/source/blender/editors/space_nla/nla_select.c
index 3000b4a1109..1efb91bc99f 100644
--- a/source/blender/editors/space_nla/nla_select.c
+++ b/source/blender/editors/space_nla/nla_select.c
@@ -439,7 +439,7 @@ static void nlaedit_select_leftright(bContext *C,
/* if currently in tweak-mode, exit tweak-mode first */
if (scene->flag & SCE_NLA_EDIT_ON) {
- WM_operator_name_call(C, "NLA_OT_tweakmode_exit", WM_OP_EXEC_DEFAULT, NULL);
+ WM_operator_name_call(C, "NLA_OT_tweakmode_exit", WM_OP_EXEC_DEFAULT, NULL, NULL);
}
/* if select mode is replace, deselect all keyframes (and channels) first */
@@ -600,7 +600,7 @@ static int mouse_nla_strips(bContext *C,
* now that we've found our target...
*/
if (scene->flag & SCE_NLA_EDIT_ON) {
- WM_operator_name_call(C, "NLA_OT_tweakmode_exit", WM_OP_EXEC_DEFAULT, NULL);
+ WM_operator_name_call(C, "NLA_OT_tweakmode_exit", WM_OP_EXEC_DEFAULT, NULL, NULL);
}
if (select_mode != SELECT_REPLACE) {
diff --git a/source/blender/editors/space_node/drawnode.cc b/source/blender/editors/space_node/drawnode.cc
index afb205f9f9e..fab2946ad76 100644
--- a/source/blender/editors/space_node/drawnode.cc
+++ b/source/blender/editors/space_node/drawnode.cc
@@ -304,9 +304,11 @@ static void node_buts_image_user(uiLayout *layout,
const bool show_layer_selection,
const bool show_color_management)
{
- if (!imaptr->data) {
+ Image *image = (Image *)imaptr->data;
+ if (!image) {
return;
}
+ ImageUser *iuser = (ImageUser *)iuserptr->data;
uiLayout *col = uiLayoutColumn(layout, false);
@@ -318,8 +320,6 @@ static void node_buts_image_user(uiLayout *layout,
/* don't use iuser->framenr directly
* because it may not be updated if auto-refresh is off */
Scene *scene = CTX_data_scene(C);
- ImageUser *iuser = (ImageUser *)iuserptr->data;
- /* Image *ima = imaptr->data; */ /* UNUSED */
char numstr[32];
const int framenr = BKE_image_user_frame_get(iuser, CFRA, nullptr);
@@ -343,11 +343,20 @@ static void node_buts_image_user(uiLayout *layout,
}
if (show_color_management) {
- uiLayout *split = uiLayoutSplit(layout, 0.5f, true);
+ uiLayout *split = uiLayoutSplit(layout, 0.33f, true);
PointerRNA colorspace_settings_ptr = RNA_pointer_get(imaptr, "colorspace_settings");
uiItemL(split, IFACE_("Color Space"), ICON_NONE);
uiItemR(split, &colorspace_settings_ptr, "name", DEFAULT_FLAGS, "", ICON_NONE);
+ if (image->source != IMA_SRC_GENERATED) {
+ split = uiLayoutSplit(layout, 0.33f, true);
+ uiItemL(split, IFACE_("Alpha"), ICON_NONE);
+ uiItemR(split, imaptr, "alpha_mode", DEFAULT_FLAGS, "", ICON_NONE);
+
+ bool is_data = IMB_colormanagement_space_name_is_data(image->colorspace_settings.name);
+ uiLayoutSetActive(split, !is_data);
+ }
+
/* Avoid losing changes image is painted. */
if (BKE_image_is_dirty((Image *)imaptr->data)) {
uiLayoutSetEnabled(split, false);
diff --git a/source/blender/editors/space_node/link_drag_search.cc b/source/blender/editors/space_node/link_drag_search.cc
index 2484318e612..ccd3333fcc5 100644
--- a/source/blender/editors/space_node/link_drag_search.cc
+++ b/source/blender/editors/space_node/link_drag_search.cc
@@ -235,7 +235,7 @@ static void link_drag_search_exec_fn(bContext *C, void *arg1, void *arg2)
PointerRNA ptr;
WM_operator_properties_create_ptr(&ptr, ot);
RNA_boolean_set(&ptr, "view2d_edge_pan", true);
- WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &ptr);
+ WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &ptr, nullptr);
WM_operator_properties_free(&ptr);
}
diff --git a/source/blender/editors/space_node/node_draw.cc b/source/blender/editors/space_node/node_draw.cc
index 1286f6a818c..9976ecf7700 100644
--- a/source/blender/editors/space_node/node_draw.cc
+++ b/source/blender/editors/space_node/node_draw.cc
@@ -720,7 +720,7 @@ static void node_socket_draw_multi_input(const float color[4],
{
/* The other sockets are drawn with the keyframe shader. There, the outline has a base thickness
* that can be varied but always scales with the size the socket is drawn at. Using `U.dpi_fac`
- * has the the same effect here. It scales the outline correctly across different screen DPIs
+ * has the same effect here. It scales the outline correctly across different screen DPI's
* and UI scales without being affected by the 'line-width'. */
const float outline_width = NODE_SOCK_OUTLINE_SCALE * U.dpi_fac;
@@ -1193,7 +1193,7 @@ static void node_toggle_button_cb(struct bContext *C, void *node_argv, void *op_
/* Select & activate only the button's node. */
node_select_single(*C, *node);
- WM_operator_name_call(C, opname, WM_OP_INVOKE_DEFAULT, nullptr);
+ WM_operator_name_call(C, opname, WM_OP_INVOKE_DEFAULT, nullptr, nullptr);
}
static void node_draw_shadow(const SpaceNode &snode,
diff --git a/source/blender/editors/space_node/node_edit.cc b/source/blender/editors/space_node/node_edit.cc
index b30be6ae0af..974e4c2e1cf 100644
--- a/source/blender/editors/space_node/node_edit.cc
+++ b/source/blender/editors/space_node/node_edit.cc
@@ -955,8 +955,10 @@ static int node_resize_modal(bContext *C, wmOperator *op, const wmEvent *event)
switch (event->type) {
case MOUSEMOVE: {
+ int mval[2];
+ WM_event_drag_start_mval(event, region, mval);
float mx, my;
- UI_view2d_region_to_view(&region->v2d, event->mval[0], event->mval[1], &mx, &my);
+ UI_view2d_region_to_view(&region->v2d, mval[0], mval[1], &mx, &my);
float dx = (mx - nsw->mxstart) / UI_DPI_FAC;
float dy = (my - nsw->mystart) / UI_DPI_FAC;
@@ -1057,7 +1059,9 @@ static int node_resize_invoke(bContext *C, wmOperator *op, const wmEvent *event)
/* convert mouse coordinates to v2d space */
float cursor[2];
- UI_view2d_region_to_view(&region->v2d, event->mval[0], event->mval[1], &cursor[0], &cursor[1]);
+ int mval[2];
+ WM_event_drag_start_mval(event, region, mval);
+ UI_view2d_region_to_view(&region->v2d, mval[0], mval[1], &cursor[0], &cursor[1]);
const NodeResizeDirection dir = node_get_resize_direction(node, cursor[0], cursor[1]);
if (dir == NODE_RESIZE_NONE) {
return OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH;
@@ -1503,7 +1507,7 @@ int node_render_changed_exec(bContext *C, wmOperator *UNUSED(op))
/* To keep keyframe positions. */
sce->r.scemode |= R_NO_FRAME_UPDATE;
- WM_operator_name_call(C, "RENDER_OT_render", WM_OP_INVOKE_DEFAULT, &op_ptr);
+ WM_operator_name_call(C, "RENDER_OT_render", WM_OP_INVOKE_DEFAULT, &op_ptr, nullptr);
WM_operator_properties_free(&op_ptr);
diff --git a/source/blender/editors/space_node/node_relationships.cc b/source/blender/editors/space_node/node_relationships.cc
index 299e7e5658c..2eae1ce240c 100644
--- a/source/blender/editors/space_node/node_relationships.cc
+++ b/source/blender/editors/space_node/node_relationships.cc
@@ -1177,8 +1177,11 @@ static int node_link_invoke(bContext *C, wmOperator *op, const wmEvent *event)
bool detach = RNA_boolean_get(op->ptr, "detach");
+ int mval[2];
+ WM_event_drag_start_mval(event, &region, mval);
+
float2 cursor;
- UI_view2d_region_to_view(&region.v2d, event->mval[0], event->mval[1], &cursor[0], &cursor[1]);
+ UI_view2d_region_to_view(&region.v2d, mval[0], mval[1], &cursor[0], &cursor[1]);
RNA_float_set_array(op->ptr, "drag_start", cursor);
RNA_boolean_set(op->ptr, "has_link_picked", false);
diff --git a/source/blender/editors/space_node/node_select.cc b/source/blender/editors/space_node/node_select.cc
index a355487057c..1d0097068f1 100644
--- a/source/blender/editors/space_node/node_select.cc
+++ b/source/blender/editors/space_node/node_select.cc
@@ -185,7 +185,11 @@ static bool is_event_over_node_or_socket(bContext *C, const wmEvent *event)
SpaceNode *snode = CTX_wm_space_node(C);
ARegion *region = CTX_wm_region(C);
float2 mouse;
- UI_view2d_region_to_view(&region->v2d, event->mval[0], event->mval[1], &mouse.x, &mouse.y);
+
+ int mval[2];
+ WM_event_drag_start_mval(event, region, mval);
+
+ UI_view2d_region_to_view(&region->v2d, mval[0], mval[1], &mouse.x, &mouse.y);
return is_position_over_node_or_socket(*snode, mouse);
}
diff --git a/source/blender/editors/space_outliner/outliner_collections.cc b/source/blender/editors/space_outliner/outliner_collections.cc
index f38f6c2855d..7c0ccd7b14c 100644
--- a/source/blender/editors/space_outliner/outliner_collections.cc
+++ b/source/blender/editors/space_outliner/outliner_collections.cc
@@ -9,6 +9,7 @@
#include "BLI_listbase.h"
#include "BLI_utildefines.h"
+#include "DNA_ID.h"
#include "DNA_collection_types.h"
#include "DNA_object_types.h"
@@ -275,6 +276,12 @@ struct CollectionEditData {
Scene *scene;
SpaceOutliner *space_outliner;
GSet *collections_to_edit;
+
+ /* Whether the processed operation should be allowed on liboverride collections, or not. */
+ bool is_liboverride_allowed;
+ /* Whether the processed operation should be allowed on hierarchy roots of liboverride
+ * collections, or not. */
+ bool is_liboverride_hierarchy_root_allowed;
};
static TreeTraversalAction collection_find_data_to_edit(TreeElement *te, void *customdata)
@@ -287,27 +294,40 @@ static TreeTraversalAction collection_find_data_to_edit(TreeElement *te, void *c
}
if (collection->flag & COLLECTION_IS_MASTER) {
- /* skip - showing warning/error message might be misleading
- * when deleting multiple collections, so just do nothing */
+ /* Skip - showing warning/error message might be misleading
+ * when deleting multiple collections, so just do nothing. */
+ return TRAVERSE_CONTINUE;
}
- else {
- /* Delete, duplicate and link don't edit children, those will come along
- * with the parents. */
- BLI_gset_add(data->collections_to_edit, collection);
- return TRAVERSE_SKIP_CHILDS;
+
+ if (ID_IS_OVERRIDE_LIBRARY_REAL(collection)) {
+ if (ID_IS_OVERRIDE_LIBRARY_HIERARCHY_ROOT(collection)) {
+ if (!data->is_liboverride_hierarchy_root_allowed) {
+ return TRAVERSE_SKIP_CHILDS;
+ }
+ }
+ else {
+ if (!data->is_liboverride_allowed) {
+ return TRAVERSE_SKIP_CHILDS;
+ }
+ }
}
- return TRAVERSE_CONTINUE;
+ /* Delete, duplicate and link don't edit children, those will come along
+ * with the parents. */
+ BLI_gset_add(data->collections_to_edit, collection);
+ return TRAVERSE_SKIP_CHILDS;
}
void outliner_collection_delete(
- bContext *C, Main *bmain, Scene *scene, ReportList *reports, bool hierarchy)
+ bContext *C, Main *bmain, Scene *scene, ReportList *reports, bool do_hierarchy)
{
SpaceOutliner *space_outliner = CTX_wm_space_outliner(C);
CollectionEditData data{};
data.scene = scene;
data.space_outliner = space_outliner;
+ data.is_liboverride_allowed = false;
+ data.is_liboverride_hierarchy_root_allowed = do_hierarchy;
data.collections_to_edit = BLI_gset_ptr_new(__func__);
@@ -356,14 +376,14 @@ void outliner_collection_delete(
}
if (!skip) {
- BKE_collection_delete(bmain, collection, hierarchy);
+ BKE_collection_delete(bmain, collection, do_hierarchy);
}
else {
- BKE_reportf(
- reports,
- RPT_WARNING,
- "Cannot delete linked collection '%s', it is used by other linked scenes/collections",
- collection->id.name + 2);
+ BKE_reportf(reports,
+ RPT_WARNING,
+ "Cannot delete collection '%s', it is either a linked one used by other "
+ "linked scenes/collections, or a library override one",
+ collection->id.name + 2);
}
}
}
@@ -662,6 +682,8 @@ static int collection_link_exec(bContext *C, wmOperator *op)
CollectionEditData data{};
data.scene = scene;
data.space_outliner = space_outliner;
+ data.is_liboverride_allowed = false; /* No linking of non-root collections. */
+ data.is_liboverride_hierarchy_root_allowed = true;
if ((ID_IS_LINKED(active_collection) || ID_IS_OVERRIDE_LIBRARY(active_collection)) ||
((active_collection->flag & COLLECTION_IS_MASTER) &&
@@ -726,6 +748,8 @@ static int collection_instance_exec(bContext *C, wmOperator *UNUSED(op))
CollectionEditData data{};
data.scene = scene;
data.space_outliner = space_outliner;
+ data.is_liboverride_allowed = false; /* No instancing of non-root collections. */
+ data.is_liboverride_hierarchy_root_allowed = true;
data.collections_to_edit = BLI_gset_ptr_new(__func__);
@@ -825,6 +849,8 @@ static bool collections_view_layer_poll(bContext *C, bool clear, int flag)
CollectionEditData data{};
data.scene = scene;
data.space_outliner = space_outliner;
+ data.is_liboverride_allowed = true;
+ data.is_liboverride_hierarchy_root_allowed = true;
data.collections_to_edit = BLI_gset_ptr_new(__func__);
bool result = false;
@@ -891,6 +917,8 @@ static int collection_view_layer_exec(bContext *C, wmOperator *op)
CollectionEditData data{};
data.scene = scene;
data.space_outliner = space_outliner;
+ data.is_liboverride_allowed = true;
+ data.is_liboverride_hierarchy_root_allowed = true;
bool clear = strstr(op->idname, "clear") != nullptr;
int flag = strstr(op->idname, "holdout") ? LAYER_COLLECTION_HOLDOUT :
strstr(op->idname, "indirect_only") ? LAYER_COLLECTION_INDIRECT_ONLY :
@@ -1029,6 +1057,8 @@ static int collection_isolate_exec(bContext *C, wmOperator *op)
CollectionEditData data{};
data.scene = scene;
data.space_outliner = space_outliner;
+ data.is_liboverride_allowed = true;
+ data.is_liboverride_hierarchy_root_allowed = true;
data.collections_to_edit = BLI_gset_ptr_new(__func__);
outliner_tree_traverse(space_outliner,
&space_outliner->tree,
@@ -1126,6 +1156,8 @@ static int collection_visibility_exec(bContext *C, wmOperator *op)
CollectionEditData data{};
data.scene = scene;
data.space_outliner = space_outliner;
+ data.is_liboverride_allowed = true;
+ data.is_liboverride_hierarchy_root_allowed = true;
data.collections_to_edit = BLI_gset_ptr_new(__func__);
outliner_tree_traverse(space_outliner,
@@ -1273,6 +1305,8 @@ static int collection_flag_exec(bContext *C, wmOperator *op)
CollectionEditData data{};
data.scene = scene;
data.space_outliner = space_outliner;
+ data.is_liboverride_allowed = true;
+ data.is_liboverride_hierarchy_root_allowed = true;
data.collections_to_edit = BLI_gset_ptr_new(__func__);
const bool has_layer_collection = space_outliner->outlinevis == SO_VIEW_LAYER;
diff --git a/source/blender/editors/space_outliner/outliner_dragdrop.cc b/source/blender/editors/space_outliner/outliner_dragdrop.cc
index edd2e5f304f..30b81b2ecb2 100644
--- a/source/blender/editors/space_outliner/outliner_dragdrop.cc
+++ b/source/blender/editors/space_outliner/outliner_dragdrop.cc
@@ -46,7 +46,9 @@
static Collection *collection_parent_from_ID(ID *id);
-/* ******************** Drop Target Find *********************** */
+/* -------------------------------------------------------------------- */
+/** \name Drop Target Find
+ * \{ */
static TreeElement *outliner_dropzone_element(TreeElement *te,
const float fmval[2],
@@ -254,7 +256,11 @@ static int outliner_get_insert_index(TreeElement *drag_te,
return BLI_findindex(listbase, drop_te->directdata);
}
-/* ******************** Parent Drop Operator *********************** */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Parent Drop Operator
+ * \{ */
static bool parent_drop_allowed(TreeElement *te, Object *potential_child)
{
@@ -443,7 +449,11 @@ void OUTLINER_OT_parent_drop(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
}
-/* ******************** Parent Clear Operator *********************** */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Parent Clear Operator
+ * \{ */
static bool parent_clear_poll(bContext *C, wmDrag *drag, const wmEvent *event)
{
@@ -527,7 +537,11 @@ void OUTLINER_OT_parent_clear(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
}
-/* ******************** Scene Drop Operator *********************** */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Scene Drop Operator
+ * \{ */
static bool scene_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event)
{
@@ -592,7 +606,11 @@ void OUTLINER_OT_scene_drop(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
}
-/* ******************** Material Drop Operator *********************** */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Material Drop Operator
+ * \{ */
static bool material_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event)
{
@@ -641,15 +659,19 @@ void OUTLINER_OT_material_drop(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
}
-/* ******************** Data Stack Drop Operator *********************** */
+/** \} */
-/* A generic operator to allow drag and drop for modifiers, constraints,
+/* -------------------------------------------------------------------- */
+/** \name Data Stack Drop Operator
+ *
+ * A generic operator to allow drag and drop for modifiers, constraints,
* and shader effects which all share the same UI stack layout.
*
* The following operations are allowed:
* - Reordering within an object.
* - Copying a single modifier/constraint/effect to another object.
- * - Copying (linking) an object's modifiers/constraints/effects to another. */
+ * - Copying (linking) an object's modifiers/constraints/effects to another.
+ * \{ */
enum eDataStackDropAction {
DATA_STACK_DROP_REORDER,
@@ -1069,7 +1091,11 @@ void OUTLINER_OT_datastack_drop(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
}
-/* ******************** Collection Drop Operator *********************** */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Collection Drop Operator
+ * \{ */
struct CollectionDrop {
Collection *from;
@@ -1350,7 +1376,11 @@ void OUTLINER_OT_collection_drop(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
}
-/* ********************* Outliner Drag Operator ******************** */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Outliner Drag Operator
+ * \{ */
#define OUTLINER_DRAG_SCOLL_OUTSIDE_PAD 7 /* In UI units */
@@ -1358,9 +1388,12 @@ static TreeElement *outliner_item_drag_element_find(SpaceOutliner *space_outline
ARegion *region,
const wmEvent *event)
{
- /* NOTE: using EVT_TWEAK_ events to trigger dragging is fine,
+ /* NOTE: using click-drag events to trigger dragging is fine,
* it sends coordinates from where dragging was started */
- const float my = UI_view2d_region_to_view_y(&region->v2d, event->mval[1]);
+ int mval[2];
+ WM_event_drag_start_mval(event, region, mval);
+
+ const float my = UI_view2d_region_to_view_y(&region->v2d, mval[1]);
return outliner_find_item_at_y(space_outliner, &space_outliner->tree, my);
}
@@ -1372,6 +1405,9 @@ static int outliner_item_drag_drop_invoke(bContext *C,
SpaceOutliner *space_outliner = CTX_wm_space_outliner(C);
TreeElement *te = outliner_item_drag_element_find(space_outliner, region, event);
+ int mval[2];
+ WM_event_drag_start_mval(event, region, mval);
+
if (!te) {
return (OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH);
}
@@ -1383,8 +1419,7 @@ static int outliner_item_drag_drop_invoke(bContext *C,
}
float view_mval[2];
- UI_view2d_region_to_view(
- &region->v2d, event->mval[0], event->mval[1], &view_mval[0], &view_mval[1]);
+ UI_view2d_region_to_view(&region->v2d, mval[0], mval[1], &view_mval[0], &view_mval[1]);
if (outliner_item_is_co_within_close_toggle(te, view_mval[0])) {
return (OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH);
}
@@ -1399,7 +1434,7 @@ static int outliner_item_drag_drop_invoke(bContext *C,
PointerRNA op_ptr;
WM_operator_properties_create_ptr(&op_ptr, ot);
RNA_float_set(&op_ptr, "outside_padding", OUTLINER_DRAG_SCOLL_OUTSIDE_PAD);
- WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &op_ptr);
+ WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &op_ptr, event);
WM_operator_properties_free(&op_ptr);
}
@@ -1523,7 +1558,11 @@ void OUTLINER_OT_item_drag_drop(wmOperatorType *ot)
#undef OUTLINER_DRAG_SCOLL_OUTSIDE_PAD
-/* *************************** Drop Boxes ************************** */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Drop Boxes
+ * \{ */
void outliner_dropboxes(void)
{
@@ -1546,3 +1585,5 @@ void outliner_dropboxes(void)
nullptr,
collection_drop_tooltip);
}
+
+/** \} */
diff --git a/source/blender/editors/space_outliner/outliner_draw.cc b/source/blender/editors/space_outliner/outliner_draw.cc
index 53de7d582b6..7b62b28abc5 100644
--- a/source/blender/editors/space_outliner/outliner_draw.cc
+++ b/source/blender/editors/space_outliner/outliner_draw.cc
@@ -1721,7 +1721,7 @@ static void outliner_draw_userbuts(uiBlock *block,
LISTBASE_FOREACH (TreeElement *, te, lb) {
TreeStoreElem *tselem = TREESTORE(te);
- if (te->ys + 2 * UI_UNIT_Y >= region->v2d.cur.ymin && te->ys <= region->v2d.cur.ymax) {
+ if (outliner_is_element_in_view(te, &region->v2d)) {
if (tselem->type == TSE_SOME_ID) {
uiBut *bt;
ID *id = tselem->id;
@@ -1792,8 +1792,7 @@ static bool outliner_draw_overrides_buts(uiBlock *block,
LISTBASE_FOREACH (TreeElement *, te, lb) {
bool item_has_warnings = false;
- const bool do_draw = (te->ys + 2 * UI_UNIT_Y >= region->v2d.cur.ymin &&
- te->ys <= region->v2d.cur.ymax);
+ const bool do_draw = outliner_is_element_in_view(te, &region->v2d);
int but_flag = UI_BUT_DRAG_LOCK;
const char *tip = nullptr;
@@ -1903,7 +1902,7 @@ static void outliner_draw_rnabuts(
LISTBASE_FOREACH (TreeElement *, te, lb) {
TreeStoreElem *tselem = TREESTORE(te);
- if (te->ys + 2 * UI_UNIT_Y >= region->v2d.cur.ymin && te->ys <= region->v2d.cur.ymax) {
+ if (outliner_is_element_in_view(te, &region->v2d)) {
if (TreeElementRNAProperty *te_rna_prop = tree_element_cast<TreeElementRNAProperty>(te)) {
ptr = te_rna_prop->getPointerRNA();
prop = te_rna_prop->getPropertyRNA();
@@ -2348,10 +2347,8 @@ static BIFIconID tree_element_get_icon_from_id(const ID *id)
if (text->filepath == nullptr || (text->flags & TXT_ISMEM)) {
return ICON_FILE_TEXT;
}
- else {
- /* Helps distinguish text-based formats like the file-browser does. */
- return (BIFIconID)ED_file_extension_icon(text->filepath);
- }
+ /* Helps distinguish text-based formats like the file-browser does. */
+ return (BIFIconID)ED_file_extension_icon(text->filepath);
}
case ID_GR:
return ICON_OUTLINER_COLLECTION;
diff --git a/source/blender/editors/space_outliner/outliner_edit.cc b/source/blender/editors/space_outliner/outliner_edit.cc
index 6916f5fe502..a60e082f6a5 100644
--- a/source/blender/editors/space_outliner/outliner_edit.cc
+++ b/source/blender/editors/space_outliner/outliner_edit.cc
@@ -225,8 +225,11 @@ static int outliner_item_openclose_invoke(bContext *C, wmOperator *op, const wmE
const bool toggle_all = RNA_boolean_get(op->ptr, "all");
float view_mval[2];
- UI_view2d_region_to_view(
- &region->v2d, event->mval[0], event->mval[1], &view_mval[0], &view_mval[1]);
+
+ int mval[2];
+ WM_event_drag_start_mval(event, region, mval);
+
+ UI_view2d_region_to_view(&region->v2d, mval[0], mval[1], &view_mval[0], &view_mval[1]);
TreeElement *te = outliner_find_item_at_y(space_outliner, &space_outliner->tree, view_mval[1]);
@@ -726,7 +729,7 @@ void id_remap_fn(bContext *C,
RNA_enum_set(&op_props, "id_type", GS(tselem->id->name));
RNA_enum_set_identifier(C, &op_props, "old_id", tselem->id->name + 2);
- WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &op_props);
+ WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &op_props, nullptr);
WM_operator_properties_free(&op_props);
}
@@ -872,10 +875,10 @@ static int lib_relocate(
RNA_string_set(&op_props, "directory", dir);
RNA_string_set(&op_props, "filename", filename);
- ret = WM_operator_name_call_ptr(C, ot, WM_OP_EXEC_DEFAULT, &op_props);
+ ret = WM_operator_name_call_ptr(C, ot, WM_OP_EXEC_DEFAULT, &op_props, nullptr);
}
else {
- ret = WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &op_props);
+ ret = WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &op_props, nullptr);
}
WM_operator_properties_free(&op_props);
diff --git a/source/blender/editors/space_outliner/outliner_intern.hh b/source/blender/editors/space_outliner/outliner_intern.hh
index 0516758e887..a9bdcc56787 100644
--- a/source/blender/editors/space_outliner/outliner_intern.hh
+++ b/source/blender/editors/space_outliner/outliner_intern.hh
@@ -33,6 +33,7 @@ struct ViewLayer;
struct bContext;
struct bContextDataResult;
struct bPoseChannel;
+struct View2D;
struct wmKeyConfig;
struct wmOperatorType;
@@ -218,8 +219,9 @@ typedef enum {
/* is the current element open? if so we also show children */
#define TSELEM_OPEN(telm, sv) \
- (((telm)->flag & TSE_CLOSED) == 0 || \
- (SEARCHING_OUTLINER(sv) && ((telm)->flag & TSE_CHILDSEARCH)))
+ (CHECK_TYPE_INLINE(telm, TreeStoreElem *), \
+ (((telm)->flag & TSE_CLOSED) == 0 || \
+ (SEARCHING_OUTLINER(sv) && ((telm)->flag & TSE_CHILDSEARCH))))
/**
* Container to avoid passing around these variables to many functions.
@@ -545,7 +547,7 @@ void outliner_collection_delete(struct bContext *C,
struct Main *bmain,
struct Scene *scene,
struct ReportList *reports,
- bool hierarchy);
+ bool do_hierarchy);
void OUTLINER_OT_collection_new(struct wmOperatorType *ot);
void OUTLINER_OT_collection_duplicate_linked(struct wmOperatorType *ot);
@@ -642,10 +644,16 @@ float outliner_restrict_columns_width(const struct SpaceOutliner *space_outliner
*/
TreeElement *outliner_find_element_with_flag(const ListBase *lb, short flag);
/**
- * Find if element is visible in the outliner tree.
+ * Find if element is visible in the outliner tree, i.e. if all of its parents are expanded.
+ * Doesn't check if the item is in view-bounds, for that use #outliner_is_element_in_view().
*/
bool outliner_is_element_visible(const TreeElement *te);
/**
+ * Check if the element is displayed within the view bounds. Doesn't check if all parents are
+ * open/uncollapsed.
+ */
+bool outliner_is_element_in_view(const TreeElement *te, const struct View2D *v2d);
+/**
* Scroll view vertically while keeping within total bounds.
*/
void outliner_scroll_view(struct SpaceOutliner *space_outliner,
diff --git a/source/blender/editors/space_outliner/outliner_ops.cc b/source/blender/editors/space_outliner/outliner_ops.cc
index 69a691aeb50..8baac45666e 100644
--- a/source/blender/editors/space_outliner/outliner_ops.cc
+++ b/source/blender/editors/space_outliner/outliner_ops.cc
@@ -11,7 +11,9 @@
#include "outliner_intern.hh"
-/* ************************** registration **********************************/
+/* -------------------------------------------------------------------- */
+/** \name Registration
+ * \{ */
void outliner_operatortypes(void)
{
@@ -97,3 +99,5 @@ void outliner_keymap(wmKeyConfig *keyconf)
{
WM_keymap_ensure(keyconf, "Outliner", SPACE_OUTLINER, 0);
}
+
+/** \} */
diff --git a/source/blender/editors/space_outliner/outliner_select.cc b/source/blender/editors/space_outliner/outliner_select.cc
index c6b9d9577b5..233051f31ff 100644
--- a/source/blender/editors/space_outliner/outliner_select.cc
+++ b/source/blender/editors/space_outliner/outliner_select.cc
@@ -68,6 +68,10 @@
using namespace blender::ed::outliner;
+/* -------------------------------------------------------------------- */
+/** \name Internal Utilities
+ * \{ */
+
/**
* \note changes to selection are by convention and not essential.
*
@@ -199,8 +203,11 @@ void outliner_item_mode_toggle(bContext *C,
}
}
-/* ****************************************************** */
-/* Outliner Element Selection/Activation on Click */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Outliner Element Selection/Activation on Click Operator
+ * \{ */
static void tree_element_viewlayer_activate(bContext *C, TreeElement *te)
{
@@ -1662,10 +1669,15 @@ static int outliner_item_do_activate_from_cursor(bContext *C,
/* Event can enter-key, then it opens/closes. */
static int outliner_item_activate_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
+ ARegion *region = CTX_wm_region(C);
+
const bool extend = RNA_boolean_get(op->ptr, "extend");
const bool use_range = RNA_boolean_get(op->ptr, "extend_range");
const bool deselect_all = RNA_boolean_get(op->ptr, "deselect_all");
- return outliner_item_do_activate_from_cursor(C, event->mval, extend, use_range, deselect_all);
+
+ int mval[2];
+ WM_event_drag_start_mval(event, region, mval);
+ return outliner_item_do_activate_from_cursor(C, mval, extend, use_range, deselect_all);
}
void OUTLINER_OT_item_activate(wmOperatorType *ot)
@@ -1695,9 +1707,12 @@ void OUTLINER_OT_item_activate(wmOperatorType *ot)
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
-/* ****************************************************** */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Box Select Operator
+ * \{ */
-/* **************** Box Select Tool ****************** */
static void outliner_item_box_select(bContext *C,
SpaceOutliner *space_outliner,
Scene *scene,
@@ -1756,8 +1771,9 @@ static int outliner_box_select_invoke(bContext *C, wmOperator *op, const wmEvent
float view_mval[2];
const bool tweak = RNA_boolean_get(op->ptr, "tweak");
- UI_view2d_region_to_view(
- &region->v2d, event->mval[0], event->mval[1], &view_mval[0], &view_mval[1]);
+ int mval[2];
+ WM_event_drag_start_mval(event, region, mval);
+ UI_view2d_region_to_view(&region->v2d, mval[0], mval[1], &view_mval[0], &view_mval[1]);
/* Find element clicked on */
TreeElement *te = outliner_find_item_at_y(space_outliner, &space_outliner->tree, view_mval[1]);
@@ -1803,9 +1819,11 @@ void OUTLINER_OT_select_box(wmOperatorType *ot)
WM_operator_properties_select_operation_simple(ot);
}
-/* ****************************************************** */
+/** \} */
-/* **************** Walk Select Tool ****************** */
+/* -------------------------------------------------------------------- */
+/** \name Walk Select Operator
+ * \{ */
/* Given a tree element return the rightmost child that is visible in the outliner */
static TreeElement *outliner_find_rightmost_visible_child(SpaceOutliner *space_outliner,
@@ -2030,4 +2048,4 @@ void OUTLINER_OT_select_walk(wmOperatorType *ot)
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
-/* ****************************************************** */
+/** \} */
diff --git a/source/blender/editors/space_outliner/outliner_tools.cc b/source/blender/editors/space_outliner/outliner_tools.cc
index 8fcf967bce8..3b14c8542bd 100644
--- a/source/blender/editors/space_outliner/outliner_tools.cc
+++ b/source/blender/editors/space_outliner/outliner_tools.cc
@@ -1705,7 +1705,16 @@ static TreeTraversalAction outliner_find_objects_to_delete(TreeElement *te, void
return TRAVERSE_SKIP_CHILDS;
}
- BLI_gset_add(objects_to_delete, tselem->id);
+ ID *id = tselem->id;
+
+ if (ID_IS_OVERRIDE_LIBRARY_REAL(id)) {
+ if (!ID_IS_OVERRIDE_LIBRARY_HIERARCHY_ROOT(id)) {
+ /* Only allow deletion of liboverride objects if they are root overrides. */
+ return TRAVERSE_SKIP_CHILDS;
+ }
+ }
+
+ BLI_gset_add(objects_to_delete, id);
return TRAVERSE_CONTINUE;
}
@@ -2216,14 +2225,14 @@ static int outliner_id_operation_exec(bContext *C, wmOperator *op)
}
case OUTLINER_IDOP_COPY: {
wm->op_undo_depth++;
- WM_operator_name_call(C, "OUTLINER_OT_id_copy", WM_OP_INVOKE_DEFAULT, nullptr);
+ WM_operator_name_call(C, "OUTLINER_OT_id_copy", WM_OP_INVOKE_DEFAULT, nullptr, nullptr);
wm->op_undo_depth--;
/* No need for undo, this operation does not change anything... */
break;
}
case OUTLINER_IDOP_PASTE: {
wm->op_undo_depth++;
- WM_operator_name_call(C, "OUTLINER_OT_id_paste", WM_OP_INVOKE_DEFAULT, nullptr);
+ WM_operator_name_call(C, "OUTLINER_OT_id_paste", WM_OP_INVOKE_DEFAULT, nullptr, nullptr);
wm->op_undo_depth--;
ED_outliner_select_sync_from_all_tag(C);
ED_undo_push(C, "Paste");
@@ -2595,7 +2604,8 @@ static int outliner_animdata_operation_exec(bContext *C, wmOperator *op)
case OUTLINER_ANIMOP_SET_ACT:
/* delegate once again... */
wm->op_undo_depth++;
- WM_operator_name_call(C, "OUTLINER_OT_action_set", WM_OP_INVOKE_REGION_WIN, nullptr);
+ WM_operator_name_call(
+ C, "OUTLINER_OT_action_set", WM_OP_INVOKE_REGION_WIN, nullptr, nullptr);
wm->op_undo_depth--;
ED_undo_push(C, "Set active action");
break;
@@ -2618,7 +2628,7 @@ static int outliner_animdata_operation_exec(bContext *C, wmOperator *op)
nullptr);
WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN, nullptr);
- /* ED_undo_push(C, "Refresh Drivers"); No undo needed - shouldn't have any impact? */
+ // ED_undo_push(C, "Refresh Drivers"); /* No undo needed - shouldn't have any impact? */
break;
case OUTLINER_ANIMOP_CLEAR_DRV:
diff --git a/source/blender/editors/space_outliner/outliner_tree.cc b/source/blender/editors/space_outliner/outliner_tree.cc
index 06a5918f25c..1a772287dfa 100644
--- a/source/blender/editors/space_outliner/outliner_tree.cc
+++ b/source/blender/editors/space_outliner/outliner_tree.cc
@@ -74,8 +74,9 @@ using namespace blender::ed::outliner;
/* prototypes */
static int outliner_exclude_filter_get(const SpaceOutliner *space_outliner);
-/* ********************************************************* */
-/* Persistent Data */
+/* -------------------------------------------------------------------- */
+/** \name Persistent Data
+ * \{ */
static void outliner_storage_cleanup(SpaceOutliner *space_outliner)
{
@@ -175,8 +176,11 @@ static void check_persistent(
BKE_outliner_treehash_add_element(space_outliner->runtime->treehash, tselem);
}
-/* ********************************************************* */
-/* Tree Management */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Tree Management
+ * \{ */
void outliner_free_tree(ListBase *tree)
{
@@ -960,10 +964,14 @@ TreeElement *outliner_add_collection_recursive(SpaceOutliner *space_outliner,
return ten;
}
+/** \} */
+
/* ======================================================= */
/* Generic Tree Building helpers - order these are called is top to bottom */
-/* Sorting ------------------------------------------------------ */
+/* -------------------------------------------------------------------- */
+/** \name Tree Sorting Helper
+ * \{ */
struct tTreeSort {
TreeElement *te;
@@ -1195,7 +1203,11 @@ static void outliner_collections_children_sort(ListBase *lb)
}
}
-/* Filtering ----------------------------------------------- */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Tree Filtering Helper
+ * \{ */
struct OutlinerTreeElementFocus {
TreeStoreElem *tselem;
@@ -1644,8 +1656,11 @@ static void outliner_clear_newid_from_main(Main *bmain)
FOREACH_MAIN_ID_END;
}
-/* ======================================================= */
-/* Main Tree Building API */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Main Tree Building API
+ * \{ */
void outliner_build_tree(Main *mainvar,
Scene *scene,
@@ -1707,3 +1722,5 @@ void outliner_build_tree(Main *mainvar,
* as this expects valid IDs in this pointer, not random unknown data. */
outliner_clear_newid_from_main(mainvar);
}
+
+/** \} */
diff --git a/source/blender/editors/space_outliner/outliner_utils.cc b/source/blender/editors/space_outliner/outliner_utils.cc
index b49a2416b38..556f87617f6 100644
--- a/source/blender/editors/space_outliner/outliner_utils.cc
+++ b/source/blender/editors/space_outliner/outliner_utils.cc
@@ -386,6 +386,11 @@ bool outliner_is_element_visible(const TreeElement *te)
return true;
}
+bool outliner_is_element_in_view(const TreeElement *te, const View2D *v2d)
+{
+ return ((te->ys + UI_UNIT_Y) >= v2d->cur.ymin) && (te->ys <= v2d->cur.ymax);
+}
+
bool outliner_item_is_co_over_name_icons(const TreeElement *te, float view_co_x)
{
/* Special case: count area left of Scene Collection as empty space */
diff --git a/source/blender/editors/space_sequencer/sequencer_draw.c b/source/blender/editors/space_sequencer/sequencer_draw.c
index 5ac4363e63d..0d0042c4656 100644
--- a/source/blender/editors/space_sequencer/sequencer_draw.c
+++ b/source/blender/editors/space_sequencer/sequencer_draw.c
@@ -476,7 +476,7 @@ static void draw_seq_waveform_overlay(View2D *v2d,
bool is_line_strip = (value_max - value_min < 0.05f);
- if (was_line_strip != -1 && is_line_strip != was_line_strip) {
+ if (!ELEM(was_line_strip, -1, is_line_strip)) {
/* If the previously added strip type isn't the same as the current one,
* add transition areas so they transition smoothly between each other. */
if (is_line_strip) {
@@ -2690,12 +2690,7 @@ void draw_timeline_seq(const bContext *C, ARegion *region)
GPU_depth_test(GPU_DEPTH_NONE);
UI_GetThemeColor3fv(TH_BACK, col);
- if (ed && ed->metastack.first) {
- GPU_clear_color(col[0], col[1], col[2] - 0.1f, 0.0f);
- }
- else {
- GPU_clear_color(col[0], col[1], col[2], 0.0f);
- }
+ GPU_clear_color(col[0], col[1], col[2], 0.0f);
UI_view2d_view_ortho(v2d);
draw_seq_timeline_channels(v2d);
diff --git a/source/blender/editors/space_text/text_draw.c b/source/blender/editors/space_text/text_draw.c
index 8fefd258f7a..d3fc3e9d352 100644
--- a/source/blender/editors/space_text/text_draw.c
+++ b/source/blender/editors/space_text/text_draw.c
@@ -36,7 +36,9 @@
#include "WM_api.h"
#include "WM_types.h"
-/******************** text font drawing ******************/
+/* -------------------------------------------------------------------- */
+/** \name Text Font Drawing
+ * \{ */
typedef struct TextDrawContext {
int font_id;
@@ -141,7 +143,11 @@ static void format_draw_color(const TextDrawContext *tdc, char formatchar)
}
}
-/************************** draw text *****************************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Draw Text
+ * \{ */
/**
* Notes on word-wrap
@@ -556,7 +562,11 @@ static void text_draw(const SpaceText *st,
flatten_string_free(&fs);
}
-/************************ cache utilities *****************************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Cache Utilities
+ * \{ */
typedef struct DrawCache {
int *line_height;
@@ -766,7 +776,11 @@ void text_free_caches(SpaceText *st)
}
}
-/************************ word-wrap utilities *****************************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Word-Wrap Utilities
+ * \{ */
/* cache should be updated in caller */
static int text_get_visible_lines_no(const SpaceText *st, int lineno)
@@ -845,7 +859,11 @@ int text_get_total_lines(SpaceText *st, ARegion *region)
return drawcache->total_lines;
}
-/************************ draw scrollbar *****************************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Draw Scroll-Bar
+ * \{ */
static void calc_text_rcts(SpaceText *st, ARegion *region, rcti *scroll, rcti *back)
{
@@ -1006,7 +1024,11 @@ static void draw_textscroll(const SpaceText *st, rcti *scroll, rcti *back)
col);
}
-/*********************** draw documentation *******************************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Draw Documentation
+ * \{ */
#if 0
static void draw_documentation(const SpaceText *st, ARegion *region)
@@ -1086,7 +1108,7 @@ static void draw_documentation(const SpaceText *st, ARegion *region)
if (*p == '\r' && *(++p) != '\n') {
*(--p) = '\n'; /* Fix line endings */
}
- if (*p == ' ' || *p == '\t') {
+ if (ELEM(*p, ' ', '\t')) {
br = i;
}
else if (*p == '\n') {
@@ -1118,7 +1140,11 @@ static void draw_documentation(const SpaceText *st, ARegion *region)
}
#endif
-/*********************** draw suggestion list *******************************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Draw Suggestion List
+ * \{ */
static void draw_suggestion_list(const SpaceText *st, const TextDrawContext *tdc, ARegion *region)
{
@@ -1221,7 +1247,11 @@ static void draw_suggestion_list(const SpaceText *st, const TextDrawContext *tdc
}
}
-/*********************** draw cursor ************************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Draw Cursor
+ * \{ */
static void draw_text_decoration(SpaceText *st, ARegion *region)
{
@@ -1383,7 +1413,11 @@ static void draw_text_decoration(SpaceText *st, ARegion *region)
immUnbindProgram();
}
-/******************* draw matching brackets *********************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Draw Matching Brackets
+ * \{ */
static void draw_brackets(const SpaceText *st, const TextDrawContext *tdc, ARegion *region)
{
@@ -1544,7 +1578,11 @@ static void draw_brackets(const SpaceText *st, const TextDrawContext *tdc, ARegi
}
}
-/*********************** main region drawing *************************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Main Region Drawing
+ * \{ */
void draw_text_main(SpaceText *st, ARegion *region)
{
@@ -1707,7 +1745,11 @@ void draw_text_main(SpaceText *st, ARegion *region)
text_font_end(&tdc);
}
-/************************** update ***************************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Update & Coordinate Conversion
+ * \{ */
void text_update_character_width(SpaceText *st)
{
@@ -1861,3 +1903,5 @@ error:
r_pixel_co[0] = r_pixel_co[1] = -1;
return false;
}
+
+/** \} */
diff --git a/source/blender/editors/space_text/text_ops.c b/source/blender/editors/space_text/text_ops.c
index 3c29b32c2fa..15fea301b1c 100644
--- a/source/blender/editors/space_text/text_ops.c
+++ b/source/blender/editors/space_text/text_ops.c
@@ -649,13 +649,13 @@ static int text_save_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-static int text_save_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
+static int text_save_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
Text *text = CTX_data_edit_text(C);
/* Internal and texts without a filepath will go to "Save As". */
if (text->filepath == NULL || (text->flags & TXT_ISMEM)) {
- WM_operator_name_call(C, "TEXT_OT_save_as", WM_OP_INVOKE_DEFAULT, NULL);
+ WM_operator_name_call(C, "TEXT_OT_save_as", WM_OP_INVOKE_DEFAULT, NULL, event);
return OPERATOR_CANCELLED;
}
return text_save_exec(C, op);
@@ -1098,10 +1098,10 @@ static int text_indent_or_autocomplete_exec(bContext *C, wmOperator *UNUSED(op))
TextLine *line = text->curl;
bool text_before_cursor = text->curc != 0 && !ELEM(line->line[text->curc - 1], ' ', '\t');
if (text_before_cursor && (txt_has_sel(text) == false)) {
- WM_operator_name_call(C, "TEXT_OT_autocomplete", WM_OP_INVOKE_DEFAULT, NULL);
+ WM_operator_name_call(C, "TEXT_OT_autocomplete", WM_OP_INVOKE_DEFAULT, NULL, NULL);
}
else {
- WM_operator_name_call(C, "TEXT_OT_indent", WM_OP_EXEC_DEFAULT, NULL);
+ WM_operator_name_call(C, "TEXT_OT_indent", WM_OP_EXEC_DEFAULT, NULL, NULL);
}
return OPERATOR_FINISHED;
}
diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c
index 4656540c19b..e2a027837a7 100644
--- a/source/blender/editors/space_view3d/space_view3d.c
+++ b/source/blender/editors/space_view3d/space_view3d.c
@@ -801,7 +801,7 @@ static void view3d_lightcache_update(bContext *C)
RNA_int_set(&op_ptr, "delay", 200);
RNA_enum_set_identifier(C, &op_ptr, "subset", "DIRTY");
- WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &op_ptr);
+ WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &op_ptr, NULL);
WM_operator_properties_free(&op_ptr);
}
diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c
index b4cf08f69fe..e52ff062302 100644
--- a/source/blender/editors/space_view3d/view3d_edit.c
+++ b/source/blender/editors/space_view3d/view3d_edit.c
@@ -507,19 +507,17 @@ void VIEW3D_OT_view_persportho(wmOperatorType *ot)
* Wraps walk/fly modes.
* \{ */
-static int view3d_navigate_invoke(bContext *C,
- wmOperator *UNUSED(op),
- const wmEvent *UNUSED(event))
+static int view3d_navigate_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
{
eViewNavigation_Method mode = U.navigation_mode;
switch (mode) {
case VIEW_NAVIGATION_FLY:
- WM_operator_name_call(C, "VIEW3D_OT_fly", WM_OP_INVOKE_DEFAULT, NULL);
+ WM_operator_name_call(C, "VIEW3D_OT_fly", WM_OP_INVOKE_DEFAULT, NULL, event);
break;
case VIEW_NAVIGATION_WALK:
default:
- WM_operator_name_call(C, "VIEW3D_OT_walk", WM_OP_INVOKE_DEFAULT, NULL);
+ WM_operator_name_call(C, "VIEW3D_OT_walk", WM_OP_INVOKE_DEFAULT, NULL, event);
break;
}
diff --git a/source/blender/editors/space_view3d/view3d_gizmo_ruler.c b/source/blender/editors/space_view3d/view3d_gizmo_ruler.c
index 9b954cd817b..3a8a28dc2a1 100644
--- a/source/blender/editors/space_view3d/view3d_gizmo_ruler.c
+++ b/source/blender/editors/space_view3d/view3d_gizmo_ruler.c
@@ -455,6 +455,19 @@ static bool view3d_ruler_item_mousemove(const bContext *C,
return false;
}
+/**
+ * When the gizmo-group has been created immediately before running an operator
+ * to manipulate rulers, it's possible the new gizmo-group has not yet been initialized.
+ * in 3.0 this happened because left-click drag would both select and add a new ruler,
+ * significantly increasing the likelihood of this happening.
+ * Workaround this crash by checking the gizmo's custom-data has not been cleared.
+ * The key-map has also been modified not to trigger this bug, see T95591.
+ */
+static bool gizmo_ruler_check_for_operator(const wmGizmoGroup *gzgroup)
+{
+ return gzgroup->customdata != NULL;
+}
+
/** \} */
/* -------------------------------------------------------------------- */
@@ -1069,7 +1082,8 @@ static int gizmo_ruler_invoke(bContext *C, wmGizmo *gz, const wmEvent *event)
ARegion *region = ruler_info->region;
- const float mval_fl[2] = {UNPACK2(event->mval)};
+ float mval_fl[2];
+ WM_event_drag_start_mval_fl(event, region, mval_fl);
#ifdef USE_AXIS_CONSTRAINTS
ruler_info->constrain_axis = CONSTRAIN_AXIS_NONE;
@@ -1294,13 +1308,21 @@ static int view3d_ruler_add_invoke(bContext *C, wmOperator *op, const wmEvent *e
wmGizmoGroup *gzgroup = WM_gizmomap_group_find(gzmap, view3d_gzgt_ruler_id);
const bool use_depth = (v3d->shading.type >= OB_SOLID);
+ if (!gizmo_ruler_check_for_operator(gzgroup)) {
+ return OPERATOR_CANCELLED;
+ }
+
+ int mval[2];
+ WM_event_drag_start_mval(event, region, mval);
+
/* Create new line */
RulerItem *ruler_item;
ruler_item = ruler_item_add(gzgroup);
/* This is a little weak, but there is no real good way to tweak directly. */
WM_gizmo_highlight_set(gzmap, &ruler_item->gz);
- if (WM_operator_name_call(C, "GIZMOGROUP_OT_gizmo_tweak", WM_OP_INVOKE_REGION_WIN, NULL) ==
+ if (WM_operator_name_call(
+ C, "GIZMOGROUP_OT_gizmo_tweak", WM_OP_INVOKE_REGION_WIN, NULL, event) ==
OPERATOR_RUNNING_MODAL) {
RulerInfo *ruler_info = gzgroup->customdata;
RulerInteraction *inter = ruler_item->gz.interaction_data;
@@ -1312,7 +1334,7 @@ static int view3d_ruler_add_invoke(bContext *C, wmOperator *op, const wmEvent *e
depsgraph,
ruler_info,
ruler_item,
- event->mval,
+ mval,
false
#ifndef USE_SNAP_DETECT_FROM_KEYMAP_HACK
,
@@ -1327,7 +1349,7 @@ static int view3d_ruler_add_invoke(bContext *C, wmOperator *op, const wmEvent *e
else {
negate_v3_v3(inter->drag_start_co, rv3d->ofs);
copy_v3_v3(ruler_item->co[0], inter->drag_start_co);
- view3d_ruler_item_project(ruler_info, ruler_item->co[0], event->mval);
+ view3d_ruler_item_project(ruler_info, ruler_item->co[0], mval);
}
copy_v3_v3(ruler_item->co[2], ruler_item->co[0]);
@@ -1369,6 +1391,9 @@ static int view3d_ruler_remove_invoke(bContext *C, wmOperator *op, const wmEvent
wmGizmoMap *gzmap = region->gizmo_map;
wmGizmoGroup *gzgroup = WM_gizmomap_group_find(gzmap, view3d_gzgt_ruler_id);
if (gzgroup) {
+ if (!gizmo_ruler_check_for_operator(gzgroup)) {
+ return OPERATOR_CANCELLED;
+ }
RulerInfo *ruler_info = gzgroup->customdata;
if (ruler_info->item_active) {
RulerItem *ruler_item = ruler_info->item_active;
diff --git a/source/blender/editors/space_view3d/view3d_navigate.c b/source/blender/editors/space_view3d/view3d_navigate.c
index daf534ce0ba..50d7626a57d 100644
--- a/source/blender/editors/space_view3d/view3d_navigate.c
+++ b/source/blender/editors/space_view3d/view3d_navigate.c
@@ -1153,16 +1153,16 @@ static int view_axis_exec(bContext *C, wmOperator *op)
float quat_test[4];
if (viewnum == RV3D_VIEW_LEFT) {
- axis_angle_to_quat(quat_rotate, rv3d->viewinv[1], -M_PI / 2.0f);
+ axis_angle_to_quat(quat_rotate, rv3d->viewinv[1], -M_PI_2);
}
else if (viewnum == RV3D_VIEW_RIGHT) {
- axis_angle_to_quat(quat_rotate, rv3d->viewinv[1], M_PI / 2.0f);
+ axis_angle_to_quat(quat_rotate, rv3d->viewinv[1], M_PI_2);
}
else if (viewnum == RV3D_VIEW_TOP) {
- axis_angle_to_quat(quat_rotate, rv3d->viewinv[0], -M_PI / 2.0f);
+ axis_angle_to_quat(quat_rotate, rv3d->viewinv[0], -M_PI_2);
}
else if (viewnum == RV3D_VIEW_BOTTOM) {
- axis_angle_to_quat(quat_rotate, rv3d->viewinv[0], M_PI / 2.0f);
+ axis_angle_to_quat(quat_rotate, rv3d->viewinv[0], M_PI_2);
}
else if (viewnum == RV3D_VIEW_FRONT) {
unit_qt(quat_rotate);
diff --git a/source/blender/editors/space_view3d/view3d_navigate_dolly.c b/source/blender/editors/space_view3d/view3d_navigate_dolly.c
index 7b6b119294d..29ccc352950 100644
--- a/source/blender/editors/space_view3d/view3d_navigate_dolly.c
+++ b/source/blender/editors/space_view3d/view3d_navigate_dolly.c
@@ -134,11 +134,11 @@ static int viewdolly_modal(bContext *C, wmOperator *op, const wmEvent *event)
event_code = VIEW_CONFIRM;
break;
case VIEWROT_MODAL_SWITCH_MOVE:
- WM_operator_name_call(C, "VIEW3D_OT_move", WM_OP_INVOKE_DEFAULT, NULL);
+ WM_operator_name_call(C, "VIEW3D_OT_move", WM_OP_INVOKE_DEFAULT, NULL, event);
event_code = VIEW_CONFIRM;
break;
case VIEWROT_MODAL_SWITCH_ROTATE:
- WM_operator_name_call(C, "VIEW3D_OT_rotate", WM_OP_INVOKE_DEFAULT, NULL);
+ WM_operator_name_call(C, "VIEW3D_OT_rotate", WM_OP_INVOKE_DEFAULT, NULL, event);
event_code = VIEW_CONFIRM;
break;
}
diff --git a/source/blender/editors/space_view3d/view3d_navigate_move.c b/source/blender/editors/space_view3d/view3d_navigate_move.c
index 071643e9314..af8419894b1 100644
--- a/source/blender/editors/space_view3d/view3d_navigate_move.c
+++ b/source/blender/editors/space_view3d/view3d_navigate_move.c
@@ -76,11 +76,11 @@ static int viewmove_modal(bContext *C, wmOperator *op, const wmEvent *event)
event_code = VIEW_CONFIRM;
break;
case VIEWROT_MODAL_SWITCH_ZOOM:
- WM_operator_name_call(C, "VIEW3D_OT_zoom", WM_OP_INVOKE_DEFAULT, NULL);
+ WM_operator_name_call(C, "VIEW3D_OT_zoom", WM_OP_INVOKE_DEFAULT, NULL, event);
event_code = VIEW_CONFIRM;
break;
case VIEWROT_MODAL_SWITCH_ROTATE:
- WM_operator_name_call(C, "VIEW3D_OT_rotate", WM_OP_INVOKE_DEFAULT, NULL);
+ WM_operator_name_call(C, "VIEW3D_OT_rotate", WM_OP_INVOKE_DEFAULT, NULL, event);
event_code = VIEW_CONFIRM;
break;
}
diff --git a/source/blender/editors/space_view3d/view3d_navigate_roll.c b/source/blender/editors/space_view3d/view3d_navigate_roll.c
index 9c070fb0341..ea21eed6445 100644
--- a/source/blender/editors/space_view3d/view3d_navigate_roll.c
+++ b/source/blender/editors/space_view3d/view3d_navigate_roll.c
@@ -99,11 +99,11 @@ static int viewroll_modal(bContext *C, wmOperator *op, const wmEvent *event)
event_code = VIEW_CONFIRM;
break;
case VIEWROT_MODAL_SWITCH_MOVE:
- WM_operator_name_call(C, "VIEW3D_OT_move", WM_OP_INVOKE_DEFAULT, NULL);
+ WM_operator_name_call(C, "VIEW3D_OT_move", WM_OP_INVOKE_DEFAULT, NULL, event);
event_code = VIEW_CONFIRM;
break;
case VIEWROT_MODAL_SWITCH_ROTATE:
- WM_operator_name_call(C, "VIEW3D_OT_rotate", WM_OP_INVOKE_DEFAULT, NULL);
+ WM_operator_name_call(C, "VIEW3D_OT_rotate", WM_OP_INVOKE_DEFAULT, NULL, event);
event_code = VIEW_CONFIRM;
break;
}
diff --git a/source/blender/editors/space_view3d/view3d_navigate_rotate.c b/source/blender/editors/space_view3d/view3d_navigate_rotate.c
index 11de5463cdb..a53c71bd823 100644
--- a/source/blender/editors/space_view3d/view3d_navigate_rotate.c
+++ b/source/blender/editors/space_view3d/view3d_navigate_rotate.c
@@ -327,11 +327,11 @@ static int viewrotate_modal(bContext *C, wmOperator *op, const wmEvent *event)
event_code = VIEW_APPLY;
break;
case VIEWROT_MODAL_SWITCH_ZOOM:
- WM_operator_name_call(C, "VIEW3D_OT_zoom", WM_OP_INVOKE_DEFAULT, NULL);
+ WM_operator_name_call(C, "VIEW3D_OT_zoom", WM_OP_INVOKE_DEFAULT, NULL, event);
event_code = VIEW_CONFIRM;
break;
case VIEWROT_MODAL_SWITCH_MOVE:
- WM_operator_name_call(C, "VIEW3D_OT_move", WM_OP_INVOKE_DEFAULT, NULL);
+ WM_operator_name_call(C, "VIEW3D_OT_move", WM_OP_INVOKE_DEFAULT, NULL, event);
event_code = VIEW_CONFIRM;
break;
}
diff --git a/source/blender/editors/space_view3d/view3d_navigate_zoom.c b/source/blender/editors/space_view3d/view3d_navigate_zoom.c
index 5f6f9fde324..c744ef85236 100644
--- a/source/blender/editors/space_view3d/view3d_navigate_zoom.c
+++ b/source/blender/editors/space_view3d/view3d_navigate_zoom.c
@@ -370,11 +370,11 @@ static int viewzoom_modal(bContext *C, wmOperator *op, const wmEvent *event)
event_code = VIEW_CONFIRM;
break;
case VIEWROT_MODAL_SWITCH_MOVE:
- WM_operator_name_call(C, "VIEW3D_OT_move", WM_OP_INVOKE_DEFAULT, NULL);
+ WM_operator_name_call(C, "VIEW3D_OT_move", WM_OP_INVOKE_DEFAULT, NULL, event);
event_code = VIEW_CONFIRM;
break;
case VIEWROT_MODAL_SWITCH_ROTATE:
- WM_operator_name_call(C, "VIEW3D_OT_rotate", WM_OP_INVOKE_DEFAULT, NULL);
+ WM_operator_name_call(C, "VIEW3D_OT_rotate", WM_OP_INVOKE_DEFAULT, NULL, event);
event_code = VIEW_CONFIRM;
break;
}
diff --git a/source/blender/editors/space_view3d/view3d_placement.c b/source/blender/editors/space_view3d/view3d_placement.c
index 98fb914cda9..05d4372723b 100644
--- a/source/blender/editors/space_view3d/view3d_placement.c
+++ b/source/blender/editors/space_view3d/view3d_placement.c
@@ -733,9 +733,11 @@ static void view3d_interactive_add_begin(bContext *C, wmOperator *op, const wmEv
* the current cursor location instead of the drag-start. */
if (event->val == KM_CLICK_DRAG) {
/* Set this flag so snapping always updated. */
+ int mval[2];
+ WM_event_drag_start_mval(event, ipd->region, mval);
int flag_orig = snap_state_new->flag;
snap_state_new->flag |= V3D_SNAPCURSOR_TOGGLE_ALWAYS_TRUE;
- ED_view3d_cursor_snap_data_get(snap_state_new, C, event->mval[0], event->mval[1]);
+ ED_view3d_cursor_snap_data_get(snap_state_new, C, mval[0], mval[1]);
snap_state_new->flag = flag_orig;
}
}
@@ -1151,7 +1153,7 @@ static int view3d_interactive_add_modal(bContext *C, wmOperator *op, const wmEve
RNA_float_set(&op_props, "radius2", 0.0f);
}
- WM_operator_name_call_ptr(C, ot, WM_OP_EXEC_DEFAULT, &op_props);
+ WM_operator_name_call_ptr(C, ot, WM_OP_EXEC_DEFAULT, &op_props, NULL);
WM_operator_properties_free(&op_props);
}
else {
@@ -1168,7 +1170,8 @@ static int view3d_interactive_add_modal(bContext *C, wmOperator *op, const wmEve
}
if (do_cursor_update) {
- const float mval_fl[2] = {UNPACK2(event->mval)};
+ float mval_fl[2];
+ WM_event_drag_start_mval_fl(event, region, mval_fl);
/* Calculate the snap location on mouse-move or when toggling snap. */
ipd->is_snap_found = false;
diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.c
index e380a08dcc7..5d3168908d6 100644
--- a/source/blender/editors/space_view3d/view3d_select.c
+++ b/source/blender/editors/space_view3d/view3d_select.c
@@ -1628,7 +1628,7 @@ static Base *object_mouse_select_menu(bContext *C,
RNA_boolean_set(&ptr, "extend", extend);
RNA_boolean_set(&ptr, "deselect", deselect);
RNA_boolean_set(&ptr, "toggle", toggle);
- WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &ptr);
+ WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &ptr, NULL);
WM_operator_properties_free(&ptr);
BLI_linklist_free(linklist.list, NULL);
@@ -1851,7 +1851,7 @@ static bool bone_mouse_select_menu(bContext *C,
RNA_boolean_set(&ptr, "extend", extend);
RNA_boolean_set(&ptr, "deselect", deselect);
RNA_boolean_set(&ptr, "toggle", toggle);
- WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &ptr);
+ WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &ptr, NULL);
WM_operator_properties_free(&ptr);
BLI_linklist_free(base_list.list, NULL);
diff --git a/source/blender/editors/space_view3d/view3d_snap.c b/source/blender/editors/space_view3d/view3d_snap.c
index bcdc962a860..2f51b2dce3b 100644
--- a/source/blender/editors/space_view3d/view3d_snap.c
+++ b/source/blender/editors/space_view3d/view3d_snap.c
@@ -600,9 +600,9 @@ static int snap_selected_to_cursor_exec(bContext *C, wmOperator *op)
const int pivot_point = scene->toolsettings->transform_pivot_point;
if (snap_selected_to_location(C, snap_target_global, use_offset, pivot_point, true)) {
- return OPERATOR_CANCELLED;
+ return OPERATOR_FINISHED;
}
- return OPERATOR_FINISHED;
+ return OPERATOR_CANCELLED;
}
void VIEW3D_OT_snap_selected_to_cursor(wmOperatorType *ot)
diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c
index fd01f708ed2..92d312cebce 100644
--- a/source/blender/editors/transform/transform.c
+++ b/source/blender/editors/transform/transform.c
@@ -1513,14 +1513,42 @@ void saveTransform(bContext *C, TransInfo *t, wmOperator *op)
if (t->flag & T_MODAL) {
/* do we check for parameter? */
if (transformModeUseSnap(t)) {
- if (!(t->modifiers & MOD_SNAP) != !(ts->snap_flag & SCE_SNAP)) {
+ if (!(t->modifiers & MOD_SNAP) != !(t->tsnap.flag & SCE_SNAP)) {
+ char *snap_flag_ptr;
+
+ wmMsgParams_RNA msg_key_params = {{0}};
+ RNA_pointer_create(&t->scene->id, &RNA_ToolSettings, ts, &msg_key_params.ptr);
+
+ _WM_MESSAGE_EXTERN_BEGIN;
+ extern PropertyRNA rna_ToolSettings_use_snap;
+ extern PropertyRNA rna_ToolSettings_use_snap_node;
+ extern PropertyRNA rna_ToolSettings_use_snap_sequencer;
+ extern PropertyRNA rna_ToolSettings_use_snap_uv;
+ _WM_MESSAGE_EXTERN_END;
+ if (t->spacetype == SPACE_NODE) {
+ snap_flag_ptr = &ts->snap_flag_node;
+ msg_key_params.prop = &rna_ToolSettings_use_snap_node;
+ }
+ else if (t->spacetype == SPACE_IMAGE) {
+ snap_flag_ptr = &ts->snap_uv_flag;
+ msg_key_params.prop = &rna_ToolSettings_use_snap_uv;
+ }
+ else if (t->spacetype == SPACE_SEQ) {
+ snap_flag_ptr = &ts->snap_flag_seq;
+ msg_key_params.prop = &rna_ToolSettings_use_snap_sequencer;
+ }
+ else {
+ snap_flag_ptr = &ts->snap_flag;
+ msg_key_params.prop = &rna_ToolSettings_use_snap;
+ }
+
if (t->modifiers & MOD_SNAP) {
- ts->snap_flag |= SCE_SNAP;
+ *snap_flag_ptr |= SCE_SNAP;
}
else {
- ts->snap_flag &= ~SCE_SNAP;
+ *snap_flag_ptr &= ~SCE_SNAP;
}
- WM_msg_publish_rna_prop(t->mbus, &t->scene->id, ts, ToolSettings, use_snap);
+ WM_msg_publish_rna_params(t->mbus, &msg_key_params);
}
}
}
@@ -1819,7 +1847,15 @@ bool initTransform(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
use_accurate = true;
}
}
- initMouseInput(t, &t->mouse, t->center2d, event->mval, use_accurate);
+
+ int mval[2];
+ if (t->flag & T_EVENT_DRAG_START) {
+ WM_event_drag_start_mval(event, t->region, mval);
+ }
+ else {
+ copy_v2_v2_int(mval, event->mval);
+ }
+ initMouseInput(t, &t->mouse, t->center2d, mval, use_accurate);
}
transform_mode_init(t, op, mode);
diff --git a/source/blender/editors/transform/transform.h b/source/blender/editors/transform/transform.h
index 3ee5868d5be..713cf487ac7 100644
--- a/source/blender/editors/transform/transform.h
+++ b/source/blender/editors/transform/transform.h
@@ -137,6 +137,9 @@ typedef enum {
/** Runs auto-merge & splits. */
T_AUTOSPLIT = 1 << 21,
+ /** Use drag-start position of the event, otherwise use the cursor coordinates (unmodified). */
+ T_EVENT_DRAG_START = (1 << 22),
+
/** No cursor wrapping on region bounds */
T_NO_CURSOR_WRAP = 1 << 23,
} eTFlag;
@@ -292,7 +295,8 @@ typedef struct TransSnapPoint {
} TransSnapPoint;
typedef struct TransSnap {
- short mode;
+ char flag;
+ char mode;
short target;
short modePoint;
short modeSelect;
diff --git a/source/blender/editors/transform/transform_convert.c b/source/blender/editors/transform/transform_convert.c
index 4a2169b381e..dbe67bd0d66 100644
--- a/source/blender/editors/transform/transform_convert.c
+++ b/source/blender/editors/transform/transform_convert.c
@@ -1113,7 +1113,8 @@ static void init_TransDataContainers(TransInfo *t,
&objects_len,
{
.object_mode = object_mode,
- .no_dup_data = true,
+ /* Pose transform operates on `ob->pose` so don't skip duplicate object-data. */
+ .no_dup_data = (object_mode & OB_MODE_POSE) == 0,
});
free_objects = true;
}
diff --git a/source/blender/editors/transform/transform_convert_mesh.c b/source/blender/editors/transform/transform_convert_mesh.c
index b8530293d3e..d4b12142162 100644
--- a/source/blender/editors/transform/transform_convert_mesh.c
+++ b/source/blender/editors/transform/transform_convert_mesh.c
@@ -1449,7 +1449,7 @@ static void VertsToTransData(TransInfo *t,
td->ext = NULL;
td->val = NULL;
td->extra = eve;
- if (t->mode == TFM_BWEIGHT || t->mode == TFM_VERT_CREASE) {
+ if (ELEM(t->mode, TFM_BWEIGHT, TFM_VERT_CREASE)) {
td->val = bweight;
td->ival = *bweight;
}
diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c
index 8987325145c..3b9e2a982dc 100644
--- a/source/blender/editors/transform/transform_generics.c
+++ b/source/blender/editors/transform/transform_generics.c
@@ -206,6 +206,12 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
t->obedit_type = -1;
}
+ if (t->options & CTX_CURSOR) {
+ /* Cursor should always use the drag start as the combination of click-drag to place & move
+ * doesn't work well if the click location isn't used when transforming. */
+ t->flag |= T_EVENT_DRAG_START;
+ }
+
/* Many kinds of transform only use a single handle. */
if (t->data_container == NULL) {
t->data_container = MEM_callocN(sizeof(*t->data_container), __func__);
@@ -216,7 +222,12 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
int mval[2];
if (event) {
- copy_v2_v2_int(mval, event->mval);
+ if (t->flag & T_EVENT_DRAG_START) {
+ WM_event_drag_start_mval(event, region, mval);
+ }
+ else {
+ copy_v2_v2_int(mval, event->mval);
+ }
}
else {
zero_v2_int(mval);
diff --git a/source/blender/editors/transform/transform_gizmo_3d.c b/source/blender/editors/transform/transform_gizmo_3d.c
index f07fadb7fc1..5381785091a 100644
--- a/source/blender/editors/transform/transform_gizmo_3d.c
+++ b/source/blender/editors/transform/transform_gizmo_3d.c
@@ -1824,7 +1824,7 @@ static void WIDGETGROUP_gizmo_draw_prepare(const bContext *C, wmGizmoGroup *gzgr
static void WIDGETGROUP_gizmo_invoke_prepare(const bContext *C,
wmGizmoGroup *gzgroup,
wmGizmo *gz,
- const wmEvent *UNUSED(event))
+ const wmEvent *event)
{
GizmoGroup *ggd = gzgroup->customdata;
@@ -1867,9 +1867,8 @@ static void WIDGETGROUP_gizmo_invoke_prepare(const bContext *C,
}
if (axis != -1) {
- wmWindow *win = CTX_wm_window(C);
/* Swap single axis for two-axis constraint. */
- bool flip = (win->eventstate->modifier & KM_SHIFT) != 0;
+ const bool flip = (event->modifier & KM_SHIFT) != 0;
BLI_assert(axis_idx != -1);
const short axis_type = gizmo_get_axis_type(axis_idx);
if (axis_type != MAN_AXES_ROTATE) {
diff --git a/source/blender/editors/transform/transform_mode.c b/source/blender/editors/transform/transform_mode.c
index 6162dfc9bb5..2fd81486bb6 100644
--- a/source/blender/editors/transform/transform_mode.c
+++ b/source/blender/editors/transform/transform_mode.c
@@ -1212,8 +1212,8 @@ void transform_mode_init(TransInfo *t, wmOperator *op, const int mode)
}
/* TODO(germano): Some of these operations change the `t->mode`.
- * This can be bad for Redo.
- * BLI_assert(t->mode == mode); */
+ * This can be bad for Redo. */
+ // BLI_assert(t->mode == mode);
}
void transform_mode_default_modal_orientation_set(TransInfo *t, int type)
diff --git a/source/blender/editors/transform/transform_ops.c b/source/blender/editors/transform/transform_ops.c
index 936aca7d2e0..efbb7375af4 100644
--- a/source/blender/editors/transform/transform_ops.c
+++ b/source/blender/editors/transform/transform_ops.c
@@ -1311,9 +1311,7 @@ static void TRANSFORM_OT_transform(struct wmOperatorType *ot)
P_ALIGN_SNAP | P_GPENCIL_EDIT | P_CENTER);
}
-static int transform_from_gizmo_invoke(bContext *C,
- wmOperator *UNUSED(op),
- const wmEvent *UNUSED(event))
+static int transform_from_gizmo_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
{
bToolRef *tref = WM_toolsystem_ref_from_context(C);
if (tref) {
@@ -1343,7 +1341,7 @@ static int transform_from_gizmo_invoke(bContext *C,
PointerRNA op_ptr;
WM_operator_properties_create_ptr(&op_ptr, ot);
RNA_boolean_set(&op_ptr, "release_confirm", true);
- WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &op_ptr);
+ WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &op_ptr, event);
WM_operator_properties_free(&op_ptr);
return OPERATOR_FINISHED;
}
diff --git a/source/blender/editors/transform/transform_snap.c b/source/blender/editors/transform/transform_snap.c
index 2f3c021ba38..7ace6343985 100644
--- a/source/blender/editors/transform/transform_snap.c
+++ b/source/blender/editors/transform/transform_snap.c
@@ -561,7 +561,22 @@ static bool bm_face_is_snap_target(BMFace *f, void *UNUSED(user_data))
return true;
}
-static short snap_mode_from_scene(TransInfo *t)
+static char snap_flag_from_spacetype(TransInfo *t)
+{
+ ToolSettings *ts = t->settings;
+ if (t->spacetype == SPACE_NODE) {
+ return ts->snap_flag_node;
+ }
+ else if (t->spacetype == SPACE_IMAGE) {
+ return ts->snap_uv_flag;
+ }
+ else if (t->spacetype == SPACE_SEQ) {
+ return ts->snap_flag_seq;
+ }
+ return ts->snap_flag;
+}
+
+static short snap_mode_from_spacetype(TransInfo *t)
{
ToolSettings *ts = t->settings;
short r_snap_mode = SCE_SNAP_MODE_INCREMENT;
@@ -580,7 +595,7 @@ static short snap_mode_from_scene(TransInfo *t)
else if (t->spacetype == SPACE_SEQ) {
r_snap_mode = SEQ_tool_settings_snap_mode_get(t->scene);
}
- else if (ELEM(t->spacetype, SPACE_VIEW3D, SPACE_IMAGE) && !(t->options & CTX_CAMERA)) {
+ else if ((t->spacetype == SPACE_VIEW3D) && !(t->options & CTX_CAMERA)) {
/* All obedit types will match. */
const int obedit_type = t->obedit_type;
if ((t->options & (CTX_GPENCIL_STROKES | CTX_CURSOR | CTX_OBMODE_XFORM_OBDATA)) ||
@@ -652,7 +667,7 @@ static short snap_select_type_get(TransInfo *t)
static void initSnappingMode(TransInfo *t)
{
ToolSettings *ts = t->settings;
- t->tsnap.mode = snap_mode_from_scene(t);
+ t->tsnap.mode = snap_mode_from_spacetype(t);
t->tsnap.modeSelect = snap_select_type_get(t);
if ((t->spacetype != SPACE_VIEW3D) || !(ts->snap_mode & SCE_SNAP_MODE_FACE)) {
@@ -701,10 +716,9 @@ static void initSnappingMode(TransInfo *t)
void initSnapping(TransInfo *t, wmOperator *op)
{
- ToolSettings *ts = t->settings;
- short snap_target = t->settings->snap_target;
-
resetSnapping(t);
+ t->tsnap.flag = snap_flag_from_spacetype(t);
+ short snap_target = t->settings->snap_target;
/* if snap property exists */
PropertyRNA *prop;
@@ -745,19 +759,14 @@ void initSnapping(TransInfo *t, wmOperator *op)
}
/* use scene defaults only when transform is modal */
else if (t->flag & T_MODAL) {
- if (ELEM(t->spacetype, SPACE_VIEW3D, SPACE_IMAGE, SPACE_NODE)) {
- if (transformModeUseSnap(t) && (ts->snap_flag & SCE_SNAP)) {
- t->modifiers |= MOD_SNAP;
- }
-
- t->tsnap.align = ((t->settings->snap_flag & SCE_SNAP_ROTATE) != 0);
- t->tsnap.project = ((t->settings->snap_flag & SCE_SNAP_PROJECT) != 0);
- t->tsnap.snap_self = !((t->settings->snap_flag & SCE_SNAP_NO_SELF) != 0);
- t->tsnap.peel = ((t->settings->snap_flag & SCE_SNAP_PROJECT) != 0);
- }
- else if ((t->spacetype == SPACE_SEQ) && (ts->snap_flag & SCE_SNAP_SEQ)) {
+ if (transformModeUseSnap(t) && (t->tsnap.flag & SCE_SNAP)) {
t->modifiers |= MOD_SNAP;
}
+
+ t->tsnap.align = ((t->tsnap.flag & SCE_SNAP_ROTATE) != 0);
+ t->tsnap.project = ((t->tsnap.flag & SCE_SNAP_PROJECT) != 0);
+ t->tsnap.snap_self = !((t->tsnap.flag & SCE_SNAP_NO_SELF) != 0);
+ t->tsnap.peel = ((t->tsnap.flag & SCE_SNAP_PROJECT) != 0);
}
t->tsnap.target = snap_target;
diff --git a/source/blender/editors/uvedit/uvedit_intern.h b/source/blender/editors/uvedit/uvedit_intern.h
index b2a411147a5..b73a02e8de6 100644
--- a/source/blender/editors/uvedit/uvedit_intern.h
+++ b/source/blender/editors/uvedit/uvedit_intern.h
@@ -155,8 +155,8 @@ void UV_OT_shortest_path_select(struct wmOperatorType *ot);
/* uvedit_select.c */
-bool uvedit_select_is_any_selected(struct Scene *scene, struct Object *obedit);
-bool uvedit_select_is_any_selected_multi(struct Scene *scene,
+bool uvedit_select_is_any_selected(const struct Scene *scene, struct Object *obedit);
+bool uvedit_select_is_any_selected_multi(const struct Scene *scene,
struct Object **objects,
uint objects_len);
/**
diff --git a/source/blender/editors/uvedit/uvedit_ops.c b/source/blender/editors/uvedit/uvedit_ops.c
index bbf84ee74d7..fe6f9f0d513 100644
--- a/source/blender/editors/uvedit/uvedit_ops.c
+++ b/source/blender/editors/uvedit/uvedit_ops.c
@@ -1518,11 +1518,11 @@ static int uv_hide_exec(bContext *C, wmOperator *op)
BM_face_select_set(em->bm, efa, false);
break;
}
- else if (UV_VERT_SEL_TEST(luv, !swap) && (ts->uv_selectmode == UV_SELECT_VERTEX)) {
+ if (UV_VERT_SEL_TEST(luv, !swap) && (ts->uv_selectmode == UV_SELECT_VERTEX)) {
BM_face_select_set(em->bm, efa, false);
break;
}
- else if (ts->uv_selectmode == UV_SELECT_ISLAND) {
+ if (ts->uv_selectmode == UV_SELECT_ISLAND) {
BM_face_select_set(em->bm, efa, false);
break;
}
@@ -1533,18 +1533,21 @@ static int uv_hide_exec(bContext *C, wmOperator *op)
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
if (UV_EDGE_SEL_TEST(luv, !swap) && (ts->uv_selectmode == UV_SELECT_EDGE)) {
- if (em->selectmode == SCE_SELECT_EDGE)
+ if (em->selectmode == SCE_SELECT_EDGE) {
BM_edge_select_set(em->bm, l->e, false);
+ }
else {
BM_vert_select_set(em->bm, l->v, false);
BM_vert_select_set(em->bm, l->next->v, false);
}
}
else if (UV_VERT_SEL_TEST(luv, !swap) && (ts->uv_selectmode != UV_SELECT_EDGE)) {
- if (em->selectmode == SCE_SELECT_EDGE)
+ if (em->selectmode == SCE_SELECT_EDGE) {
BM_edge_select_set(em->bm, l->e, false);
- else
+ }
+ else {
BM_vert_select_set(em->bm, l->v, false);
+ }
}
}
if (!swap) {
diff --git a/source/blender/editors/uvedit/uvedit_parametrizer.c b/source/blender/editors/uvedit/uvedit_parametrizer.c
index 53b8a541dba..3f7c7745bff 100644
--- a/source/blender/editors/uvedit/uvedit_parametrizer.c
+++ b/source/blender/editors/uvedit/uvedit_parametrizer.c
@@ -2039,7 +2039,7 @@ static float p_collapse_cost(PEdge *edge, PEdge *pair)
float *co1 = e->next->vert->co;
float *co2 = e->next->next->vert->co;
- if ((e->face != oldf1) && (e->face != oldf2)) {
+ if (!ELEM(e->face, oldf1, oldf2)) {
float tetrav2[3], tetrav3[3];
/* tetrahedron volume = (1/3!)*|a.(b x c)| */
@@ -2059,7 +2059,7 @@ static float p_collapse_cost(PEdge *edge, PEdge *pair)
a1 = a1 - M_PI / 3.0;
a2 = a2 - M_PI / 3.0;
a3 = a3 - M_PI / 3.0;
- shapeold = (a1 * a1 + a2 * a2 + a3 * a3) / ((M_PI / 2) * (M_PI / 2));
+ shapeold = (a1 * a1 + a2 * a2 + a3 * a3) / (M_PI_2 * M_PI_2);
nshapeold++;
}
@@ -2068,7 +2068,7 @@ static float p_collapse_cost(PEdge *edge, PEdge *pair)
a1 = a1 - M_PI / 3.0;
a2 = a2 - M_PI / 3.0;
a3 = a3 - M_PI / 3.0;
- shapenew = (a1 * a1 + a2 * a2 + a3 * a3) / ((M_PI / 2) * (M_PI / 2));
+ shapenew = (a1 * a1 + a2 * a2 + a3 * a3) / (M_PI_2 * M_PI_2);
nshapenew++;
}
@@ -3730,7 +3730,7 @@ static float p_chart_minimum_area_angle(PChart *chart)
minarea = 1e10;
minangle = 0.0;
- while (rotated <= (float)(M_PI / 2.0)) { /* INVESTIGATE: how far to rotate? */
+ while (rotated <= (float)M_PI_2) { /* INVESTIGATE: how far to rotate? */
/* rotate with the smallest angle */
i_min = 0;
mina = 1e10;
@@ -3777,8 +3777,8 @@ static float p_chart_minimum_area_angle(PChart *chart)
}
/* try keeping rotation as small as possible */
- if (minangle > (float)(M_PI / 4)) {
- minangle -= (float)(M_PI / 2.0);
+ if (minangle > (float)M_PI_4) {
+ minangle -= (float)M_PI_2;
}
MEM_freeN(angles);
diff --git a/source/blender/editors/uvedit/uvedit_select.c b/source/blender/editors/uvedit/uvedit_select.c
index ca66981cd3a..938b798f4b6 100644
--- a/source/blender/editors/uvedit/uvedit_select.c
+++ b/source/blender/editors/uvedit/uvedit_select.c
@@ -55,18 +55,21 @@
#include "uvedit_intern.h"
-static void uv_select_all_perform(Scene *scene, Object *obedit, int action);
-
-static void uv_select_all_perform_multi_ex(
- Scene *scene, Object **objects, const uint objects_len, int action, const Object *ob_exclude);
-static void uv_select_all_perform_multi(Scene *scene,
+static void uv_select_all_perform(const Scene *scene, Object *obedit, int action);
+
+static void uv_select_all_perform_multi_ex(const Scene *scene,
+ Object **objects,
+ const uint objects_len,
+ int action,
+ const Object *ob_exclude);
+static void uv_select_all_perform_multi(const Scene *scene,
Object **objects,
const uint objects_len,
int action);
-static void uv_select_flush_from_tag_face(Scene *scene, Object *obedit, const bool select);
-static void uv_select_flush_from_tag_loop(Scene *scene, Object *obedit, const bool select);
-static void uv_select_flush_from_loop_edge_flag(Scene *scene, BMEditMesh *em);
+static void uv_select_flush_from_tag_face(const Scene *scene, Object *obedit, const bool select);
+static void uv_select_flush_from_tag_loop(const Scene *scene, Object *obedit, const bool select);
+static void uv_select_flush_from_loop_edge_flag(const Scene *scene, BMEditMesh *em);
static void uv_select_tag_update_for_object(Depsgraph *depsgraph,
const ToolSettings *ts,
@@ -435,7 +438,7 @@ void uvedit_edge_select_shared_vert(const Scene *scene,
const bool do_history,
const int cd_loop_uv_offset)
{
- BLI_assert((sticky_flag == SI_STICKY_LOC) || (sticky_flag == SI_STICKY_VERTEX));
+ BLI_assert(ELEM(sticky_flag, SI_STICKY_LOC, SI_STICKY_VERTEX));
/* Set edge flags. Rely on this for face visibility checks */
uvedit_edge_select_set_noflush(scene, l, select, sticky_flag, cd_loop_uv_offset);
@@ -644,7 +647,7 @@ void uvedit_uv_select_shared_vert(const Scene *scene,
const bool do_history,
const int cd_loop_uv_offset)
{
- BLI_assert((sticky_flag == SI_STICKY_LOC) || (sticky_flag == SI_STICKY_VERTEX));
+ BLI_assert(ELEM(sticky_flag, SI_STICKY_LOC, SI_STICKY_VERTEX));
BMEdge *e_first, *e_iter;
e_first = e_iter = l->e;
@@ -1200,7 +1203,10 @@ bool uvedit_vert_is_all_other_faces_selected(const Scene *scene,
/**
* Clear specified UV flag (vert/edge/pinned).
*/
-static void bm_uv_flag_clear(Scene *scene, BMesh *bm, const int flag, const int cd_loop_uv_offset)
+static void bm_uv_flag_clear(const Scene *scene,
+ BMesh *bm,
+ const int flag,
+ const int cd_loop_uv_offset)
{
BMFace *efa;
BMLoop *l;
@@ -1223,12 +1229,13 @@ static void bm_uv_flag_clear(Scene *scene, BMesh *bm, const int flag, const int
*
* \{ */
-void ED_uvedit_selectmode_flush(Scene *scene, BMEditMesh *em)
+void ED_uvedit_selectmode_flush(const Scene *scene, BMEditMesh *em)
{
- ToolSettings *ts = scene->toolsettings;
+ const ToolSettings *ts = scene->toolsettings;
const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
BLI_assert((ts->uv_flag & UV_SYNC_SELECTION) == 0);
+ UNUSED_VARS_NDEBUG(ts);
/* Vertex Mode only. */
if (ts->uv_selectmode & UV_SELECT_VERTEX) {
@@ -1261,14 +1268,15 @@ void ED_uvedit_selectmode_flush(Scene *scene, BMEditMesh *em)
/** \name UV Flush selection (up/down)
* \{ */
-/* Careful when using this in face select mode.
- * For face selections with sticky mode enabled, this can create invalid selection states. */
-void uvedit_select_flush(Scene *scene, BMEditMesh *em)
+void uvedit_select_flush(const Scene *scene, BMEditMesh *em)
{
- ToolSettings *ts = scene->toolsettings;
+ /* Careful when using this in face select mode.
+ * For face selections with sticky mode enabled, this can create invalid selection states. */
+ const ToolSettings *ts = scene->toolsettings;
const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
BLI_assert((ts->uv_flag & UV_SYNC_SELECTION) == 0);
+ UNUSED_VARS_NDEBUG(ts);
BMFace *efa;
BMLoop *l;
@@ -1289,12 +1297,13 @@ void uvedit_select_flush(Scene *scene, BMEditMesh *em)
}
}
-void uvedit_deselect_flush(Scene *scene, BMEditMesh *em)
+void uvedit_deselect_flush(const Scene *scene, BMEditMesh *em)
{
- ToolSettings *ts = scene->toolsettings;
+ const ToolSettings *ts = scene->toolsettings;
const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
BLI_assert((ts->uv_flag & UV_SYNC_SELECTION) == 0);
+ UNUSED_VARS_NDEBUG(ts);
BMFace *efa;
BMLoop *l;
@@ -1711,7 +1720,7 @@ static int uv_select_edgering(Scene *scene, Object *obedit, UvNearestHit *hit, c
if (select && uvedit_edge_select_test(scene, l_step, cd_loop_uv_offset)) {
break;
}
- else if (!select && !uvedit_edge_select_test(scene, l_step, cd_loop_uv_offset)) {
+ if (!select && !uvedit_edge_select_test(scene, l_step, cd_loop_uv_offset)) {
break;
}
}
@@ -2163,7 +2172,7 @@ void UV_OT_select_less(wmOperatorType *ot)
/** \name (De)Select All Operator
* \{ */
-bool uvedit_select_is_any_selected(Scene *scene, Object *obedit)
+bool uvedit_select_is_any_selected(const Scene *scene, Object *obedit)
{
const ToolSettings *ts = scene->toolsettings;
BMEditMesh *em = BKE_editmesh_from_object(obedit);
@@ -2191,7 +2200,9 @@ bool uvedit_select_is_any_selected(Scene *scene, Object *obedit)
return false;
}
-bool uvedit_select_is_any_selected_multi(Scene *scene, Object **objects, const uint objects_len)
+bool uvedit_select_is_any_selected_multi(const Scene *scene,
+ Object **objects,
+ const uint objects_len)
{
bool found = false;
for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
@@ -2204,7 +2215,7 @@ bool uvedit_select_is_any_selected_multi(Scene *scene, Object **objects, const u
return found;
}
-static void uv_select_all(Scene *scene, BMEditMesh *em, bool select_all)
+static void uv_select_all(const Scene *scene, BMEditMesh *em, bool select_all)
{
BMFace *efa;
BMLoop *l;
@@ -2223,7 +2234,7 @@ static void uv_select_all(Scene *scene, BMEditMesh *em, bool select_all)
}
}
-static void uv_select_invert(Scene *scene, BMEditMesh *em)
+static void uv_select_invert(const Scene *scene, BMEditMesh *em)
{
const ToolSettings *ts = scene->toolsettings;
BLI_assert((ts->uv_flag & UV_SYNC_SELECTION) == 0);
@@ -2240,13 +2251,13 @@ static void uv_select_invert(Scene *scene, BMEditMesh *em)
}
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
- if ((uv_selectmode == UV_SELECT_EDGE) || (uv_selectmode == UV_SELECT_FACE)) {
+ if (ELEM(uv_selectmode, UV_SELECT_EDGE, UV_SELECT_FACE)) {
/* Use #MLOOPUV_EDGESEL to flag edges that must be selected. */
luv->flag ^= MLOOPUV_EDGESEL;
luv->flag &= ~MLOOPUV_VERTSEL;
}
/* Use #MLOOPUV_VERTSEL to flag verts that must be selected. */
- else if ((uv_selectmode == UV_SELECT_VERTEX) || (uv_selectmode == UV_SELECT_ISLAND)) {
+ else if (ELEM(uv_selectmode, UV_SELECT_VERTEX, UV_SELECT_ISLAND)) {
luv->flag ^= MLOOPUV_VERTSEL;
luv->flag &= ~MLOOPUV_EDGESEL;
}
@@ -2254,15 +2265,15 @@ static void uv_select_invert(Scene *scene, BMEditMesh *em)
}
/* Flush based on uv vert/edge flags and current UV select mode */
- if ((uv_selectmode == UV_SELECT_EDGE) || (uv_selectmode == UV_SELECT_FACE)) {
+ if (ELEM(uv_selectmode, UV_SELECT_EDGE, UV_SELECT_FACE)) {
uv_select_flush_from_loop_edge_flag(scene, em);
}
- else if ((uv_selectmode == UV_SELECT_VERTEX) || (uv_selectmode == UV_SELECT_ISLAND)) {
+ else if (ELEM(uv_selectmode, UV_SELECT_VERTEX, UV_SELECT_ISLAND)) {
uvedit_select_flush(scene, em);
}
}
-static void uv_select_all_perform(Scene *scene, Object *obedit, int action)
+static void uv_select_all_perform(const Scene *scene, Object *obedit, int action)
{
const ToolSettings *ts = scene->toolsettings;
BMEditMesh *em = BKE_editmesh_from_object(obedit);
@@ -2303,8 +2314,11 @@ static void uv_select_all_perform(Scene *scene, Object *obedit, int action)
}
}
-static void uv_select_all_perform_multi_ex(
- Scene *scene, Object **objects, const uint objects_len, int action, const Object *ob_exclude)
+static void uv_select_all_perform_multi_ex(const Scene *scene,
+ Object **objects,
+ const uint objects_len,
+ int action,
+ const Object *ob_exclude)
{
if (action == SEL_TOGGLE) {
action = uvedit_select_is_any_selected_multi(scene, objects, objects_len) ? SEL_DESELECT :
@@ -2320,7 +2334,7 @@ static void uv_select_all_perform_multi_ex(
}
}
-static void uv_select_all_perform_multi(Scene *scene,
+static void uv_select_all_perform_multi(const Scene *scene,
Object **objects,
const uint objects_len,
int action)
@@ -3133,7 +3147,7 @@ static void uv_select_tag_update_for_object(Depsgraph *depsgraph,
/**
* helper function for #uv_select_flush_from_tag_loop and uv_select_flush_from_tag_face
*/
-static void uv_select_flush_from_tag_sticky_loc_internal(Scene *scene,
+static void uv_select_flush_from_tag_sticky_loc_internal(const Scene *scene,
BMEditMesh *em,
UvVertMap *vmap,
const uint efa_index,
@@ -3191,7 +3205,7 @@ static void uv_select_flush_from_tag_sticky_loc_internal(Scene *scene,
* \note This function is very similar to #uv_select_flush_from_tag_loop,
* be sure to update both upon changing.
*/
-static void uv_select_flush_from_tag_face(Scene *scene, Object *obedit, const bool select)
+static void uv_select_flush_from_tag_face(const Scene *scene, Object *obedit, const bool select)
{
/* Selecting UV Faces with some modes requires us to change
* the selection in other faces (depending on the sticky mode).
@@ -3207,7 +3221,7 @@ static void uv_select_flush_from_tag_face(Scene *scene, Object *obedit, const bo
const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
if ((ts->uv_flag & UV_SYNC_SELECTION) == 0 &&
- ((ts->uv_sticky == SI_STICKY_VERTEX) || (ts->uv_sticky == SI_STICKY_LOC))) {
+ ELEM(ts->uv_sticky, SI_STICKY_VERTEX, SI_STICKY_LOC)) {
struct UvVertMap *vmap;
uint efa_index;
@@ -3260,7 +3274,7 @@ static void uv_select_flush_from_tag_face(Scene *scene, Object *obedit, const bo
* \note This function is very similar to #uv_select_flush_from_tag_face,
* be sure to update both upon changing.
*/
-static void uv_select_flush_from_tag_loop(Scene *scene, Object *obedit, const bool select)
+static void uv_select_flush_from_tag_loop(const Scene *scene, Object *obedit, const bool select)
{
/* Selecting UV Loops with some modes requires us to change
* the selection in other faces (depending on the sticky mode).
@@ -3342,7 +3356,7 @@ static void uv_select_flush_from_tag_loop(Scene *scene, Object *obedit, const bo
*
* \note Current behavior is selecting only; deselecting can be added but the behavior isn't
* required anywhere.*/
-static void uv_select_flush_from_loop_edge_flag(Scene *scene, BMEditMesh *em)
+static void uv_select_flush_from_loop_edge_flag(const Scene *scene, BMEditMesh *em)
{
const ToolSettings *ts = scene->toolsettings;
BMFace *efa;
@@ -3352,7 +3366,7 @@ static void uv_select_flush_from_loop_edge_flag(Scene *scene, BMEditMesh *em)
const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
if ((ts->uv_flag & UV_SYNC_SELECTION) == 0 &&
- ((ts->uv_sticky == SI_STICKY_LOC) || (ts->uv_sticky == SI_STICKY_VERTEX))) {
+ ELEM(ts->uv_sticky, SI_STICKY_LOC, SI_STICKY_VERTEX)) {
/* Use the #MLOOPUV_EDGESEL flag to identify which verts must to be selected */
struct UvVertMap *vmap;
uint efa_index;
@@ -4355,7 +4369,7 @@ void UV_OT_select_overlap(wmOperatorType *ot)
* So an edge that has two connected edge loops only assigns one loop in the array.
* \{ */
-BMFace **ED_uvedit_selected_faces(Scene *scene, BMesh *bm, int len_max, int *r_faces_len)
+BMFace **ED_uvedit_selected_faces(const Scene *scene, BMesh *bm, int len_max, int *r_faces_len)
{
const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
CLAMP_MAX(len_max, bm->totface);
@@ -4383,7 +4397,7 @@ finally:
return faces;
}
-BMLoop **ED_uvedit_selected_edges(Scene *scene, BMesh *bm, int len_max, int *r_edges_len)
+BMLoop **ED_uvedit_selected_edges(const Scene *scene, BMesh *bm, int len_max, int *r_edges_len)
{
const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
CLAMP_MAX(len_max, bm->totloop);
@@ -4439,7 +4453,7 @@ finally:
return edges;
}
-BMLoop **ED_uvedit_selected_verts(Scene *scene, BMesh *bm, int len_max, int *r_verts_len)
+BMLoop **ED_uvedit_selected_verts(const Scene *scene, BMesh *bm, int len_max, int *r_verts_len)
{
const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
CLAMP_MAX(len_max, bm->totloop);
@@ -4505,7 +4519,9 @@ finally:
*
* Use only when sync select disabled.
*/
-static void uv_isolate_selected_islands(Scene *scene, BMEditMesh *em, const int cd_loop_uv_offset)
+static void uv_isolate_selected_islands(const Scene *scene,
+ BMEditMesh *em,
+ const int cd_loop_uv_offset)
{
BLI_assert((scene->toolsettings->uv_flag & UV_SYNC_SELECTION) == 0);
BMFace *efa;
@@ -4553,9 +4569,9 @@ static void uv_isolate_selected_islands(Scene *scene, BMEditMesh *em, const int
MEM_freeN(is_island_not_selected);
}
-void ED_uvedit_selectmode_clean(Scene *scene, Object *obedit)
+void ED_uvedit_selectmode_clean(const Scene *scene, Object *obedit)
{
- ToolSettings *ts = scene->toolsettings;
+ const ToolSettings *ts = scene->toolsettings;
BLI_assert((ts->uv_flag & UV_SYNC_SELECTION) == 0);
BMEditMesh *em = BKE_editmesh_from_object(obedit);
char sticky = ts->uv_sticky;
diff --git a/source/blender/freestyle/intern/geometry/matrix_util.cpp b/source/blender/freestyle/intern/geometry/matrix_util.cpp
index ecf5443a957..35503a37685 100644
--- a/source/blender/freestyle/intern/geometry/matrix_util.cpp
+++ b/source/blender/freestyle/intern/geometry/matrix_util.cpp
@@ -106,7 +106,7 @@ void semi_definite_symmetric_eigen(const double *mat, int n, double *eigen_vec,
delta = a_ll - a_mm;
if (delta == 0.0) {
- x = -M_PI / 4;
+ x = -M_PI_4;
}
else {
x = -atan((a_lm + a_lm) / delta) / 2.0;
diff --git a/source/blender/freestyle/intern/view_map/ViewMap.h b/source/blender/freestyle/intern/view_map/ViewMap.h
index 729b31965c8..fe7c2e62d9a 100644
--- a/source/blender/freestyle/intern/view_map/ViewMap.h
+++ b/source/blender/freestyle/intern/view_map/ViewMap.h
@@ -938,7 +938,7 @@ class ViewEdge : public Interface1D {
FEdge *_FEdgeB; // last edge of the embedded fedges chain
Id _Id;
unsigned _ChainingTimeStamp;
- // The silhouette view edge separates 2 2D spaces. The one on the left is necessarly the Shape
+ // The silhouette view edge separates two 2D spaces. The one on the left is necessarily the Shape
// _Shape (the one to which this edge belongs to) and _aShape is the one on its right NOT HANDLED
// BY THE COPY CONSTRUCTOR
ViewShape *_aShape;
diff --git a/source/blender/freestyle/intern/winged_edge/Curvature.cpp b/source/blender/freestyle/intern/winged_edge/Curvature.cpp
index fba3110907a..9086593a945 100644
--- a/source/blender/freestyle/intern/winged_edge/Curvature.cpp
+++ b/source/blender/freestyle/intern/winged_edge/Curvature.cpp
@@ -474,10 +474,10 @@ inline static real angle(WOEdge *h)
const Vec3r v = h->GetVec();
real sine = (n1 ^ n2) * v / v.norm();
if (sine >= 1.0) {
- return M_PI / 2.0;
+ return M_PI_2;
}
if (sine <= -1.0) {
- return -M_PI / 2.0;
+ return -M_PI_2;
}
return ::asin(sine);
}
diff --git a/source/blender/freestyle/intern/winged_edge/WEdge.h b/source/blender/freestyle/intern/winged_edge/WEdge.h
index b77381bd4e5..6d39446056f 100644
--- a/source/blender/freestyle/intern/winged_edge/WEdge.h
+++ b/source/blender/freestyle/intern/winged_edge/WEdge.h
@@ -1400,11 +1400,11 @@ inline void WOEdge::setVecAndAngle()
if (_paFace && _pbFace) {
float sine = (_pbFace->GetNormal() ^ _paFace->GetNormal()) * _vec / _vec.norm();
if (sine >= 1.0) {
- _angle = M_PI / 2.0;
+ _angle = M_PI_2;
return;
}
if (sine <= -1.0) {
- _angle = -M_PI / 2.0;
+ _angle = -M_PI_2;
return;
}
_angle = ::asin(sine);
diff --git a/source/blender/freestyle/intern/winged_edge/WXEdge.cpp b/source/blender/freestyle/intern/winged_edge/WXEdge.cpp
index a56ac003703..b18d232dbbe 100644
--- a/source/blender/freestyle/intern/winged_edge/WXEdge.cpp
+++ b/source/blender/freestyle/intern/winged_edge/WXEdge.cpp
@@ -74,7 +74,7 @@ WXSmoothEdge *WXFaceLayer::BuildSmoothEdge()
//-----------------------------
// We retrieve the 2 edges for which we have opposite signs for each extremity
RetrieveCuspEdgesIndices(cuspEdgesIndices);
- if (cuspEdgesIndices.size() != 2) { // we necessarly have 2 cusp edges
+ if (cuspEdgesIndices.size() != 2) { // we necessarily have 2 cusp edges
return nullptr;
}
diff --git a/source/blender/geometry/GEO_mesh_to_curve.hh b/source/blender/geometry/GEO_mesh_to_curve.hh
index a99ee9c7fee..c480e4178cf 100644
--- a/source/blender/geometry/GEO_mesh_to_curve.hh
+++ b/source/blender/geometry/GEO_mesh_to_curve.hh
@@ -2,11 +2,10 @@
#include "BLI_index_mask.hh"
-#include "BKE_spline.hh"
-
#pragma once
struct Mesh;
+struct Curves;
class MeshComponent;
/** \file
@@ -20,7 +19,6 @@ namespace blender::geometry {
* intersections of more than three edges will become breaks in splines. Attributes that
* are not built-in on meshes and not curves are transferred to the result curve.
*/
-std::unique_ptr<CurveEval> mesh_to_curve_convert(const MeshComponent &mesh_component,
- const IndexMask selection);
+Curves *mesh_to_curve_convert(const MeshComponent &mesh_component, const IndexMask selection);
} // namespace blender::geometry
diff --git a/source/blender/geometry/intern/mesh_to_curve_convert.cc b/source/blender/geometry/intern/mesh_to_curve_convert.cc
index 121a1b5de39..0c2377fde6d 100644
--- a/source/blender/geometry/intern/mesh_to_curve_convert.cc
+++ b/source/blender/geometry/intern/mesh_to_curve_convert.cc
@@ -2,7 +2,6 @@
#include "BLI_array.hh"
#include "BLI_set.hh"
-#include "BLI_string_ref.hh"
#include "BLI_task.hh"
#include "DNA_mesh_types.h"
@@ -10,85 +9,48 @@
#include "BKE_attribute_access.hh"
#include "BKE_attribute_math.hh"
+#include "BKE_curves.hh"
#include "BKE_geometry_set.hh"
-#include "BKE_spline.hh"
#include "GEO_mesh_to_curve.hh"
namespace blender::geometry {
template<typename T>
-static void copy_attribute_to_points(const VArray<T> &source_data,
- Span<int> map,
- MutableSpan<T> dest_data)
+static void copy_with_map(const VArray<T> &src, Span<int> map, MutableSpan<T> dst)
{
- for (const int point_index : map.index_range()) {
- const int vert_index = map[point_index];
- dest_data[point_index] = source_data[vert_index];
- }
+ devirtualize_varray(src, [&](const auto &src) {
+ threading::parallel_for(map.index_range(), 1024, [&](const IndexRange range) {
+ for (const int i : range) {
+ const int vert_index = map[i];
+ dst[i] = src[vert_index];
+ }
+ });
+ });
}
-static std::unique_ptr<CurveEval> create_curve_from_vert_indices(
- const MeshComponent &mesh_component, Span<Vector<int>> vert_indices, IndexRange cyclic_splines)
+static Curves *create_curve_from_vert_indices(const MeshComponent &mesh_component,
+ const Span<int> vert_indices,
+ const Span<int> curve_offsets,
+ const IndexRange cyclic_splines)
{
- std::unique_ptr<CurveEval> curve = std::make_unique<CurveEval>();
- curve->resize(vert_indices.size());
-
- MutableSpan<SplinePtr> splines = curve->splines();
+ Curves *curves_id = bke::curves_new_nomain(vert_indices.size(), curve_offsets.size());
+ bke::CurvesGeometry &curves = bke::CurvesGeometry::wrap(curves_id->geometry);
+ curves.offsets().drop_back(1).copy_from(curve_offsets);
+ curves.offsets().last() = vert_indices.size();
+ curves.curve_types().fill(CURVE_TYPE_POLY);
- for (const int i : vert_indices.index_range()) {
- splines[i] = std::make_unique<PolySpline>();
- splines[i]->resize(vert_indices[i].size());
- }
- for (const int i : cyclic_splines) {
- splines[i]->set_cyclic(true);
- }
+ curves.cyclic().fill(false);
+ curves.cyclic().slice(cyclic_splines).fill(true);
Set<bke::AttributeIDRef> source_attribute_ids = mesh_component.attribute_ids();
- /* Copy builtin control point attributes. */
- if (source_attribute_ids.contains("tilt")) {
- const VArray<float> tilt_attribute = mesh_component.attribute_get_for_read<float>(
- "tilt", ATTR_DOMAIN_POINT, 0.0f);
- threading::parallel_for(splines.index_range(), 256, [&](IndexRange range) {
- for (const int i : range) {
- copy_attribute_to_points<float>(tilt_attribute, vert_indices[i], splines[i]->tilts());
- }
- });
- source_attribute_ids.remove_contained("tilt");
- }
- else {
- for (SplinePtr &spline : splines) {
- spline->tilts().fill(0.0f);
- }
- }
-
- if (source_attribute_ids.contains("radius")) {
- const VArray<float> radius_attribute = mesh_component.attribute_get_for_read<float>(
- "radius", ATTR_DOMAIN_POINT, 1.0f);
- threading::parallel_for(splines.index_range(), 256, [&](IndexRange range) {
- for (const int i : range) {
- copy_attribute_to_points<float>(radius_attribute, vert_indices[i], splines[i]->radii());
- }
- });
- source_attribute_ids.remove_contained("radius");
- }
- else {
- for (SplinePtr &spline : splines) {
- spline->radii().fill(1.0f);
- }
- }
-
- VArray<float3> mesh_positions = mesh_component.attribute_get_for_read(
- "position", ATTR_DOMAIN_POINT, float3(0));
- threading::parallel_for(splines.index_range(), 128, [&](IndexRange range) {
- for (const int i : range) {
- copy_attribute_to_points(mesh_positions, vert_indices[i], splines[i]->positions());
- }
- });
+ CurveComponent curves_component;
+ curves_component.replace(curves_id, GeometryOwnershipType::Editable);
for (const bke::AttributeIDRef &attribute_id : source_attribute_ids) {
- if (mesh_component.attribute_is_builtin(attribute_id)) {
+ if (mesh_component.attribute_is_builtin(attribute_id) &&
+ !curves_component.attribute_is_builtin(attribute_id)) {
/* Don't copy attributes that are built-in on meshes but not on curves. */
continue;
}
@@ -105,33 +67,24 @@ static std::unique_ptr<CurveEval> create_curve_from_vert_indices(
continue;
}
- const CustomDataType data_type = bke::cpp_type_to_custom_data_type(mesh_attribute.type());
-
- threading::parallel_for(splines.index_range(), 128, [&](IndexRange range) {
- for (const int i : range) {
- /* Create attribute on the spline points. */
- splines[i]->attributes.create(attribute_id, data_type);
- std::optional<fn::GMutableSpan> spline_attribute = splines[i]->attributes.get_for_write(
- attribute_id);
- BLI_assert(spline_attribute);
-
- /* Copy attribute based on the map for this spline. */
- attribute_math::convert_to_static_type(mesh_attribute.type(), [&](auto dummy) {
- using T = decltype(dummy);
- copy_attribute_to_points<T>(
- mesh_attribute.typed<T>(), vert_indices[i], spline_attribute->typed<T>());
- });
- }
+ /* Copy attribute based on the map for this spline. */
+ attribute_math::convert_to_static_type(mesh_attribute.type(), [&](auto dummy) {
+ using T = decltype(dummy);
+ bke::OutputAttribute_Typed<T> attribute =
+ curves_component.attribute_try_get_for_output_only<T>(attribute_id, ATTR_DOMAIN_POINT);
+ copy_with_map<T>(mesh_attribute.typed<T>(), vert_indices, attribute.as_span());
+ attribute.save();
});
}
- curve->assert_valid_point_attributes();
- return curve;
+ return curves_id;
}
struct CurveFromEdgesOutput {
/** The indices in the mesh for each control point of each result splines. */
- Vector<Vector<int>> vert_indices;
+ Vector<int> vert_indices;
+ /** The first index of each curve in the result. */
+ Vector<int> curve_offsets;
/** A subset of splines that should be set cyclic. */
IndexRange cyclic_splines;
};
@@ -139,7 +92,9 @@ struct CurveFromEdgesOutput {
static CurveFromEdgesOutput edges_to_curve_point_indices(Span<MVert> verts,
Span<std::pair<int, int>> edges)
{
- Vector<Vector<int>> vert_indices;
+ Vector<int> vert_indices;
+ vert_indices.reserve(edges.size());
+ Vector<int> curve_offsets;
/* Compute the number of edges connecting to each vertex. */
Array<int> neighbor_count(verts.size(), 0);
@@ -191,15 +146,16 @@ static CurveFromEdgesOutput edges_to_curve_point_indices(Span<MVert> verts,
continue;
}
- Vector<int> spline_indices;
- spline_indices.append(current_vert);
+ /* Start a new curve in the output. */
+ curve_offsets.append(vert_indices.size());
+ vert_indices.append(current_vert);
/* Follow connected edges until we read a vertex with more than two connected edges. */
while (true) {
int last_vert = current_vert;
current_vert = next_vert;
- spline_indices.append(current_vert);
+ vert_indices.append(current_vert);
unused_edges[current_vert]--;
unused_edges[last_vert]--;
@@ -212,13 +168,11 @@ static CurveFromEdgesOutput edges_to_curve_point_indices(Span<MVert> verts,
const int next_b = neighbors[offset + 1];
next_vert = (last_vert == next_a) ? next_b : next_a;
}
-
- vert_indices.append(std::move(spline_indices));
}
}
/* All splines added after this are cyclic. */
- const int cyclic_start = vert_indices.size();
+ const int cyclic_start = curve_offsets.size();
/* All remaining edges are part of cyclic splines (we skipped vertices with two edges before). */
for (const int start_vert : verts.index_range()) {
@@ -229,16 +183,15 @@ static CurveFromEdgesOutput edges_to_curve_point_indices(Span<MVert> verts,
int current_vert = start_vert;
int next_vert = neighbors[neighbor_offsets[current_vert]];
- Vector<int> spline_indices;
-
- spline_indices.append(current_vert);
+ curve_offsets.append(vert_indices.size());
+ vert_indices.append(current_vert);
/* Follow connected edges until we loop back to the start vertex. */
while (next_vert != start_vert) {
const int last_vert = current_vert;
current_vert = next_vert;
- spline_indices.append(current_vert);
+ vert_indices.append(current_vert);
unused_edges[current_vert]--;
unused_edges[last_vert]--;
@@ -247,13 +200,11 @@ static CurveFromEdgesOutput edges_to_curve_point_indices(Span<MVert> verts,
const int next_b = neighbors[offset + 1];
next_vert = (last_vert == next_a) ? next_b : next_a;
}
-
- vert_indices.append(std::move(spline_indices));
}
- const int final_size = vert_indices.size();
+ const IndexRange cyclic_curves = curve_offsets.index_range().drop_front(cyclic_start);
- return {std::move(vert_indices), IndexRange(cyclic_start, final_size - cyclic_start)};
+ return {std::move(vert_indices), std::move(curve_offsets), cyclic_curves};
}
/**
@@ -270,8 +221,7 @@ static Vector<std::pair<int, int>> get_selected_edges(const Mesh &mesh, const In
return selected_edges;
}
-std::unique_ptr<CurveEval> mesh_to_curve_convert(const MeshComponent &mesh_component,
- const IndexMask selection)
+Curves *mesh_to_curve_convert(const MeshComponent &mesh_component, const IndexMask selection)
{
const Mesh &mesh = *mesh_component.get_for_read();
Vector<std::pair<int, int>> selected_edges = get_selected_edges(*mesh_component.get_for_read(),
@@ -280,7 +230,7 @@ std::unique_ptr<CurveEval> mesh_to_curve_convert(const MeshComponent &mesh_compo
selected_edges);
return create_curve_from_vert_indices(
- mesh_component, output.vert_indices, output.cyclic_splines);
+ mesh_component, output.vert_indices, output.curve_offsets, output.cyclic_splines);
}
} // namespace blender::geometry
diff --git a/source/blender/geometry/intern/realize_instances.cc b/source/blender/geometry/intern/realize_instances.cc
index 4f7024eea82..32bad07de4f 100644
--- a/source/blender/geometry/intern/realize_instances.cc
+++ b/source/blender/geometry/intern/realize_instances.cc
@@ -121,15 +121,37 @@ struct RealizeMeshTask {
struct RealizeCurveInfo {
const Curves *curves;
/**
- * Matches the order in #AllCurvesInfo.attributes. For point attributes, the `std::optional`
- * will be empty.
+ * Matches the order in #AllCurvesInfo.attributes.
*/
- Array<std::optional<GVArray_GSpan>> spline_attributes;
+ Array<std::optional<GVArray_GSpan>> attributes;
+
+ /** ID attribute on the curves. If there are no ids, this #Span is empty. */
+ Span<int> stored_ids;
+
+ /**
+ * Handle position attributes must be transformed along with positions. Accessing them in
+ * advance isn't necessary theoretically, but is done to simplify other code and to avoid
+ * some overhead.
+ */
+ Span<float3> handle_left;
+ Span<float3> handle_right;
+
+ /**
+ * The radius attribute must be filled with a default of 1.0 if it
+ * doesn't exist on some (but not all) of the input curves data-blocks.
+ */
+ Span<float> radius;
+};
+
+/** Start indices in the final output curves data-block. */
+struct CurvesElementStartIndices {
+ int point = 0;
+ int curve = 0;
};
struct RealizeCurveTask {
- /* Start index in the final curve. */
- int start_spline_index = 0;
+ CurvesElementStartIndices start_indices;
+
const RealizeCurveInfo *curve_info;
/* Transformation applied to the position of control points and handles. */
float4x4 transform;
@@ -168,6 +190,8 @@ struct AllCurvesInfo {
/** Preprocessed data about every original curve. This is ordered by #order. */
Array<RealizeCurveInfo> realize_info;
bool create_id_attribute = false;
+ bool create_handle_postion_attributes = false;
+ bool create_radius_attribute = false;
};
/** Collects all tasks that need to be executed to realize all instances. */
@@ -185,7 +209,7 @@ struct GatherTasks {
struct GatherOffsets {
int pointcloud_offset = 0;
MeshElementStartIndices mesh_offsets;
- int spline_offset = 0;
+ CurvesElementStartIndices curves_offsets;
};
struct GatherTasksInfo {
@@ -230,6 +254,92 @@ struct InstanceContext {
}
};
+static void copy_transformed_positions(const Span<float3> src,
+ const float4x4 &transform,
+ MutableSpan<float3> dst)
+{
+ threading::parallel_for(src.index_range(), 1024, [&](const IndexRange range) {
+ for (const int i : range) {
+ dst[i] = transform * src[i];
+ }
+ });
+}
+
+static void threaded_copy(const GSpan src, GMutableSpan dst)
+{
+ BLI_assert(src.size() == dst.size());
+ BLI_assert(src.type() == dst.type());
+ threading::parallel_for(IndexRange(src.size()), 1024, [&](const IndexRange range) {
+ src.type().copy_construct_n(src.slice(range).data(), dst.slice(range).data(), range.size());
+ });
+}
+
+static void threaded_fill(const fn::GPointer value, GMutableSpan dst)
+{
+ BLI_assert(*value.type() == dst.type());
+ threading::parallel_for(IndexRange(dst.size()), 1024, [&](const IndexRange range) {
+ value.type()->fill_construct_n(value.get(), dst.slice(range).data(), range.size());
+ });
+}
+
+static void copy_generic_attributes_to_result(
+ const Span<std::optional<GVArray_GSpan>> src_attributes,
+ const AttributeFallbacksArray &attribute_fallbacks,
+ const OrderedAttributes &ordered_attributes,
+ const FunctionRef<IndexRange(AttributeDomain)> &range_fn,
+ MutableSpan<GMutableSpan> dst_attributes)
+{
+ threading::parallel_for(dst_attributes.index_range(), 10, [&](const IndexRange attribute_range) {
+ for (const int attribute_index : attribute_range) {
+ const AttributeDomain domain = ordered_attributes.kinds[attribute_index].domain;
+ const IndexRange element_slice = range_fn(domain);
+
+ GMutableSpan dst_span = dst_attributes[attribute_index].slice(element_slice);
+ if (src_attributes[attribute_index].has_value()) {
+ threaded_copy(*src_attributes[attribute_index], dst_span);
+ }
+ else {
+ const CPPType &cpp_type = dst_span.type();
+ const void *fallback = attribute_fallbacks.array[attribute_index] == nullptr ?
+ cpp_type.default_value() :
+ attribute_fallbacks.array[attribute_index];
+ threaded_fill({cpp_type, fallback}, dst_span);
+ }
+ }
+ });
+}
+
+static void create_result_ids(const RealizeInstancesOptions &options,
+ Span<int> stored_ids,
+ const int task_id,
+ MutableSpan<int> dst_ids)
+{
+ if (options.keep_original_ids) {
+ if (stored_ids.is_empty()) {
+ dst_ids.fill(0);
+ }
+ else {
+ dst_ids.copy_from(stored_ids);
+ }
+ }
+ else {
+ if (stored_ids.is_empty()) {
+ threading::parallel_for(dst_ids.index_range(), 1024, [&](const IndexRange range) {
+ for (const int i : range) {
+ dst_ids[i] = noise::hash(task_id, i);
+ }
+ });
+ }
+ else {
+ threading::parallel_for(dst_ids.index_range(), 1024, [&](const IndexRange range) {
+ for (const int i : range) {
+ dst_ids[i] = noise::hash(task_id, stored_ids[i]);
+ }
+ });
+ }
+ }
+}
+
/* -------------------------------------------------------------------- */
/** \name Gather Realize Tasks
* \{ */
@@ -448,12 +558,13 @@ static void gather_realize_tasks_recursive(GatherTasksInfo &gather_info,
if (curves != nullptr && curves->geometry.curve_size > 0) {
const int curve_index = gather_info.curves.order.index_of(curves);
const RealizeCurveInfo &curve_info = gather_info.curves.realize_info[curve_index];
- gather_info.r_tasks.curve_tasks.append({gather_info.r_offsets.spline_offset,
+ gather_info.r_tasks.curve_tasks.append({gather_info.r_offsets.curves_offsets,
&curve_info,
base_transform,
base_instance_context.curves,
base_instance_context.id});
- gather_info.r_offsets.spline_offset += curves->geometry.curve_size;
+ gather_info.r_offsets.curves_offsets.point += curves->geometry.point_size;
+ gather_info.r_offsets.curves_offsets.curve += curves->geometry.curve_size;
}
break;
}
@@ -559,6 +670,7 @@ static AllPointCloudsInfo preprocess_pointclouds(const GeometrySet &geometry_set
static void execute_realize_pointcloud_task(const RealizeInstancesOptions &options,
const RealizePointCloudTask &task,
+ const OrderedAttributes &ordered_attributes,
PointCloud &dst_pointcloud,
MutableSpan<GMutableSpan> dst_attribute_spans,
MutableSpan<int> all_dst_ids)
@@ -569,68 +681,25 @@ static void execute_realize_pointcloud_task(const RealizeInstancesOptions &optio
const IndexRange point_slice{task.start_index, pointcloud.totpoint};
MutableSpan<float3> dst_positions{(float3 *)dst_pointcloud.co + task.start_index,
pointcloud.totpoint};
- MutableSpan<int> dst_ids = all_dst_ids.slice(task.start_index, pointcloud.totpoint);
- /* Copy transformed positions. */
- threading::parallel_for(IndexRange(pointcloud.totpoint), 1024, [&](const IndexRange range) {
- for (const int i : range) {
- dst_positions[i] = task.transform * src_positions[i];
- }
- });
+ copy_transformed_positions(src_positions, task.transform, dst_positions);
+
/* Create point ids. */
if (!all_dst_ids.is_empty()) {
- if (options.keep_original_ids) {
- if (pointcloud_info.stored_ids.is_empty()) {
- dst_ids.fill(0);
- }
- else {
- dst_ids.copy_from(pointcloud_info.stored_ids);
- }
- }
- else {
- threading::parallel_for(IndexRange(pointcloud.totpoint), 1024, [&](const IndexRange range) {
- if (pointcloud_info.stored_ids.is_empty()) {
- for (const int i : range) {
- dst_ids[i] = noise::hash(task.id, i);
- }
- }
- else {
- for (const int i : range) {
- dst_ids[i] = noise::hash(task.id, pointcloud_info.stored_ids[i]);
- }
- }
- });
- }
+ create_result_ids(
+ options, pointcloud_info.stored_ids, task.id, all_dst_ids.slice(point_slice));
}
- /* Copy generic attributes. */
- threading::parallel_for(
- dst_attribute_spans.index_range(), 10, [&](const IndexRange attribute_range) {
- for (const int attribute_index : attribute_range) {
- GMutableSpan dst_span = dst_attribute_spans[attribute_index].slice(point_slice);
- const CPPType &cpp_type = dst_span.type();
- const void *attribute_fallback = task.attribute_fallbacks.array[attribute_index];
- if (pointcloud_info.attributes[attribute_index].has_value()) {
- /* Copy attribute from the original point cloud. */
- const GSpan src_span = *pointcloud_info.attributes[attribute_index];
- threading::parallel_for(
- IndexRange(pointcloud.totpoint), 1024, [&](const IndexRange range) {
- cpp_type.copy_assign_n(
- src_span.slice(range).data(), dst_span.slice(range).data(), range.size());
- });
- }
- else {
- if (attribute_fallback == nullptr) {
- attribute_fallback = cpp_type.default_value();
- }
- /* As the fallback value for the attribute. */
- threading::parallel_for(
- IndexRange(pointcloud.totpoint), 1024, [&](const IndexRange range) {
- cpp_type.fill_assign_n(
- attribute_fallback, dst_span.slice(range).data(), range.size());
- });
- }
- }
- });
+
+ copy_generic_attributes_to_result(
+ pointcloud_info.attributes,
+ task.attribute_fallbacks,
+ ordered_attributes,
+ [&](const AttributeDomain domain) {
+ BLI_assert(domain == ATTR_DOMAIN_POINT);
+ UNUSED_VARS_NDEBUG(domain);
+ return point_slice;
+ },
+ dst_attribute_spans);
}
static void execute_realize_pointcloud_tasks(const RealizeInstancesOptions &options,
@@ -678,7 +747,7 @@ static void execute_realize_pointcloud_tasks(const RealizeInstancesOptions &opti
for (const int task_index : task_range) {
const RealizePointCloudTask &task = tasks[task_index];
execute_realize_pointcloud_task(
- options, task, *dst_pointcloud, dst_attribute_spans, point_ids_span);
+ options, task, ordered_attributes, *dst_pointcloud, dst_attribute_spans, point_ids_span);
}
});
@@ -810,9 +879,6 @@ static void execute_realize_mesh_task(const RealizeInstancesOptions &options,
MutableSpan<MLoop> dst_loops{dst_mesh.mloop + task.start_indices.loop, mesh.totloop};
MutableSpan<MPoly> dst_polys{dst_mesh.mpoly + task.start_indices.poly, mesh.totpoly};
- MutableSpan<int> dst_vertex_ids = all_dst_vertex_ids.slice(task.start_indices.vertex,
- mesh.totvert);
-
const Span<int> material_index_map = mesh_info.material_index_map;
threading::parallel_for(IndexRange(mesh.totvert), 1024, [&](const IndexRange vert_range) {
@@ -856,78 +922,34 @@ static void execute_realize_mesh_task(const RealizeInstancesOptions &options,
}
}
});
- /* Create id attribute. */
+
if (!all_dst_vertex_ids.is_empty()) {
- if (options.keep_original_ids) {
- if (mesh_info.stored_vertex_ids.is_empty()) {
- dst_vertex_ids.fill(0);
- }
- else {
- dst_vertex_ids.copy_from(mesh_info.stored_vertex_ids);
- }
- }
- else {
- threading::parallel_for(IndexRange(mesh.totvert), 1024, [&](const IndexRange vert_range) {
- if (mesh_info.stored_vertex_ids.is_empty()) {
- for (const int i : vert_range) {
- dst_vertex_ids[i] = noise::hash(task.id, i);
- }
- }
- else {
- for (const int i : vert_range) {
- const int original_id = mesh_info.stored_vertex_ids[i];
- dst_vertex_ids[i] = noise::hash(task.id, original_id);
- }
- }
- });
- }
+ create_result_ids(options,
+ mesh_info.stored_vertex_ids,
+ task.id,
+ all_dst_vertex_ids.slice(task.start_indices.vertex, mesh.totvert));
}
- /* Copy generic attributes. */
- threading::parallel_for(
- dst_attribute_spans.index_range(), 10, [&](const IndexRange attribute_range) {
- for (const int attribute_index : attribute_range) {
- const AttributeDomain domain = ordered_attributes.kinds[attribute_index].domain;
- IndexRange element_slice;
- switch (domain) {
- case ATTR_DOMAIN_POINT:
- element_slice = IndexRange(task.start_indices.vertex, mesh.totvert);
- break;
- case ATTR_DOMAIN_EDGE:
- element_slice = IndexRange(task.start_indices.edge, mesh.totedge);
- break;
- case ATTR_DOMAIN_CORNER:
- element_slice = IndexRange(task.start_indices.loop, mesh.totloop);
- break;
- case ATTR_DOMAIN_FACE:
- element_slice = IndexRange(task.start_indices.poly, mesh.totpoly);
- break;
- default:
- BLI_assert_unreachable();
- }
- GMutableSpan dst_span = dst_attribute_spans[attribute_index].slice(element_slice);
- const CPPType &cpp_type = dst_span.type();
- const void *attribute_fallback = task.attribute_fallbacks.array[attribute_index];
- if (mesh_info.attributes[attribute_index].has_value()) {
- const GSpan src_span = *mesh_info.attributes[attribute_index];
- threading::parallel_for(
- IndexRange(element_slice.size()), 1024, [&](const IndexRange sub_range) {
- cpp_type.copy_assign_n(src_span.slice(sub_range).data(),
- dst_span.slice(sub_range).data(),
- sub_range.size());
- });
- }
- else {
- if (attribute_fallback == nullptr) {
- attribute_fallback = cpp_type.default_value();
- }
- threading::parallel_for(
- IndexRange(element_slice.size()), 1024, [&](const IndexRange sub_range) {
- cpp_type.fill_assign_n(
- attribute_fallback, dst_span.slice(sub_range).data(), sub_range.size());
- });
- }
+
+ copy_generic_attributes_to_result(
+ mesh_info.attributes,
+ task.attribute_fallbacks,
+ ordered_attributes,
+ [&](const AttributeDomain domain) {
+ switch (domain) {
+ case ATTR_DOMAIN_POINT:
+ return IndexRange(task.start_indices.vertex, mesh.totvert);
+ case ATTR_DOMAIN_EDGE:
+ return IndexRange(task.start_indices.edge, mesh.totedge);
+ case ATTR_DOMAIN_CORNER:
+ return IndexRange(task.start_indices.loop, mesh.totloop);
+ case ATTR_DOMAIN_FACE:
+ return IndexRange(task.start_indices.poly, mesh.totpoly);
+ default:
+ BLI_assert_unreachable();
+ return IndexRange();
}
- });
+ },
+ dst_attribute_spans);
}
static void execute_realize_mesh_tasks(const RealizeInstancesOptions &options,
@@ -1007,7 +1029,7 @@ static void execute_realize_mesh_tasks(const RealizeInstancesOptions &options,
/** \} */
/* -------------------------------------------------------------------- */
-/** \name Curve
+/** \name Curves
* \{ */
static OrderedAttributes gather_generic_curve_attributes_to_propagate(
@@ -1023,9 +1045,6 @@ static OrderedAttributes gather_generic_curve_attributes_to_propagate(
in_geometry_set.gather_attributes_for_propagation(
src_component_types, GEO_COMPONENT_TYPE_CURVE, true, attributes_to_propagate);
attributes_to_propagate.remove("position");
- attributes_to_propagate.remove("cyclic");
- attributes_to_propagate.remove("resolution");
- attributes_to_propagate.remove("tilt");
attributes_to_propagate.remove("radius");
attributes_to_propagate.remove("handle_right");
attributes_to_propagate.remove("handle_left");
@@ -1071,19 +1090,43 @@ static AllCurvesInfo preprocess_curves(const GeometrySet &geometry_set,
/* Access attributes. */
CurveComponent component;
component.replace(const_cast<Curves *>(curves), GeometryOwnershipType::ReadOnly);
- curve_info.spline_attributes.reinitialize(info.attributes.size());
+ curve_info.attributes.reinitialize(info.attributes.size());
for (const int attribute_index : info.attributes.index_range()) {
const AttributeDomain domain = info.attributes.kinds[attribute_index].domain;
- if (domain != ATTR_DOMAIN_CURVE) {
- continue;
- }
const AttributeIDRef &attribute_id = info.attributes.ids[attribute_index];
const CustomDataType data_type = info.attributes.kinds[attribute_index].data_type;
if (component.attribute_exists(attribute_id)) {
GVArray attribute = component.attribute_get_for_read(attribute_id, domain, data_type);
- curve_info.spline_attributes[attribute_index].emplace(std::move(attribute));
+ curve_info.attributes[attribute_index].emplace(std::move(attribute));
}
}
+ if (info.create_id_attribute) {
+ ReadAttributeLookup ids_lookup = component.attribute_try_get_for_read("id");
+ if (ids_lookup) {
+ curve_info.stored_ids = ids_lookup.varray.get_internal_span().typed<int>();
+ }
+ }
+
+ /* Retrieve the radius attribute, if it exists. */
+ if (component.attribute_exists("radius")) {
+ curve_info.radius = component
+ .attribute_get_for_read<float>("radius", ATTR_DOMAIN_POINT, 0.0f)
+ .get_internal_span();
+ info.create_radius_attribute = true;
+ }
+
+ /* Retrieve handle position attributes, if they exist. */
+ if (component.attribute_exists("handle_right")) {
+ curve_info.handle_left = component
+ .attribute_get_for_read<float3>(
+ "handle_left", ATTR_DOMAIN_POINT, float3(0))
+ .get_internal_span();
+ curve_info.handle_right = component
+ .attribute_get_for_read<float3>(
+ "handle_right", ATTR_DOMAIN_POINT, float3(0))
+ .get_internal_span();
+ info.create_handle_postion_attributes = true;
+ }
}
return info;
}
@@ -1092,108 +1135,81 @@ static void execute_realize_curve_task(const RealizeInstancesOptions &options,
const AllCurvesInfo &all_curves_info,
const RealizeCurveTask &task,
const OrderedAttributes &ordered_attributes,
- MutableSpan<SplinePtr> dst_splines,
- MutableSpan<GMutableSpan> dst_spline_attributes)
+ bke::CurvesGeometry &dst_curves,
+ MutableSpan<GMutableSpan> dst_attribute_spans,
+ MutableSpan<int> all_dst_ids,
+ MutableSpan<float3> all_handle_left,
+ MutableSpan<float3> all_handle_right,
+ MutableSpan<float> all_radii)
{
- const RealizeCurveInfo &curve_info = *task.curve_info;
- const std::unique_ptr<CurveEval> curve = curves_to_curve_eval(*curve_info.curves);
-
- const Span<SplinePtr> src_splines = curve->splines();
-
- /* Initialize point attributes. */
- threading::parallel_for(src_splines.index_range(), 100, [&](const IndexRange src_spline_range) {
- for (const int src_spline_index : src_spline_range) {
- const int dst_spline_index = src_spline_index + task.start_spline_index;
- const Spline &src_spline = *src_splines[src_spline_index];
- SplinePtr dst_spline = src_spline.copy_without_attributes();
- dst_spline->transform(task.transform);
- const int spline_size = dst_spline->size();
-
- const CustomDataAttributes &src_point_attributes = src_spline.attributes;
- CustomDataAttributes &dst_point_attributes = dst_spline->attributes;
-
- /* Create point ids. */
- if (all_curves_info.create_id_attribute) {
- dst_point_attributes.create("id", CD_PROP_INT32);
- MutableSpan<int> dst_point_ids = dst_point_attributes.get_for_write("id")->typed<int>();
- std::optional<GSpan> src_point_ids_opt = src_point_attributes.get_for_read("id");
- if (options.keep_original_ids) {
- if (src_point_ids_opt.has_value()) {
- const Span<int> src_point_ids = src_point_ids_opt->typed<int>();
- dst_point_ids.copy_from(src_point_ids);
- }
- else {
- dst_point_ids.fill(0);
- }
- }
- else {
- if (src_point_ids_opt.has_value()) {
- const Span<int> src_point_ids = src_point_ids_opt->typed<int>();
- for (const int i : IndexRange(dst_spline->size())) {
- dst_point_ids[i] = noise::hash(task.id, src_point_ids[i]);
- }
- }
- else {
- for (const int i : IndexRange(dst_spline->size())) {
- /* Mix spline index into the id, because otherwise points on different splines will
- * get the same id. */
- dst_point_ids[i] = noise::hash(task.id, src_spline_index, i);
- }
- }
- }
- }
+ const RealizeCurveInfo &curves_info = *task.curve_info;
+ const Curves &curves_id = *curves_info.curves;
+ const bke::CurvesGeometry &curves = bke::CurvesGeometry::wrap(curves_id.geometry);
- /* Copy generic point attributes. */
- for (const int attribute_index : ordered_attributes.index_range()) {
- const AttributeDomain domain = ordered_attributes.kinds[attribute_index].domain;
- if (domain != ATTR_DOMAIN_POINT) {
- continue;
- }
- const CustomDataType data_type = ordered_attributes.kinds[attribute_index].data_type;
- const CPPType &cpp_type = *custom_data_type_to_cpp_type(data_type);
- const AttributeIDRef &attribute_id = ordered_attributes.ids[attribute_index];
- const void *attribute_fallback = task.attribute_fallbacks.array[attribute_index];
- const std::optional<GSpan> src_span_opt = src_point_attributes.get_for_read(attribute_id);
- void *dst_buffer = MEM_malloc_arrayN(spline_size, cpp_type.size(), "Curve Attribute");
- if (src_span_opt.has_value()) {
- const GSpan src_span = *src_span_opt;
- cpp_type.copy_construct_n(src_span.data(), dst_buffer, spline_size);
- }
- else {
- if (attribute_fallback == nullptr) {
- attribute_fallback = cpp_type.default_value();
- }
- cpp_type.fill_construct_n(attribute_fallback, dst_buffer, spline_size);
- }
- dst_point_attributes.create_by_move(attribute_id, data_type, dst_buffer);
- }
+ const IndexRange dst_point_range{task.start_indices.point, curves.points_size()};
+ const IndexRange dst_curve_range{task.start_indices.curve, curves.curves_size()};
+
+ copy_transformed_positions(
+ curves.positions(), task.transform, dst_curves.positions().slice(dst_point_range));
- dst_splines[dst_spline_index] = std::move(dst_spline);
+ /* Copy and transform handle positions if necessary. */
+ if (all_curves_info.create_handle_postion_attributes) {
+ if (curves_info.handle_left.is_empty()) {
+ all_handle_left.slice(dst_point_range).fill(float3(0));
}
- });
- /* Initialize spline attributes. */
- for (const int attribute_index : ordered_attributes.index_range()) {
- const AttributeDomain domain = ordered_attributes.kinds[attribute_index].domain;
- if (domain != ATTR_DOMAIN_CURVE) {
- continue;
+ else {
+ copy_transformed_positions(
+ curves_info.handle_left, task.transform, all_handle_left.slice(dst_point_range));
}
- const CustomDataType data_type = ordered_attributes.kinds[attribute_index].data_type;
- const CPPType &cpp_type = *custom_data_type_to_cpp_type(data_type);
+ if (curves_info.handle_right.is_empty()) {
+ all_handle_right.slice(dst_point_range).fill(float3(0));
+ }
+ else {
+ copy_transformed_positions(
+ curves_info.handle_right, task.transform, all_handle_right.slice(dst_point_range));
+ }
+ }
- GMutableSpan dst_span = dst_spline_attributes[attribute_index].slice(task.start_spline_index,
- src_splines.size());
- if (curve_info.spline_attributes[attribute_index].has_value()) {
- const GSpan src_span = *curve_info.spline_attributes[attribute_index];
- cpp_type.copy_construct_n(src_span.data(), dst_span.data(), src_splines.size());
+ /* Copy radius attribute with 1.0 default if it doesn't exist. */
+ if (all_curves_info.create_radius_attribute) {
+ if (curves_info.radius.is_empty()) {
+ all_radii.slice(dst_point_range).fill(1.0f);
}
else {
- const void *attribute_fallback = task.attribute_fallbacks.array[attribute_index];
- if (attribute_fallback == nullptr) {
- attribute_fallback = cpp_type.default_value();
- }
- cpp_type.fill_construct_n(attribute_fallback, dst_span.data(), src_splines.size());
+ all_radii.slice(dst_point_range).copy_from(curves_info.radius);
+ }
+ }
+
+ /* Copy curve offsets. */
+ const Span<int> src_offsets = curves.offsets();
+ const MutableSpan<int> dst_offsets = dst_curves.offsets().slice(dst_curve_range);
+ threading::parallel_for(curves.curves_range(), 2048, [&](const IndexRange range) {
+ for (const int i : range) {
+ dst_offsets[i] = task.start_indices.point + src_offsets[i];
}
+ });
+
+ if (!all_dst_ids.is_empty()) {
+ create_result_ids(
+ options, curves_info.stored_ids, task.id, all_dst_ids.slice(dst_point_range));
}
+
+ copy_generic_attributes_to_result(
+ curves_info.attributes,
+ task.attribute_fallbacks,
+ ordered_attributes,
+ [&](const AttributeDomain domain) {
+ switch (domain) {
+ case ATTR_DOMAIN_POINT:
+ return IndexRange(task.start_indices.point, curves.points_size());
+ case ATTR_DOMAIN_CURVE:
+ return IndexRange(task.start_indices.curve, curves.curves_size());
+ default:
+ BLI_assert_unreachable();
+ return IndexRange();
+ }
+ },
+ dst_attribute_spans);
}
static void execute_realize_curve_tasks(const RealizeInstancesOptions &options,
@@ -1208,42 +1224,90 @@ static void execute_realize_curve_tasks(const RealizeInstancesOptions &options,
const RealizeCurveTask &last_task = tasks.last();
const Curves &last_curves = *last_task.curve_info->curves;
- const int tot_splines = last_task.start_spline_index + last_curves.geometry.curve_size;
+ const int points_size = last_task.start_indices.point + last_curves.geometry.point_size;
+ const int curves_size = last_task.start_indices.curve + last_curves.geometry.curve_size;
- Array<SplinePtr> dst_splines(tot_splines);
+ /* Allocate new curves data-block. */
+ Curves *dst_curves_id = bke::curves_new_nomain(points_size, curves_size);
+ bke::CurvesGeometry &dst_curves = bke::CurvesGeometry::wrap(dst_curves_id->geometry);
+ dst_curves.offsets().last() = points_size;
+ CurveComponent &dst_component = r_realized_geometry.get_component_for_write<CurveComponent>();
+ dst_component.replace(dst_curves_id);
- std::unique_ptr<CurveEval> dst_curve = std::make_unique<CurveEval>();
- dst_curve->attributes.reallocate(tot_splines);
- CustomDataAttributes &spline_attributes = dst_curve->attributes;
+ /* Prepare id attribute. */
+ OutputAttribute_Typed<int> point_ids;
+ MutableSpan<int> point_ids_span;
+ if (all_curves_info.create_id_attribute) {
+ point_ids = dst_component.attribute_try_get_for_output_only<int>("id", ATTR_DOMAIN_POINT);
+ point_ids_span = point_ids.as_span();
+ }
- /* Prepare spline attributes. */
- Vector<GMutableSpan> dst_spline_attributes;
+ /* Prepare generic output attributes. */
+ Vector<OutputAttribute> dst_attributes;
+ Vector<GMutableSpan> dst_attribute_spans;
for (const int attribute_index : ordered_attributes.index_range()) {
const AttributeIDRef &attribute_id = ordered_attributes.ids[attribute_index];
- const CustomDataType data_type = ordered_attributes.kinds[attribute_index].data_type;
const AttributeDomain domain = ordered_attributes.kinds[attribute_index].domain;
- if (domain == ATTR_DOMAIN_CURVE) {
- spline_attributes.create(attribute_id, data_type);
- dst_spline_attributes.append(*spline_attributes.get_for_write(attribute_id));
- }
- else {
- dst_spline_attributes.append({CPPType::get<float>()});
- }
+ const CustomDataType data_type = ordered_attributes.kinds[attribute_index].data_type;
+ OutputAttribute dst_attribute = dst_component.attribute_try_get_for_output_only(
+ attribute_id, domain, data_type);
+ dst_attribute_spans.append(dst_attribute.as_span());
+ dst_attributes.append(std::move(dst_attribute));
+ }
+
+ /* Prepare handle position attributes if necessary. */
+ OutputAttribute_Typed<float3> handle_left;
+ OutputAttribute_Typed<float3> handle_right;
+ MutableSpan<float3> handle_left_span;
+ MutableSpan<float3> handle_right_span;
+ if (all_curves_info.create_handle_postion_attributes) {
+ handle_left = dst_component.attribute_try_get_for_output_only<float3>("handle_left",
+ ATTR_DOMAIN_POINT);
+ handle_right = dst_component.attribute_try_get_for_output_only<float3>("handle_right",
+ ATTR_DOMAIN_POINT);
+ handle_left_span = handle_left.as_span();
+ handle_right_span = handle_right.as_span();
+ }
+
+ /* Prepare radius attribute if necessary. */
+ OutputAttribute_Typed<float> radius;
+ MutableSpan<float> radius_span;
+ if (all_curves_info.create_radius_attribute) {
+ radius = dst_component.attribute_try_get_for_output_only<float>("radius", ATTR_DOMAIN_POINT);
+ radius_span = radius.as_span();
}
/* Actually execute all tasks. */
threading::parallel_for(tasks.index_range(), 100, [&](const IndexRange task_range) {
for (const int task_index : task_range) {
const RealizeCurveTask &task = tasks[task_index];
- execute_realize_curve_task(
- options, all_curves_info, task, ordered_attributes, dst_splines, dst_spline_attributes);
+ execute_realize_curve_task(options,
+ all_curves_info,
+ task,
+ ordered_attributes,
+ dst_curves,
+ dst_attribute_spans,
+ point_ids_span,
+ handle_left_span,
+ handle_right_span,
+ radius_span);
}
});
- dst_curve->add_splines(dst_splines);
-
- CurveComponent &dst_component = r_realized_geometry.get_component_for_write<CurveComponent>();
- dst_component.replace(curve_eval_to_curves(*dst_curve));
+ /* Save modified attributes. */
+ for (OutputAttribute &dst_attribute : dst_attributes) {
+ dst_attribute.save();
+ }
+ if (point_ids) {
+ point_ids.save();
+ }
+ if (radius) {
+ radius.save();
+ }
+ if (all_curves_info.create_handle_postion_attributes) {
+ handle_left.save();
+ handle_right.save();
+ }
}
/** \} */
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencil_ui_common.c b/source/blender/gpencil_modifiers/intern/MOD_gpencil_ui_common.c
index 45c7bd5b4e0..288ae9c0c5f 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpencil_ui_common.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencil_ui_common.c
@@ -59,7 +59,7 @@ static void gpencil_modifier_reorder(bContext *C, Panel *panel, int new_index)
WM_operator_properties_create_ptr(&props_ptr, ot);
RNA_string_set(&props_ptr, "modifier", md->name);
RNA_int_set(&props_ptr, "index", new_index);
- WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &props_ptr);
+ WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &props_ptr, NULL);
WM_operator_properties_free(&props_ptr);
}
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencil_ui_common.h b/source/blender/gpencil_modifiers/intern/MOD_gpencil_ui_common.h
index bbc0a3d26b6..57eac4d77bf 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpencil_ui_common.h
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencil_ui_common.h
@@ -41,8 +41,8 @@ PanelType *gpencil_modifier_panel_register(struct ARegionType *region_type,
/**
* Add a child panel to the parent.
*
- * \note To create the panel type's idname, it appends the \a name argument to the \a parent's
- * idname.
+ * \note To create the panel type's #PanelType.idname,
+ * it appends the \a name argument to the \a parent's `idname`.
*/
struct PanelType *gpencil_modifier_subpanel_register(struct ARegionType *region_type,
const char *name,
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilbuild.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilbuild.c
index b1447bcaccb..1a69a6a8a38 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpencilbuild.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilbuild.c
@@ -180,23 +180,42 @@ typedef struct tStrokeBuildDetails {
int totpoints;
} tStrokeBuildDetails;
-/* Sequential - Show strokes one after the other */
-static void build_sequential(BuildGpencilModifierData *mmd,
- bGPdata *gpd,
- bGPDframe *gpf,
- float fac)
+/* Sequential and additive - Show strokes one after the other. */
+static void build_sequential(
+ BuildGpencilModifierData *mmd, bGPdata *gpd, bGPDframe *gpf, float fac, bool additive)
{
- const size_t tot_strokes = BLI_listbase_count(&gpf->strokes);
+ size_t tot_strokes = BLI_listbase_count(&gpf->strokes);
+ size_t start_stroke;
bGPDstroke *gps;
size_t i;
- /* 1) Compute proportion of time each stroke should occupy */
+ /* 1) Determine which strokes to start with & total strokes to build. */
+
+ if (additive) {
+ if (gpf->prev) {
+ start_stroke = BLI_listbase_count(&gpf->prev->strokes);
+ }
+ else {
+ start_stroke = 0;
+ }
+ if (start_stroke <= tot_strokes) {
+ tot_strokes = tot_strokes - start_stroke;
+ }
+ else {
+ start_stroke = 0;
+ }
+ }
+ else {
+ start_stroke = 0;
+ }
+
+ /* 2) Compute proportion of time each stroke should occupy */
/* NOTE: This assumes that the total number of points won't overflow! */
tStrokeBuildDetails *table = MEM_callocN(sizeof(tStrokeBuildDetails) * tot_strokes, __func__);
size_t totpoints = 0;
- /* 1.1) First pass - Tally up points */
- for (gps = gpf->strokes.first, i = 0; gps; gps = gps->next, i++) {
+ /* 2.1) First pass - Tally up points */
+ for (gps = BLI_findlink(&gpf->strokes, start_stroke), i = 0; gps; gps = gps->next, i++) {
tStrokeBuildDetails *cell = &table[i];
cell->gps = gps;
@@ -205,7 +224,7 @@ static void build_sequential(BuildGpencilModifierData *mmd,
totpoints += cell->totpoints;
}
- /* 1.2) Second pass - Compute the overall indices for points */
+ /* 2.2) Second pass - Compute the overall indices for points */
for (i = 0; i < tot_strokes; i++) {
tStrokeBuildDetails *cell = &table[i];
@@ -218,7 +237,7 @@ static void build_sequential(BuildGpencilModifierData *mmd,
cell->end_idx = cell->start_idx + cell->totpoints - 1;
}
- /* 2) Determine the global indices for points that should be visible */
+ /* 3) Determine the global indices for points that should be visible */
size_t first_visible = 0;
size_t last_visible = 0;
@@ -248,7 +267,7 @@ static void build_sequential(BuildGpencilModifierData *mmd,
break;
}
- /* 3) Go through all strokes, deciding which to keep, and/or how much of each to keep */
+ /* 4) Go through all strokes, deciding which to keep, and/or how much of each to keep */
for (i = 0; i < tot_strokes; i++) {
tStrokeBuildDetails *cell = &table[i];
@@ -386,10 +405,14 @@ static void build_concurrent(BuildGpencilModifierData *mmd,
}
/* --------------------------------------------- */
+
static void generate_geometry(
GpencilModifierData *md, Depsgraph *depsgraph, bGPdata *gpd, bGPDlayer *gpl, bGPDframe *gpf)
{
BuildGpencilModifierData *mmd = (BuildGpencilModifierData *)md;
+ if (mmd->mode == GP_BUILD_MODE_ADDITIVE) {
+ mmd->transition = GP_BUILD_TRANSITION_GROW;
+ }
const bool reverse = (mmd->transition != GP_BUILD_TRANSITION_GROW);
const bool is_percentage = (mmd->flag & GP_BUILD_PERCENTAGE);
@@ -494,13 +517,17 @@ static void generate_geometry(
/* Time management mode */
switch (mmd->mode) {
case GP_BUILD_MODE_SEQUENTIAL:
- build_sequential(mmd, gpd, gpf, fac);
+ build_sequential(mmd, gpd, gpf, fac, false);
break;
case GP_BUILD_MODE_CONCURRENT:
build_concurrent(mmd, gpd, gpf, fac);
break;
+ case GP_BUILD_MODE_ADDITIVE:
+ build_sequential(mmd, gpd, gpf, fac, true);
+ break;
+
default:
printf("Unsupported build mode (%d) for GP Build Modifier: '%s'\n",
mmd->mode,
@@ -544,7 +571,9 @@ static void panel_draw(const bContext *UNUSED(C), Panel *panel)
uiItemS(layout);
- uiItemR(layout, ptr, "transition", 0, NULL, ICON_NONE);
+ if (ELEM(mode, GP_BUILD_MODE_SEQUENTIAL, GP_BUILD_MODE_CONCURRENT)) {
+ uiItemR(layout, ptr, "transition", 0, NULL, ICON_NONE);
+ }
row = uiLayoutRow(layout, true);
uiLayoutSetActive(row, !use_percentage);
uiItemR(row, ptr, "start_delay", 0, NULL, ICON_NONE);
diff --git a/source/blender/gpu/intern/gpu_immediate_util.c b/source/blender/gpu/intern/gpu_immediate_util.c
index b2fd60a62e5..cf8837ab26e 100644
--- a/source/blender/gpu/intern/gpu_immediate_util.c
+++ b/source/blender/gpu/intern/gpu_immediate_util.c
@@ -181,7 +181,7 @@ static void imm_draw_circle_partial(GPUPrimType prim_type,
float sweep)
{
/* shift & reverse angle, increase 'nsegments' to match gluPartialDisk */
- const float angle_start = -(DEG2RADF(start)) + (float)(M_PI / 2);
+ const float angle_start = -(DEG2RADF(start)) + (float)M_PI_2;
const float angle_end = -(DEG2RADF(sweep) - angle_start);
nsegments += 1;
immBegin(prim_type, nsegments);
@@ -215,7 +215,7 @@ static void imm_draw_disk_partial(GPUPrimType prim_type,
CLAMP(sweep, -max_angle, max_angle);
/* shift & reverse angle, increase 'nsegments' to match gluPartialDisk */
- const float angle_start = -(DEG2RADF(start)) + (float)(M_PI / 2);
+ const float angle_start = -(DEG2RADF(start)) + (float)M_PI_2;
const float angle_end = -(DEG2RADF(sweep) - angle_start);
nsegments += 1;
immBegin(prim_type, nsegments * 2);
diff --git a/source/blender/gpu/intern/gpu_shader_create_info.hh b/source/blender/gpu/intern/gpu_shader_create_info.hh
index bf74d44d9a7..da63d372669 100644
--- a/source/blender/gpu/intern/gpu_shader_create_info.hh
+++ b/source/blender/gpu/intern/gpu_shader_create_info.hh
@@ -22,7 +22,7 @@
namespace blender::gpu::shader {
#ifndef GPU_SHADER_CREATE_INFO
-/* Helps intelisense / auto-completion. */
+/* Helps intellisense / auto-completion. */
# define GPU_SHADER_INTERFACE_INFO(_interface, _inst_name) \
StageInterfaceInfo _interface(#_interface, _inst_name); \
_interface
diff --git a/source/blender/gpu/intern/gpu_vertex_format.cc b/source/blender/gpu/intern/gpu_vertex_format.cc
index eedd660d0a9..a9ac191754b 100644
--- a/source/blender/gpu/intern/gpu_vertex_format.cc
+++ b/source/blender/gpu/intern/gpu_vertex_format.cc
@@ -133,7 +133,7 @@ uint GPU_vertformat_attr_add(GPUVertFormat *format,
case GPU_COMP_I10:
/* 10_10_10 format intended for normals (xyz) or colors (rgb)
* extra component packed.w can be manually set to { -2, -1, 0, 1 } */
- assert(comp_len == 3 || comp_len == 4);
+ assert(ELEM(comp_len, 3, 4));
/* Not strictly required, may relax later. */
assert(fetch_mode == GPU_FETCH_INT_TO_FLOAT_UNIT);
@@ -143,7 +143,7 @@ uint GPU_vertformat_attr_add(GPUVertFormat *format,
/* integer types can be kept as int or converted/normalized to float */
assert(fetch_mode != GPU_FETCH_FLOAT);
/* only support float matrices (see Batch_update_program_bindings) */
- assert(comp_len != 8 && comp_len != 12 && comp_len != 16);
+ assert(!ELEM(comp_len, 8, 12, 16));
}
#endif
format->name_len++; /* Multi-name support. */
diff --git a/source/blender/gpu/opengl/gl_backend.cc b/source/blender/gpu/opengl/gl_backend.cc
index 302d8249914..f0d7a23ef82 100644
--- a/source/blender/gpu/opengl/gl_backend.cc
+++ b/source/blender/gpu/opengl/gl_backend.cc
@@ -270,6 +270,11 @@ static void detect_workarounds()
GCaps.shader_image_load_store_support = false;
GCaps.broken_amd_driver = true;
}
+ /* Compute shaders have some issues with those versions (see T94936). */
+ if (GPU_type_matches(GPU_DEVICE_ATI, GPU_OS_ANY, GPU_DRIVER_OFFICIAL) &&
+ (strstr(version, "4.5.14831") || strstr(version, "4.5.14760"))) {
+ GCaps.compute_shader_support = false;
+ }
/* We have issues with this specific renderer. (see T74024) */
if (GPU_type_matches(GPU_DEVICE_ATI, GPU_OS_UNIX, GPU_DRIVER_OPENSOURCE) &&
(strstr(renderer, "AMD VERDE") || strstr(renderer, "AMD KAVERI") ||
diff --git a/source/blender/gpu/opengl/gl_shader.cc b/source/blender/gpu/opengl/gl_shader.cc
index 31f657a63b2..256702b60c5 100644
--- a/source/blender/gpu/opengl/gl_shader.cc
+++ b/source/blender/gpu/opengl/gl_shader.cc
@@ -175,7 +175,7 @@ static const char *to_string(const eGPUTextureFormat &type)
case GPU_R16:
return "r16";
default:
- return "unkown";
+ return "unknown";
}
}
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_object_info.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_object_info.glsl
index ff77b0beea2..607cf119b36 100644
--- a/source/blender/gpu/shaders/material/gpu_shader_material_object_info.glsl
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_object_info.glsl
@@ -4,12 +4,14 @@ void node_object_info(mat4 obmat,
float mat_index,
out vec3 location,
out vec4 color,
+ out float alpha,
out float object_index,
out float material_index,
out float random)
{
location = obmat[3].xyz;
color = obcolor;
+ alpha = obcolor.w;
object_index = info.x;
material_index = mat_index;
random = info.z;
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_tex_environment.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_tex_environment.glsl
index 20a65f23c05..434e07e7b86 100644
--- a/source/blender/gpu/shaders/material/gpu_shader_material_tex_environment.glsl
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_tex_environment.glsl
@@ -4,9 +4,9 @@ void node_tex_environment_texco(vec3 viewvec, out vec3 worldvec)
worldvec = worldPosition;
#else
vec4 v = (ProjectionMatrix[3][3] == 0.0) ? vec4(viewvec, 1.0) : vec4(0.0, 0.0, 1.0, 1.0);
- vec4 co_homogenous = (ProjectionMatrixInverse * v);
+ vec4 co_homogeneous = (ProjectionMatrixInverse * v);
- vec3 co = co_homogenous.xyz / co_homogenous.w;
+ vec3 co = co_homogeneous.xyz / co_homogeneous.w;
# if defined(WORLD_BACKGROUND) || defined(PROBE_CAPTURE)
worldvec = mat3(ViewMatrixInverse) * co;
# else
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_texture_coordinates.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_texture_coordinates.glsl
index 08d566224bf..a8ef9687b0a 100644
--- a/source/blender/gpu/shaders/material/gpu_shader_material_texture_coordinates.glsl
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_texture_coordinates.glsl
@@ -19,8 +19,8 @@ void generated_from_orco(vec3 orco, out vec3 generated)
void generated_texco(vec3 I, vec3 attr_orco, out vec3 generated)
{
vec4 v = (ProjectionMatrix[3][3] == 0.0) ? vec4(I, 1.0) : vec4(0.0, 0.0, 1.0, 1.0);
- vec4 co_homogenous = (ProjectionMatrixInverse * v);
- vec4 co = vec4(co_homogenous.xyz / co_homogenous.w, 0.0);
+ vec4 co_homogeneous = (ProjectionMatrixInverse * v);
+ vec4 co = vec4(co_homogeneous.xyz / co_homogeneous.w, 0.0);
co.xyz = normalize(co.xyz);
#if defined(WORLD_BACKGROUND) || defined(PROBE_CAPTURE)
generated = (ViewMatrixInverse * co).xyz;
@@ -68,9 +68,9 @@ void node_tex_coord_background(vec3 I,
out vec3 reflection)
{
vec4 v = (ProjectionMatrix[3][3] == 0.0) ? vec4(I, 1.0) : vec4(0.0, 0.0, 1.0, 1.0);
- vec4 co_homogenous = (ProjectionMatrixInverse * v);
+ vec4 co_homogeneous = (ProjectionMatrixInverse * v);
- vec4 co = vec4(co_homogenous.xyz / co_homogenous.w, 0.0);
+ vec4 co = vec4(co_homogeneous.xyz / co_homogeneous.w, 0.0);
co = normalize(co);
diff --git a/source/blender/ikplugin/intern/iksolver_plugin.c b/source/blender/ikplugin/intern/iksolver_plugin.c
index d0cb7f00df8..6d99fde9df6 100644
--- a/source/blender/ikplugin/intern/iksolver_plugin.c
+++ b/source/blender/ikplugin/intern/iksolver_plugin.c
@@ -255,8 +255,10 @@ static void where_is_ik_bone(bPoseChannel *pchan,
pchan->flag |= POSE_DONE;
}
-/* called from within the core BKE_pose_where_is loop, all animsystems and constraints
- * were executed & assigned. Now as last we do an IK pass */
+/**
+ * Called from within the core #BKE_pose_where_is loop, all animation-systems and constraints
+ * were executed & assigned. Now as last we do an IK pass.
+ */
static void execute_posetree(struct Depsgraph *depsgraph,
struct Scene *scene,
Object *ob,
diff --git a/source/blender/imbuf/IMB_thumbs.h b/source/blender/imbuf/IMB_thumbs.h
index 70ff0ad83cd..623a3b2b5f4 100644
--- a/source/blender/imbuf/IMB_thumbs.h
+++ b/source/blender/imbuf/IMB_thumbs.h
@@ -71,7 +71,7 @@ void IMB_thumb_delete(const char *path, ThumbSize size);
struct ImBuf *IMB_thumb_manage(const char *path, ThumbSize size, ThumbSource source);
/**
- * Create the necessary dirs to store the thumbnails.
+ * Create the necessary directories to store the thumbnails.
*/
void IMB_thumb_makedirs(void);
diff --git a/source/blender/imbuf/intern/anim_movie.c b/source/blender/imbuf/intern/anim_movie.c
index 7cde49f44b7..096089d4c41 100644
--- a/source/blender/imbuf/intern/anim_movie.c
+++ b/source/blender/imbuf/intern/anim_movie.c
@@ -874,6 +874,8 @@ static int ffmpeg_read_video_frame(struct anim *anim, AVPacket *packet)
if (packet->stream_index == anim->videoStream) {
break;
}
+ av_packet_unref(packet);
+ packet->stream_index = -1;
}
return ret;
diff --git a/source/blender/imbuf/intern/dds/DirectDrawSurface.cpp b/source/blender/imbuf/intern/dds/DirectDrawSurface.cpp
index 9173b5a9d49..ce5dd4927be 100644
--- a/source/blender/imbuf/intern/dds/DirectDrawSurface.cpp
+++ b/source/blender/imbuf/intern/dds/DirectDrawSurface.cpp
@@ -34,6 +34,9 @@
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE. */
+#include "BLI_utildefines.h"
+#undef CLAMP
+
#include <BlockDXT.h>
#include <DirectDrawSurface.h>
#include <PixelFormat.h>
@@ -596,7 +599,7 @@ void DDSHeader::setDepth(uint d)
void DDSHeader::setMipmapCount(uint count)
{
- if (count == 0 || count == 1) {
+ if (ELEM(count, 0, 1)) {
this->flags &= ~DDSD_MIPMAPCOUNT;
this->mipmapcount = 1;
@@ -904,11 +907,12 @@ bool DirectDrawSurface::isValid() const
bool DirectDrawSurface::isSupported() const
{
if (header.hasDX10Header()) {
- if (header.header10.dxgiFormat == DXGI_FORMAT_BC1_UNORM ||
- header.header10.dxgiFormat == DXGI_FORMAT_BC2_UNORM ||
- header.header10.dxgiFormat == DXGI_FORMAT_BC3_UNORM ||
- header.header10.dxgiFormat == DXGI_FORMAT_BC4_UNORM ||
- header.header10.dxgiFormat == DXGI_FORMAT_BC5_UNORM) {
+ if (ELEM(header.header10.dxgiFormat,
+ DXGI_FORMAT_BC1_UNORM,
+ DXGI_FORMAT_BC2_UNORM,
+ DXGI_FORMAT_BC3_UNORM,
+ DXGI_FORMAT_BC4_UNORM,
+ DXGI_FORMAT_BC5_UNORM)) {
return true;
}
@@ -916,10 +920,15 @@ bool DirectDrawSurface::isSupported() const
}
if (header.pf.flags & DDPF_FOURCC) {
- if (header.pf.fourcc != FOURCC_DXT1 && header.pf.fourcc != FOURCC_DXT2 &&
- header.pf.fourcc != FOURCC_DXT3 && header.pf.fourcc != FOURCC_DXT4 &&
- header.pf.fourcc != FOURCC_DXT5 && header.pf.fourcc != FOURCC_RXGB &&
- header.pf.fourcc != FOURCC_ATI1 && header.pf.fourcc != FOURCC_ATI2) {
+ if (!ELEM(header.pf.fourcc,
+ FOURCC_DXT1,
+ FOURCC_DXT2,
+ FOURCC_DXT3,
+ FOURCC_DXT4,
+ FOURCC_DXT5,
+ FOURCC_RXGB,
+ FOURCC_ATI1,
+ FOURCC_ATI2)) {
/* Unknown fourcc code. */
return false;
}
diff --git a/source/blender/io/collada/AnimationImporter.cpp b/source/blender/io/collada/AnimationImporter.cpp
index b14de8be7df..8f5d2742b0e 100644
--- a/source/blender/io/collada/AnimationImporter.cpp
+++ b/source/blender/io/collada/AnimationImporter.cpp
@@ -719,7 +719,7 @@ void AnimationImporter::Assign_float_animations(const COLLADAFW::UniqueId &listi
fcurve_deg_to_rad(fcu);
}
}
- /** XXX What About animtype "rotation" ? */
+ /** XXX What About animation-type "rotation" ? */
BLI_addtail(AnimCurves, fcu);
fcurve_is_used(fcu);
@@ -1938,7 +1938,7 @@ bool AnimationImporter::evaluate_animation(COLLADAFW::Transformation *tm,
return false;
}
- /* TODO: support other animclasses. */
+ /* TODO: support other animation-classes. */
if (animclass != COLLADAFW::AnimationList::ANGLE) {
report_class_type_unsupported(path, animclass, type);
return false;
diff --git a/source/blender/io/collada/DocumentImporter.cpp b/source/blender/io/collada/DocumentImporter.cpp
index 6515f7553ad..2ce97bc8b5d 100644
--- a/source/blender/io/collada/DocumentImporter.cpp
+++ b/source/blender/io/collada/DocumentImporter.cpp
@@ -396,8 +396,7 @@ Object *DocumentImporter::create_instance_node(Object *source_ob,
anim_importer.read_node_transform(instance_node, obn);
/* if we also have a source_node (always ;), take its
* transformation matrix and apply it to the newly instantiated
- * object to account for node hierarchy transforms in
- * .dae */
+ * object to account for node hierarchy transforms in `.dae`. */
if (source_node) {
COLLADABU::Math::Matrix4 mat4 = source_node->getTransformationMatrix();
COLLADABU::Math::Matrix4 bmat4 =
diff --git a/source/blender/io/collada/SceneExporter.cpp b/source/blender/io/collada/SceneExporter.cpp
index 6cdfce5f35a..ea95729666a 100644
--- a/source/blender/io/collada/SceneExporter.cpp
+++ b/source/blender/io/collada/SceneExporter.cpp
@@ -189,7 +189,7 @@ void SceneExporter::writeNode(Object *ob)
"blender", con_tag, "lin_error", con->lin_error);
/* not ideal: add the target object name as another parameter.
- * No real mapping in the .dae
+ * No real mapping in the `.dae`.
* Need support for multiple target objects also. */
const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
ListBase targets = {nullptr, nullptr};
diff --git a/source/blender/io/collada/collada_internal.cpp b/source/blender/io/collada/collada_internal.cpp
index db27236b885..da9a4cd4a9b 100644
--- a/source/blender/io/collada/collada_internal.cpp
+++ b/source/blender/io/collada/collada_internal.cpp
@@ -14,8 +14,8 @@
UnitConverter::UnitConverter() : up_axis(COLLADAFW::FileInfo::Z_UP)
{
- axis_angle_to_mat4_single(x_up_mat4, 'Y', -0.5 * M_PI);
- axis_angle_to_mat4_single(y_up_mat4, 'X', 0.5 * M_PI);
+ axis_angle_to_mat4_single(x_up_mat4, 'Y', -M_PI_2);
+ axis_angle_to_mat4_single(y_up_mat4, 'X', M_PI_2);
unit_m4(z_up_mat4);
unit_m4(scale_mat4);
diff --git a/source/blender/io/usd/intern/usd_capi_import.cc b/source/blender/io/usd/intern/usd_capi_import.cc
index f2963c87e41..3054641de2a 100644
--- a/source/blender/io/usd/intern/usd_capi_import.cc
+++ b/source/blender/io/usd/intern/usd_capi_import.cc
@@ -102,7 +102,7 @@ static void convert_to_z_up(pxr::UsdStageRefPtr stage, ImportSettings *r_setting
/* Rotate 90 degrees about the X-axis. */
float rmat[3][3];
float axis[3] = {1.0f, 0.0f, 0.0f};
- axis_angle_normalized_to_mat3(rmat, axis, M_PI / 2.0f);
+ axis_angle_normalized_to_mat3(rmat, axis, M_PI_2);
unit_m4(r_settings->conversion_mat);
copy_m4_m3(r_settings->conversion_mat, rmat);
diff --git a/source/blender/makesdna/DNA_ID.h b/source/blender/makesdna/DNA_ID.h
index 011f3618e15..c3132eeab3d 100644
--- a/source/blender/makesdna/DNA_ID.h
+++ b/source/blender/makesdna/DNA_ID.h
@@ -573,6 +573,10 @@ typedef struct PreviewImage {
#define ID_IS_OVERRIDE_LIBRARY(_id) \
(ID_IS_OVERRIDE_LIBRARY_REAL(_id) || ID_IS_OVERRIDE_LIBRARY_VIRTUAL(_id))
+#define ID_IS_OVERRIDE_LIBRARY_HIERARCHY_ROOT(_id) \
+ (!ID_IS_OVERRIDE_LIBRARY_REAL(_id) || \
+ ((ID *)(_id))->override_library->hierarchy_root == ((ID *)(_id)))
+
#define ID_IS_OVERRIDE_LIBRARY_TEMPLATE(_id) \
(((ID *)(_id))->override_library != NULL && ((ID *)(_id))->override_library->reference == NULL)
@@ -605,7 +609,7 @@ typedef struct PreviewImage {
/** id->flag (persistent). */
enum {
- /** Don't delete the datablock even if unused. */
+ /** Don't delete the data-block even if unused. */
LIB_FAKEUSER = 1 << 9,
/**
* The data-block is a sub-data of another one.
@@ -613,14 +617,14 @@ enum {
*/
LIB_EMBEDDED_DATA = 1 << 10,
/**
- * Datablock is from a library and linked indirectly, with LIB_TAG_INDIRECT
+ * Data-block is from a library and linked indirectly, with LIB_TAG_INDIRECT
* tag set. But the current .blend file also has a weak pointer to it that
* we want to restore if possible, and silently drop if it's missing.
*/
LIB_INDIRECT_WEAK_LINK = 1 << 11,
/**
* The data-block is a sub-data of another one, which is an override.
- * Note that this also applies to shapekeys, even though they are not 100% embedded data...
+ * Note that this also applies to shape-keys, even though they are not 100% embedded data.
*/
LIB_EMBEDDED_DATA_LIB_OVERRIDE = 1 << 12,
/**
diff --git a/source/blender/makesdna/DNA_action_types.h b/source/blender/makesdna/DNA_action_types.h
index fa0898e6ea5..516d3ce94f9 100644
--- a/source/blender/makesdna/DNA_action_types.h
+++ b/source/blender/makesdna/DNA_action_types.h
@@ -875,27 +875,27 @@ typedef enum eSAction_Flag {
SACTION_SHOW_MARKERS = (1 << 14),
} eSAction_Flag;
-/* SpaceAction_Runtime.flag */
+/** #SpaceAction_Runtime.flag */
typedef enum eSAction_Runtime_Flag {
/** Temporary flag to force channel selections to be synced with main */
SACTION_RUNTIME_FLAG_NEED_CHAN_SYNC = (1 << 0),
} eSAction_Runtime_Flag;
-/* SpaceAction Mode Settings */
+/** #SpaceAction.mode */
typedef enum eAnimEdit_Context {
- /* action on the active object */
+ /** Action on the active object. */
SACTCONT_ACTION = 0,
- /* list of all shapekeys on the active object, linked with their F-Curves */
+ /** List of all shape-keys on the active object, linked with their F-Curves. */
SACTCONT_SHAPEKEY = 1,
- /* editing of gpencil data */
+ /** Editing of grease-pencil data. */
SACTCONT_GPENCIL = 2,
- /* dopesheet (default) */
+ /** Dope-sheet (default). */
SACTCONT_DOPESHEET = 3,
- /* mask */
+ /** Mask. */
SACTCONT_MASK = 4,
- /* cache file */
+ /** Cache file */
SACTCONT_CACHEFILE = 5,
- /* timeline - replacement for the standalone "timeline editor" */
+ /** Timeline - replacement for the standalone "timeline editor". */
SACTCONT_TIMELINE = 6,
} eAnimEdit_Context;
diff --git a/source/blender/makesdna/DNA_brush_enums.h b/source/blender/makesdna/DNA_brush_enums.h
index 88be670457a..f8ffe6a0a47 100644
--- a/source/blender/makesdna/DNA_brush_enums.h
+++ b/source/blender/makesdna/DNA_brush_enums.h
@@ -457,9 +457,11 @@ typedef enum eBrushUVSculptTool {
/* Brush.curves_sculpt_tool. */
typedef enum eBrushCurvesSculptTool {
- CURVES_SCULPT_TOOL_TEST1 = 0,
- CURVES_SCULPT_TOOL_TEST2 = 1,
- CURVES_SCULPT_TOOL_TEST3 = 2,
+ CURVES_SCULPT_TOOL_COMB = 0,
+ CURVES_SCULPT_TOOL_DELETE = 1,
+ CURVES_SCULPT_TOOL_SNAKE_HOOK = 2,
+ CURVES_SCULPT_TOOL_TEST1 = 3,
+ CURVES_SCULPT_TOOL_TEST2 = 4,
} eBrushCurvesSculptTool;
/** When #BRUSH_ACCUMULATE is used */
diff --git a/source/blender/makesdna/DNA_curves_types.h b/source/blender/makesdna/DNA_curves_types.h
index 98d2aa4b295..f1626781fc6 100644
--- a/source/blender/makesdna/DNA_curves_types.h
+++ b/source/blender/makesdna/DNA_curves_types.h
@@ -40,6 +40,14 @@ typedef enum HandleType {
BEZIER_HANDLE_ALIGN = 3,
} HandleType;
+/** Method used to calculate a NURBS curve's knot vector. */
+typedef enum KnotsMode {
+ NURBS_KNOT_MODE_NORMAL = 0,
+ NURBS_KNOT_MODE_ENDPOINT = 1,
+ NURBS_KNOT_MODE_BEZIER = 2,
+ NURBS_KNOT_MODE_ENDPOINT_BEZIER = 3,
+} KnotsMode;
+
/**
* A reusable data structure for geometry consisting of many curves. All control point data is
* stored contiguously for better efficiency. Data for each curve is stored as a slice of the
@@ -69,7 +77,8 @@ typedef struct CurvesGeometry {
/**
* The start index of each curve in the point data. The size of each curve can be calculated by
* subtracting the offset from the next offset. That is valid even for the last curve because
- * this array is allocated with a length one larger than the number of splines.
+ * this array is allocated with a length one larger than the number of splines. This is allowed
+ * to be null when there are no curves.
*
* \note This is *not* stored in #CustomData because its size is one larger than #curve_data.
*/
@@ -77,6 +86,7 @@ typedef struct CurvesGeometry {
/**
* All attributes stored on control points (#ATTR_DOMAIN_POINT).
+ * This might not contain a layer for positions if there are no points.
*/
CustomData point_data;
diff --git a/source/blender/makesdna/DNA_gpencil_modifier_types.h b/source/blender/makesdna/DNA_gpencil_modifier_types.h
index e30dd4e1c8f..0539b84e093 100644
--- a/source/blender/makesdna/DNA_gpencil_modifier_types.h
+++ b/source/blender/makesdna/DNA_gpencil_modifier_types.h
@@ -401,6 +401,8 @@ typedef enum eBuildGpencil_Mode {
GP_BUILD_MODE_SEQUENTIAL = 0,
/* All strokes start at the same time */
GP_BUILD_MODE_CONCURRENT = 1,
+ /* Only the new strokes are built */
+ GP_BUILD_MODE_ADDITIVE = 2,
} eBuildGpencil_Mode;
typedef enum eBuildGpencil_Transition {
diff --git a/source/blender/makesdna/DNA_modifier_defaults.h b/source/blender/makesdna/DNA_modifier_defaults.h
index 41cc8048de1..299ac4e2fbe 100644
--- a/source/blender/makesdna/DNA_modifier_defaults.h
+++ b/source/blender/makesdna/DNA_modifier_defaults.h
@@ -145,7 +145,7 @@
.compression_damp = 5.0f, \
.shear_damp = 5.0f, \
.internal_spring_max_length = 0.0f, \
- .internal_spring_max_diversion = M_PI / 4.0f, \
+ .internal_spring_max_diversion = M_PI_4, \
.vgroup_intern = 0, \
.internal_tension = 15.0f, \
.internal_compression = 15.0f, \
diff --git a/source/blender/makesdna/DNA_scene_defaults.h b/source/blender/makesdna/DNA_scene_defaults.h
index 82f788e0623..74db1d14bbc 100644
--- a/source/blender/makesdna/DNA_scene_defaults.h
+++ b/source/blender/makesdna/DNA_scene_defaults.h
@@ -360,6 +360,10 @@
/* GP Stroke Placement */ \
.gpencil_v3d_align = GP_PROJECT_VIEWSPACE, \
.gpencil_v2d_align = GP_PROJECT_VIEWSPACE, \
+ \
+ /* UV painting */ \
+ .uv_sculpt_settings = 0, \
+ .uv_relax_method = UV_SCULPT_TOOL_RELAX_LAPLACIAN, \
}
/* clang-format off */
diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h
index 512be41ce2c..2f8d1c5eafe 100644
--- a/source/blender/makesdna/DNA_scene_types.h
+++ b/source/blender/makesdna/DNA_scene_types.h
@@ -1469,13 +1469,18 @@ typedef struct ToolSettings {
/* Transform */
char transform_pivot_point;
char transform_flag;
+ /** Snap elements (per spacetype). */
char snap_mode;
char snap_node_mode;
char snap_uv_mode;
+ /** Generic flags (per spacetype). */
char snap_flag;
- /** UV equivalent of `snap_flag`, limited to: #SCE_SNAP_ABS_GRID. */
+ char snap_flag_node;
+ char snap_flag_seq;
char snap_uv_flag;
+ /** Default snap source. */
char snap_target;
+ /** Snap mask for transform modes. */
char snap_transform_mode_flag;
char proportional_edit, prop_mode;
@@ -1505,16 +1510,14 @@ typedef struct ToolSettings {
char gpencil_selectmode_vertex;
/* UV painting */
- char _pad2[1];
char uv_sculpt_settings;
char uv_relax_method;
- /* XXX: these sculpt_paint_* fields are deprecated, use the
- * unified_paint_settings field instead! */
- short sculpt_paint_settings DNA_DEPRECATED;
char workspace_tool_type;
- char _pad5[1];
+ /* XXX: these sculpt_paint_* fields are deprecated, use the
+ * unified_paint_settings field instead! */
+ short sculpt_paint_settings DNA_DEPRECATED;
int sculpt_paint_unified_size DNA_DEPRECATED;
float sculpt_paint_unified_unprojected_radius DNA_DEPRECATED;
float sculpt_paint_unified_alpha DNA_DEPRECATED;
@@ -2055,7 +2058,6 @@ enum {
#define SCE_SNAP_NO_SELF (1 << 4)
#define SCE_SNAP_ABS_GRID (1 << 5)
#define SCE_SNAP_BACKFACE_CULLING (1 << 6)
-#define SCE_SNAP_SEQ (1 << 7)
/** #ToolSettings.snap_target */
#define SCE_SNAP_TARGET_CLOSEST 0
diff --git a/source/blender/makesdna/DNA_windowmanager_types.h b/source/blender/makesdna/DNA_windowmanager_types.h
index 42c94832a43..ade0fcdb13f 100644
--- a/source/blender/makesdna/DNA_windowmanager_types.h
+++ b/source/blender/makesdna/DNA_windowmanager_types.h
@@ -294,6 +294,8 @@ typedef struct wmWindow {
/** Storage for event system. */
struct wmEvent *eventstate;
+ /** Keep the last handled event in `event_queue` here (owned and must be freed). */
+ struct wmEvent *event_last_handled;
/* Input Method Editor data - complex character input (especially for Asian character input)
* Currently WIN32 and APPLE, runtime-only data. */
diff --git a/source/blender/makesrna/RNA_types.h b/source/blender/makesrna/RNA_types.h
index 74bcc95d1dd..d4c38060e1b 100644
--- a/source/blender/makesrna/RNA_types.h
+++ b/source/blender/makesrna/RNA_types.h
@@ -258,7 +258,7 @@ typedef enum PropertyFlag {
/**
* flag contains multiple enums.
- * NOTE: not to be confused with prop->enumbitflags
+ * NOTE: not to be confused with `prop->enumbitflags`
* this exposes the flag as multiple options in python and the UI.
*
* \note These can't be animated so use with care.
diff --git a/source/blender/makesrna/intern/makesrna.c b/source/blender/makesrna/intern/makesrna.c
index 01a6108fd8c..3ea7f8e0df6 100644
--- a/source/blender/makesrna/intern/makesrna.c
+++ b/source/blender/makesrna/intern/makesrna.c
@@ -724,10 +724,10 @@ static char *rna_def_property_get_func(
}
else {
const PropertySubType subtype = prop->subtype;
- const char *string_copy_func = (subtype == PROP_FILEPATH || subtype == PROP_DIRPATH ||
- subtype == PROP_FILENAME || subtype == PROP_BYTESTRING) ?
- "BLI_strncpy" :
- "BLI_strncpy_utf8";
+ const char *string_copy_func =
+ ELEM(subtype, PROP_FILEPATH, PROP_DIRPATH, PROP_FILENAME, PROP_BYTESTRING) ?
+ "BLI_strncpy" :
+ "BLI_strncpy_utf8";
rna_print_data_get(f, dp);
@@ -1073,10 +1073,10 @@ static char *rna_def_property_set_func(
}
else {
const PropertySubType subtype = prop->subtype;
- const char *string_copy_func = (subtype == PROP_FILEPATH || subtype == PROP_DIRPATH ||
- subtype == PROP_FILENAME || subtype == PROP_BYTESTRING) ?
- "BLI_strncpy" :
- "BLI_strncpy_utf8";
+ const char *string_copy_func =
+ ELEM(subtype, PROP_FILEPATH, PROP_DIRPATH, PROP_FILENAME, PROP_BYTESTRING) ?
+ "BLI_strncpy" :
+ "BLI_strncpy_utf8";
rna_print_data_get(f, dp);
@@ -2362,7 +2362,12 @@ static void rna_def_struct_function_prototype_cpp(FILE *f,
pout = (flag_parameter & PARM_OUTPUT);
if (flag & PROP_DYNAMIC) {
- ptrstr = pout ? "**" : "*";
+ if (type == PROP_STRING) {
+ ptrstr = pout ? "*" : "";
+ }
+ else {
+ ptrstr = pout ? "**" : "*";
+ }
}
else if (type == PROP_POINTER) {
ptrstr = pout ? "*" : "";
@@ -2853,7 +2858,12 @@ static void rna_def_function_funcs(FILE *f, StructDefRNA *dsrna, FunctionDefRNA
/* XXX only arrays and strings are allowed to be dynamic, is this checked anywhere? */
}
else if (cptr || (flag & PROP_DYNAMIC)) {
- ptrstr = pout ? "**" : "*";
+ if (type == PROP_STRING) {
+ ptrstr = pout ? "*" : "";
+ }
+ else {
+ ptrstr = pout ? "**" : "*";
+ }
/* Fixed size arrays and RNA pointers are pre-allocated on the ParameterList stack,
* pass a pointer to it. */
}
@@ -2933,8 +2943,14 @@ static void rna_def_function_funcs(FILE *f, StructDefRNA *dsrna, FunctionDefRNA
else {
const char *data_str;
if (cptr || (flag & PROP_DYNAMIC)) {
- ptrstr = "**";
- valstr = "*";
+ if (type == PROP_STRING) {
+ ptrstr = "*";
+ valstr = "";
+ }
+ else {
+ ptrstr = "**";
+ valstr = "*";
+ }
}
else if ((type == PROP_POINTER) && !(flag & PROP_THICK_WRAP)) {
ptrstr = "**";
@@ -3531,7 +3547,12 @@ static void rna_generate_static_parameter_prototypes(FILE *f,
}
if (cptr || (flag & PROP_DYNAMIC)) {
- ptrstr = pout ? "**" : "*";
+ if (type == PROP_STRING) {
+ ptrstr = pout ? "*" : "";
+ }
+ else {
+ ptrstr = pout ? "**" : "*";
+ }
}
else if (type == PROP_POINTER || dparm->prop->arraydimension) {
ptrstr = "*";
diff --git a/source/blender/makesrna/intern/rna_ID.c b/source/blender/makesrna/intern/rna_ID.c
index 94ffa330064..a9725da7841 100644
--- a/source/blender/makesrna/intern/rna_ID.c
+++ b/source/blender/makesrna/intern/rna_ID.c
@@ -744,6 +744,11 @@ static void rna_ID_override_library_operations_update(ID *id,
return;
}
+ if (ID_IS_LINKED(id)) {
+ BKE_reportf(reports, RPT_ERROR, "ID '%s' is linked, cannot edit its overrides", id->name);
+ return;
+ }
+
BKE_lib_override_library_operations_create(bmain, id);
WM_main_add_notifier(NC_WM | ND_LIB_OVERRIDE_CHANGED, NULL);
diff --git a/source/blender/makesrna/intern/rna_access.c b/source/blender/makesrna/intern/rna_access.c
index 7ccb8181b51..a6fa369dc73 100644
--- a/source/blender/makesrna/intern/rna_access.c
+++ b/source/blender/makesrna/intern/rna_access.c
@@ -2437,7 +2437,7 @@ void RNA_property_int_set(PointerRNA *ptr, PropertyRNA *prop, int value)
BLI_assert(RNA_property_type(prop) == PROP_INT);
BLI_assert(RNA_property_array_check(prop) == false);
/* useful to check on bad values but set function should clamp */
- /* BLI_assert(RNA_property_int_clamp(ptr, prop, &value) == 0); */
+ // BLI_assert(RNA_property_int_clamp(ptr, prop, &value) == 0);
if ((idprop = rna_idproperty_check(&prop, ptr))) {
RNA_property_int_clamp(ptr, prop, &value);
@@ -3812,7 +3812,7 @@ void RNA_property_collection_add(PointerRNA *ptr, PropertyRNA *prop, PointerRNA
}
IDP_AppendArray(idprop, item);
/* IDP_AppendArray does a shallow copy (memcpy), only free memory. */
- /* IDP_FreePropertyContent(item); */
+ // IDP_FreePropertyContent(item);
MEM_freeN(item);
rna_idproperty_touch(idprop);
}
diff --git a/source/blender/makesrna/intern/rna_brush.c b/source/blender/makesrna/intern/rna_brush.c
index e282b474d8d..6052a742ad5 100644
--- a/source/blender/makesrna/intern/rna_brush.c
+++ b/source/blender/makesrna/intern/rna_brush.c
@@ -244,9 +244,11 @@ const EnumPropertyItem rna_enum_brush_gpencil_weight_types_items[] = {
};
const EnumPropertyItem rna_enum_brush_curves_sculpt_tool_items[] = {
+ {CURVES_SCULPT_TOOL_COMB, "COMB", ICON_NONE, "Comb", ""},
+ {CURVES_SCULPT_TOOL_DELETE, "DELETE", ICON_NONE, "Delete", ""},
+ {CURVES_SCULPT_TOOL_SNAKE_HOOK, "SNAKE_HOOK", ICON_NONE, "Snake Hook", ""},
{CURVES_SCULPT_TOOL_TEST1, "TEST1", ICON_NONE, "Test 1", ""},
{CURVES_SCULPT_TOOL_TEST2, "TEST2", ICON_NONE, "Test 2", ""},
- {CURVES_SCULPT_TOOL_TEST3, "TEST3", ICON_NONE, "Test 3", ""},
{0, NULL, 0, NULL, NULL},
};
@@ -2982,7 +2984,7 @@ static void rna_def_brush(BlenderRNA *brna)
prop = RNA_def_property(srna, "falloff_angle", PROP_FLOAT, PROP_ANGLE);
RNA_def_property_float_sdna(prop, NULL, "falloff_angle");
- RNA_def_property_range(prop, 0, M_PI / 2);
+ RNA_def_property_range(prop, 0, M_PI_2);
RNA_def_property_ui_text(
prop,
"Falloff Angle",
diff --git a/source/blender/makesrna/intern/rna_camera.c b/source/blender/makesrna/intern/rna_camera.c
index 0378e64290b..118589332ea 100644
--- a/source/blender/makesrna/intern/rna_camera.c
+++ b/source/blender/makesrna/intern/rna_camera.c
@@ -136,7 +136,7 @@ static void rna_CameraDOFSettings_aperture_blades_set(PointerRNA *ptr, const int
{
CameraDOFSettings *dofsettings = (CameraDOFSettings *)ptr->data;
- if (value == 1 || value == 2) {
+ if (ELEM(value, 1, 2)) {
if (dofsettings->aperture_blades == 0) {
dofsettings->aperture_blades = 3;
}
@@ -392,13 +392,13 @@ static void rna_def_camera_stereo_data(BlenderRNA *brna)
RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL);
prop = RNA_def_property(srna, "pole_merge_angle_from", PROP_FLOAT, PROP_ANGLE);
- RNA_def_property_range(prop, 0.0f, M_PI / 2.0);
+ RNA_def_property_range(prop, 0.0f, M_PI_2);
RNA_def_property_ui_text(
prop, "Pole Merge Start Angle", "Angle at which interocular distance starts to fade to 0");
RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL);
prop = RNA_def_property(srna, "pole_merge_angle_to", PROP_FLOAT, PROP_ANGLE);
- RNA_def_property_range(prop, 0.0f, M_PI / 2.0);
+ RNA_def_property_range(prop, 0.0f, M_PI_2);
RNA_def_property_ui_text(
prop, "Pole Merge End Angle", "Angle at which interocular distance is 0");
RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL);
diff --git a/source/blender/makesrna/intern/rna_cloth.c b/source/blender/makesrna/intern/rna_cloth.c
index 4ee57017841..3ad901e5397 100644
--- a/source/blender/makesrna/intern/rna_cloth.c
+++ b/source/blender/makesrna/intern/rna_cloth.c
@@ -922,7 +922,7 @@ static void rna_def_cloth_sim_settings(BlenderRNA *brna)
prop = RNA_def_property(srna, "internal_spring_max_diversion", PROP_FLOAT, PROP_ANGLE);
RNA_def_property_float_sdna(prop, NULL, "internal_spring_max_diversion");
- RNA_def_property_range(prop, 0.0f, M_PI / 4.0f);
+ RNA_def_property_range(prop, 0.0f, M_PI_4);
RNA_def_property_ui_text(prop,
"Internal Spring Max Diversion",
"How much the rays used to connect the internal points can diverge "
diff --git a/source/blender/makesrna/intern/rna_constraint.c b/source/blender/makesrna/intern/rna_constraint.c
index 114fe30acf7..63d8876ec8b 100644
--- a/source/blender/makesrna/intern/rna_constraint.c
+++ b/source/blender/makesrna/intern/rna_constraint.c
@@ -1209,6 +1209,9 @@ static void rna_def_constraint_kinematic(BlenderRNA *brna)
prop = RNA_def_property(srna, "chain_count", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "rootbone");
+ /* Changing the IK chain length requires a rebuild of depsgraph relations. This makes it
+ * unsuitable for animation. */
+ RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_range(prop, 0, 255);
RNA_def_property_ui_text(
prop, "Chain Length", "How many bones are included in the IK effect - 0 uses all bones");
@@ -3020,6 +3023,9 @@ static void rna_def_constraint_spline_ik(BlenderRNA *brna)
prop = RNA_def_property(srna, "chain_count", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "chainlen");
+ /* Changing the IK chain length requires a rebuild of depsgraph relations. This makes it
+ * unsuitable for animation. */
+ RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
/* TODO: this should really check the max length of the chain the constraint is attached to */
RNA_def_property_range(prop, 1, 255);
RNA_def_property_ui_text(prop, "Chain Length", "How many bones are included in the chain");
diff --git a/source/blender/makesrna/intern/rna_curve.c b/source/blender/makesrna/intern/rna_curve.c
index 891de95a2a2..fb911725836 100644
--- a/source/blender/makesrna/intern/rna_curve.c
+++ b/source/blender/makesrna/intern/rna_curve.c
@@ -1995,24 +1995,20 @@ static void rna_def_curve_nurb(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Cyclic V", "Make this surface a closed loop in the V direction");
RNA_def_property_update(prop, 0, "rna_Nurb_update_cyclic_v");
- /* NOTE: endpoint and bezier flags should never be on at the same time! */
prop = RNA_def_property(srna, "use_endpoint_u", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flagu", CU_NURB_ENDPOINT);
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_ui_text(
prop,
"Endpoint U",
- "Make this nurbs curve or surface meet the endpoints in the U direction "
- "(Cyclic U must be disabled)");
+ "Make this nurbs curve or surface meet the endpoints in the U direction");
RNA_def_property_update(prop, 0, "rna_Nurb_update_knot_u");
prop = RNA_def_property(srna, "use_endpoint_v", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flagv", CU_NURB_ENDPOINT);
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
- RNA_def_property_ui_text(prop,
- "Endpoint V",
- "Make this nurbs surface meet the endpoints in the V direction "
- "(Cyclic V must be disabled)");
+ RNA_def_property_ui_text(
+ prop, "Endpoint V", "Make this nurbs surface meet the endpoints in the V direction ");
RNA_def_property_update(prop, 0, "rna_Nurb_update_knot_v");
prop = RNA_def_property(srna, "use_bezier_u", PROP_BOOLEAN, PROP_NONE);
@@ -2021,17 +2017,14 @@ static void rna_def_curve_nurb(BlenderRNA *brna)
RNA_def_property_ui_text(
prop,
"Bezier U",
- "Make this nurbs curve or surface act like a Bezier spline in the U direction "
- "(Order U must be 3 or 4, Cyclic U must be disabled)");
+ "Make this nurbs curve or surface act like a Bezier spline in the U direction");
RNA_def_property_update(prop, 0, "rna_Nurb_update_knot_u");
prop = RNA_def_property(srna, "use_bezier_v", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flagv", CU_NURB_BEZIER);
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
- RNA_def_property_ui_text(prop,
- "Bezier V",
- "Make this nurbs surface act like a Bezier spline in the V direction "
- "(Order V must be 3 or 4, Cyclic V must be disabled)");
+ RNA_def_property_ui_text(
+ prop, "Bezier V", "Make this nurbs surface act like a Bezier spline in the V direction");
RNA_def_property_update(prop, 0, "rna_Nurb_update_knot_v");
prop = RNA_def_property(srna, "use_smooth", PROP_BOOLEAN, PROP_NONE);
diff --git a/source/blender/makesrna/intern/rna_curve_api.c b/source/blender/makesrna/intern/rna_curve_api.c
index d0086a425a2..f31e72ce652 100644
--- a/source/blender/makesrna/intern/rna_curve_api.c
+++ b/source/blender/makesrna/intern/rna_curve_api.c
@@ -36,6 +36,39 @@ static float rna_Nurb_calc_length(Nurb *nu, int resolution_u)
return BKE_nurb_calc_length(nu, resolution_u);
}
+static void rna_Nurb_valid_message(Nurb *nu, int direction, int *result_len, const char **r_result)
+{
+ const bool is_surf = nu->pntsv > 1;
+ const short type = nu->type;
+
+ int pnts;
+ short order, flag;
+ const char *dir;
+ if (direction == 0) {
+ pnts = nu->pntsu;
+ order = nu->orderu;
+ flag = nu->flagu;
+ dir = "U";
+ }
+ else {
+ pnts = nu->pntsv;
+ order = nu->orderv;
+ flag = nu->flagv;
+ dir = "V";
+ }
+
+ char buf[64];
+ if (BKE_nurb_valid_message(pnts, order, flag, type, is_surf, dir, buf, sizeof(buf))) {
+ const int buf_len = strlen(buf);
+ *r_result = BLI_strdupn(buf, buf_len);
+ *result_len = buf_len;
+ }
+ else {
+ *r_result = NULL;
+ *result_len = 0;
+ }
+}
+
#else
void RNA_api_curve(StructRNA *srna)
@@ -86,6 +119,22 @@ void RNA_api_curve_nurb(StructRNA *srna)
0.0f,
FLT_MAX);
RNA_def_function_return(func, parm);
+
+ func = RNA_def_function(srna, "valid_message", "rna_Nurb_valid_message");
+ RNA_def_function_ui_description(func, "Return the message");
+ parm = RNA_def_int(
+ func, "direction", 0, 0, 1, "Direction", "The direction where 0-1 maps to U-V", 0, 1);
+ RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
+ /* return value */
+ parm = RNA_def_string(func,
+ "result",
+ "nothing",
+ 64,
+ "Return value",
+ "The message or an empty string when there is no error");
+
+ RNA_def_parameter_flags(parm, PROP_DYNAMIC, PARM_OUTPUT);
+ RNA_def_property_clear_flag(parm, PROP_NEVER_NULL);
}
#endif
diff --git a/source/blender/makesrna/intern/rna_define.c b/source/blender/makesrna/intern/rna_define.c
index 5127b418b7f..8e2b9c1d937 100644
--- a/source/blender/makesrna/intern/rna_define.c
+++ b/source/blender/makesrna/intern/rna_define.c
@@ -2394,8 +2394,7 @@ void RNA_def_property_int_sdna(PropertyRNA *prop, const char *structname, const
iprop->hardmax = iprop->softmax = INT8_MAX;
}
- if (prop->subtype == PROP_UNSIGNED || prop->subtype == PROP_PERCENTAGE ||
- prop->subtype == PROP_FACTOR) {
+ if (ELEM(prop->subtype, PROP_UNSIGNED, PROP_PERCENTAGE, PROP_FACTOR)) {
iprop->hardmin = iprop->softmin = 0;
}
diff --git a/source/blender/makesrna/intern/rna_dynamicpaint.c b/source/blender/makesrna/intern/rna_dynamicpaint.c
index d81e44791f4..ed6d4996c1e 100644
--- a/source/blender/makesrna/intern/rna_dynamicpaint.c
+++ b/source/blender/makesrna/intern/rna_dynamicpaint.c
@@ -237,8 +237,7 @@ static const EnumPropertyItem *rna_DynamicPaint_surface_type_itemf(bContext *UNU
RNA_enum_item_add(&item, &totitem, &tmp);
/* Displace */
- if (surface->format == MOD_DPAINT_SURFACE_F_VERTEX ||
- surface->format == MOD_DPAINT_SURFACE_F_IMAGESEQ) {
+ if (ELEM(surface->format, MOD_DPAINT_SURFACE_F_VERTEX, MOD_DPAINT_SURFACE_F_IMAGESEQ)) {
tmp.value = MOD_DPAINT_SURFACE_T_DISPLACE;
tmp.identifier = "DISPLACE";
tmp.name = "Displace";
diff --git a/source/blender/makesrna/intern/rna_gpencil_modifier.c b/source/blender/makesrna/intern/rna_gpencil_modifier.c
index a619d179a33..33c0b29f6d0 100644
--- a/source/blender/makesrna/intern/rna_gpencil_modifier.c
+++ b/source/blender/makesrna/intern/rna_gpencil_modifier.c
@@ -2070,6 +2070,11 @@ static void rna_def_modifier_gpencilbuild(BlenderRNA *brna)
ICON_PARTICLE_TIP,
"Concurrent",
"Multiple strokes appear/disappear at once"},
+ {GP_BUILD_MODE_ADDITIVE,
+ "ADDITIVE",
+ ICON_PARTICLE_PATH,
+ "Additive",
+ "Builds only new strokes (assuming 'additive' drawing)"},
{0, NULL, 0, NULL, NULL},
};
diff --git a/source/blender/makesrna/intern/rna_key.c b/source/blender/makesrna/intern/rna_key.c
index 7687dcbb11f..50b25157989 100644
--- a/source/blender/makesrna/intern/rna_key.c
+++ b/source/blender/makesrna/intern/rna_key.c
@@ -153,10 +153,10 @@ static void rna_ShapeKey_slider_max_set(PointerRNA *ptr, float value)
# undef SHAPEKEY_SLIDER_TOL
-/* ***** Normals accessors for shapekeys. ***** */
+/* ***** Normals accessors for shape-keys. ***** */
/* NOTE: with this we may recompute several times the same data, should we want to access verts,
* then polys, then loops normals... However,
- * such case looks rather unlikely - and not worth adding some kind of caching in KeyBlocks.
+ * such case looks rather unlikely - and not worth adding some kind of caching in key-blocks.
*/
static Mesh *rna_KeyBlock_normals_get_mesh(PointerRNA *ptr, ID *id)
diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c
index cc97dca9387..640fe3b919b 100644
--- a/source/blender/makesrna/intern/rna_nodetree.c
+++ b/source/blender/makesrna/intern/rna_nodetree.c
@@ -4520,6 +4520,25 @@ static void rna_CompositorNodeScale_update(Main *bmain, Scene *scene, PointerRNA
rna_Node_update(bmain, scene, ptr);
}
+static void rna_ShaderNode_is_active_output_set(PointerRNA *ptr, bool value)
+{
+ bNodeTree *ntree = (bNodeTree *)ptr->owner_id;
+ bNode *node = ptr->data;
+ if (value) {
+ /* If this node becomes the active output, the others of the same type can't be the active
+ * output anymore. */
+ LISTBASE_FOREACH (bNode *, other_node, &ntree->nodes) {
+ if (other_node->type == node->type) {
+ other_node->flag &= ~NODE_DO_OUTPUT;
+ }
+ }
+ node->flag |= NODE_DO_OUTPUT;
+ }
+ else {
+ node->flag &= ~NODE_DO_OUTPUT;
+ }
+}
+
static PointerRNA rna_ShaderNodePointDensity_psys_get(PointerRNA *ptr)
{
bNode *node = ptr->data;
@@ -5288,6 +5307,7 @@ static void def_sh_output(StructRNA *srna)
RNA_def_property_boolean_sdna(prop, NULL, "flag", NODE_DO_OUTPUT);
RNA_def_property_ui_text(
prop, "Active Output", "True if this node is used as the active output");
+ RNA_def_property_boolean_funcs(prop, NULL, "rna_ShaderNode_is_active_output_set");
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
prop = RNA_def_property(srna, "target", PROP_ENUM, PROP_NONE);
diff --git a/source/blender/makesrna/intern/rna_particle.c b/source/blender/makesrna/intern/rna_particle.c
index f61d5456974..2770255802d 100644
--- a/source/blender/makesrna/intern/rna_particle.c
+++ b/source/blender/makesrna/intern/rna_particle.c
@@ -438,8 +438,7 @@ static void rna_ParticleSystem_co_hair(
return;
}
- if (part->ren_as == PART_DRAW_OB || part->ren_as == PART_DRAW_GR ||
- part->ren_as == PART_DRAW_NOT) {
+ if (ELEM(part->ren_as, PART_DRAW_OB, PART_DRAW_GR, PART_DRAW_NOT)) {
return;
}
@@ -836,7 +835,7 @@ static void rna_Particle_target_reset(Main *bmain, Scene *UNUSED(scene), Pointer
ParticleTarget *pt = (ParticleTarget *)ptr->data;
ParticleSystem *kpsys = NULL, *psys = rna_particle_system_for_target(ob, pt);
- if (pt->ob == ob || pt->ob == NULL) {
+ if (ELEM(pt->ob, ob, NULL)) {
kpsys = BLI_findlink(&ob->particlesystem, pt->psys - 1);
if (kpsys) {
@@ -1334,7 +1333,7 @@ static const EnumPropertyItem *rna_Particle_type_itemf(bContext *UNUSED(C),
{
ParticleSettings *part = (ParticleSettings *)ptr->owner_id;
- if (part->type == PART_HAIR || part->type == PART_EMITTER) {
+ if (ELEM(part->type, PART_HAIR, PART_EMITTER)) {
return part_type_items;
}
else {
diff --git a/source/blender/makesrna/intern/rna_rna.c b/source/blender/makesrna/intern/rna_rna.c
index e7c3d90573f..8f1847c00f4 100644
--- a/source/blender/makesrna/intern/rna_rna.c
+++ b/source/blender/makesrna/intern/rna_rna.c
@@ -1451,7 +1451,7 @@ static int rna_property_override_diff_propptr(Main *bmain,
*r_override_changed = true;
}
- if (extended_rna_path != extended_rna_path_buffer && extended_rna_path != rna_path) {
+ if (!ELEM(extended_rna_path, extended_rna_path_buffer, rna_path)) {
MEM_freeN(extended_rna_path);
}
diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c
index 145746cdce4..d398dadbec7 100644
--- a/source/blender/makesrna/intern/rna_scene.c
+++ b/source/blender/makesrna/intern/rna_scene.c
@@ -1425,7 +1425,7 @@ static const EnumPropertyItem *rna_ImageFormatSettings_exr_codec_itemf(bContext
}
for (i = 0; i < R_IMF_EXR_CODEC_MAX; i++) {
- if ((i == R_IMF_EXR_CODEC_B44 || i == R_IMF_EXR_CODEC_B44A)) {
+ if (ELEM(i, R_IMF_EXR_CODEC_B44, R_IMF_EXR_CODEC_B44A)) {
continue; /* B44 and B44A are not defined for 32 bit floats */
}
@@ -3149,6 +3149,25 @@ static void rna_def_tool_settings(BlenderRNA *brna)
RNA_def_property_ui_icon(prop, ICON_SNAP_OFF, 1);
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); /* header redraw */
+ prop = RNA_def_property(srna, "use_snap_node", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "snap_flag_node", SCE_SNAP);
+ RNA_def_property_ui_text(prop, "Snap", "Snap Node during transform");
+ RNA_def_property_ui_icon(prop, ICON_SNAP_OFF, 1);
+ RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); /* header redraw */
+
+ prop = RNA_def_property(srna, "use_snap_sequencer", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "snap_flag_seq", SCE_SNAP);
+ RNA_def_property_ui_text(prop, "Use Snapping", "Snap to strip edges or current frame");
+ RNA_def_property_ui_icon(prop, ICON_SNAP_OFF, 1);
+ RNA_def_property_boolean_default(prop, true);
+ RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); /* Publish message-bus. */
+
+ prop = RNA_def_property(srna, "use_snap_uv", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "snap_uv_flag", SCE_SNAP);
+ RNA_def_property_ui_text(prop, "Snap", "Snap UV during transform");
+ RNA_def_property_ui_icon(prop, ICON_SNAP_OFF, 1);
+ RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); /* header redraw */
+
prop = RNA_def_property(srna, "use_snap_align_rotation", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "snap_flag", SCE_SNAP_ROTATE);
RNA_def_property_ui_text(
@@ -3163,13 +3182,6 @@ static void rna_def_tool_settings(BlenderRNA *brna)
"Absolute grid alignment while translating (based on the pivot center)");
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); /* header redraw */
- prop = RNA_def_property(srna, "use_snap_sequencer", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "snap_flag", SCE_SNAP_SEQ);
- RNA_def_property_ui_text(prop, "Use Snapping", "Snap to strip edges or current frame");
- RNA_def_property_ui_icon(prop, ICON_SNAP_OFF, 1);
- RNA_def_property_boolean_default(prop, true);
- RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); /* Publish message-bus. */
-
prop = RNA_def_property(srna, "snap_elements", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_bitflag_sdna(prop, NULL, "snap_mode");
RNA_def_property_enum_items(prop, rna_enum_snap_element_items);
diff --git a/source/blender/makesrna/intern/rna_text_api.c b/source/blender/makesrna/intern/rna_text_api.c
index 67e93add549..0c0b8a85023 100644
--- a/source/blender/makesrna/intern/rna_text_api.c
+++ b/source/blender/makesrna/intern/rna_text_api.c
@@ -32,6 +32,17 @@ static void rna_Text_write(Text *text, const char *str)
WM_main_add_notifier(NC_TEXT | NA_EDITED, text);
}
+static void rna_Text_from_string(Text *text, const char *str)
+{
+ BKE_text_clear(text);
+ BKE_text_write(text, str);
+}
+
+static void rna_Text_as_string(Text *text, int *r_result_len, const char **result)
+{
+ *result = txt_to_buf(text, r_result_len);
+}
+
static void rna_Text_select_set(Text *text, int startl, int startc, int endl, int endc)
{
txt_sel_set(text, startl, startc, endl, endc);
@@ -60,6 +71,16 @@ void RNA_api_text(StructRNA *srna)
parm = RNA_def_string(func, "text", "Text", 0, "", "New text for this data-block");
RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
+ func = RNA_def_function(srna, "from_string", "rna_Text_from_string");
+ RNA_def_function_ui_description(func, "Replace text with this string.");
+ parm = RNA_def_string(func, "text", "Text", 0, "", "");
+ RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
+
+ func = RNA_def_function(srna, "as_string", "rna_Text_as_string");
+ RNA_def_function_ui_description(func, "Return the text as a string");
+ parm = RNA_def_string(func, "text", "Text", 0, "", "");
+ RNA_def_parameter_flags(parm, PROP_DYNAMIC, PARM_OUTPUT);
+
func = RNA_def_function(
srna, "is_syntax_highlight_supported", "ED_text_is_syntax_highlight_supported");
RNA_def_function_return(func,
diff --git a/source/blender/makesrna/intern/rna_ui.c b/source/blender/makesrna/intern/rna_ui.c
index 00fb48b489a..1d0723851ad 100644
--- a/source/blender/makesrna/intern/rna_ui.c
+++ b/source/blender/makesrna/intern/rna_ui.c
@@ -549,7 +549,7 @@ static void uilist_filter_items(uiList *ui_list,
parm = RNA_function_find_parameter(NULL, func, "filter_flags");
ret_len = RNA_parameter_dynamic_length_get(&list, parm);
- if (ret_len != len && ret_len != 0) {
+ if (!ELEM(ret_len, len, 0)) {
printf("%s: Error, py func returned %d items in %s, %d or none were expected.\n",
__func__,
RNA_parameter_dynamic_length_get(&list, parm),
@@ -565,7 +565,7 @@ static void uilist_filter_items(uiList *ui_list,
parm = RNA_function_find_parameter(NULL, func, "filter_neworder");
ret_len = RNA_parameter_dynamic_length_get(&list, parm);
- if (ret_len != len && ret_len != 0) {
+ if (!ELEM(ret_len, len, 0)) {
printf("%s: Error, py func returned %d items in %s, %d or none were expected.\n",
__func__,
RNA_parameter_dynamic_length_get(&list, parm),
diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c
index 339d0bf380c..3b9632342ec 100644
--- a/source/blender/makesrna/intern/rna_userdef.c
+++ b/source/blender/makesrna/intern/rna_userdef.c
@@ -638,7 +638,7 @@ static void rna_userdef_autosave_update(Main *bmain, Scene *scene, PointerRNA *p
wmWindowManager *wm = bmain->wm.first;
if (wm) {
- WM_autosave_init(wm);
+ WM_file_autosave_init(wm);
}
rna_userdef_update(bmain, scene, ptr);
}
diff --git a/source/blender/makesrna/intern/rna_wm.c b/source/blender/makesrna/intern/rna_wm.c
index 8835591f303..a850f8862bc 100644
--- a/source/blender/makesrna/intern/rna_wm.c
+++ b/source/blender/makesrna/intern/rna_wm.c
@@ -98,11 +98,13 @@ static const EnumPropertyItem event_ndof_type_items[] = {
{NDOF_BUTTON_DOMINANT, "NDOF_BUTTON_DOMINANT", 0, "Dominant", ""},
{NDOF_BUTTON_PLUS, "NDOF_BUTTON_PLUS", 0, "Plus", ""},
{NDOF_BUTTON_MINUS, "NDOF_BUTTON_MINUS", 0, "Minus", ""},
+# if 0 /* Never used (converted to keyboard events by GHOST). */
/* keyboard emulation */
{NDOF_BUTTON_ESC, "NDOF_BUTTON_ESC", 0, "Esc"},
{NDOF_BUTTON_ALT, "NDOF_BUTTON_ALT", 0, "Alt"},
{NDOF_BUTTON_SHIFT, "NDOF_BUTTON_SHIFT", 0, "Shift"},
{NDOF_BUTTON_CTRL, "NDOF_BUTTON_CTRL", 0, "Ctrl"},
+# endif
/* general-purpose buttons */
{NDOF_BUTTON_1, "NDOF_BUTTON_1", 0, "Button 1", ""},
{NDOF_BUTTON_2, "NDOF_BUTTON_2", 0, "Button 2", ""},
@@ -311,11 +313,13 @@ const EnumPropertyItem rna_enum_event_type_items[] = {
{NDOF_BUTTON_DOMINANT, "NDOF_BUTTON_DOMINANT", 0, "NDOF Dominant", "NdofDom"},
{NDOF_BUTTON_PLUS, "NDOF_BUTTON_PLUS", 0, "NDOF Plus", "Ndof+"},
{NDOF_BUTTON_MINUS, "NDOF_BUTTON_MINUS", 0, "NDOF Minus", "Ndof-"},
+#if 0 /* Never used (converted to keyboard events by GHOST). */
/* keyboard emulation */
{NDOF_BUTTON_ESC, "NDOF_BUTTON_ESC", 0, "NDOF Esc", "NdofEsc"},
{NDOF_BUTTON_ALT, "NDOF_BUTTON_ALT", 0, "NDOF Alt", "NdofAlt"},
{NDOF_BUTTON_SHIFT, "NDOF_BUTTON_SHIFT", 0, "NDOF Shift", "NdofShift"},
{NDOF_BUTTON_CTRL, "NDOF_BUTTON_CTRL", 0, "NDOF Ctrl", "NdofCtrl"},
+#endif
/* general-purpose buttons */
{NDOF_BUTTON_1, "NDOF_BUTTON_1", 0, "NDOF Button 1", "NdofB1"},
{NDOF_BUTTON_2, "NDOF_BUTTON_2", 0, "NDOF Button 2", "NdofB2"},
@@ -2098,6 +2102,20 @@ static void rna_def_event(BlenderRNA *brna)
RNA_def_property_ui_text(
prop, "Mouse Previous Y Position", "The window relative vertical location of the mouse");
+ prop = RNA_def_property(srna, "mouse_prev_press_x", PROP_INT, PROP_NONE);
+ RNA_def_property_int_sdna(prop, NULL, "prev_press_xy[0]");
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_ui_text(prop,
+ "Mouse Previous X Press Position",
+ "The window relative horizontal location of the last press event");
+
+ prop = RNA_def_property(srna, "mouse_prev_press_y", PROP_INT, PROP_NONE);
+ RNA_def_property_int_sdna(prop, NULL, "prev_press_xy[1]");
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_ui_text(prop,
+ "Mouse Previous Y Press Position",
+ "The window relative vertical location of the last press event");
+
prop = RNA_def_property(srna, "pressure", PROP_FLOAT, PROP_FACTOR);
RNA_def_property_float_default(prop, 1.0f);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
diff --git a/source/blender/makesrna/intern/rna_xr.c b/source/blender/makesrna/intern/rna_xr.c
index 9fe3153eb1e..d8be9b7e80d 100644
--- a/source/blender/makesrna/intern/rna_xr.c
+++ b/source/blender/makesrna/intern/rna_xr.c
@@ -33,7 +33,7 @@ static wmXrData *rna_XrSession_wm_xr_data_get(PointerRNA *ptr)
/* Callers could also get XrSessionState pointer through ptr->data, but prefer if we just
* consistently pass wmXrData pointers to the WM_xr_xxx() API. */
- BLI_assert((ptr->type == &RNA_XrSessionSettings) || (ptr->type == &RNA_XrSessionState));
+ BLI_assert(ELEM(ptr->type, &RNA_XrSessionSettings, &RNA_XrSessionState));
wmWindowManager *wm = (wmWindowManager *)ptr->owner_id;
BLI_assert(wm && (GS(wm->id.name) == ID_WM));
@@ -739,7 +739,7 @@ static bool rna_XrSessionState_action_create(bContext *C,
return false;
}
- const bool is_float_action = (ami->type == XR_FLOAT_INPUT || ami->type == XR_VECTOR2F_INPUT);
+ const bool is_float_action = ELEM(ami->type, XR_FLOAT_INPUT, XR_VECTOR2F_INPUT);
const bool is_button_action = (is_float_action || ami->type == XR_BOOLEAN_INPUT);
wmOperatorType *ot = NULL;
IDProperty *op_properties = NULL;
@@ -791,7 +791,7 @@ static bool rna_XrSessionState_action_binding_create(bContext *C,
return false;
}
- const bool is_float_action = (ami->type == XR_FLOAT_INPUT || ami->type == XR_VECTOR2F_INPUT);
+ const bool is_float_action = ELEM(ami->type, XR_FLOAT_INPUT, XR_VECTOR2F_INPUT);
const bool is_button_action = (is_float_action || ami->type == XR_BOOLEAN_INPUT);
const bool is_pose_action = (ami->type == XR_POSE_INPUT);
float float_thresholds[2];
diff --git a/source/blender/modifiers/intern/MOD_edgesplit.c b/source/blender/modifiers/intern/MOD_edgesplit.c
index 9450a444042..b19caefae29 100644
--- a/source/blender/modifiers/intern/MOD_edgesplit.c
+++ b/source/blender/modifiers/intern/MOD_edgesplit.c
@@ -94,7 +94,8 @@ Mesh *doEdgeSplit(const Mesh *mesh, EdgeSplitModifierData *emd)
BM_mesh_edgesplit(bm, false, true, false);
- /* BM_mesh_validate(bm); */ /* for troubleshooting */
+ /* Uncomment for troubleshooting. */
+ // BM_mesh_validate(bm);
result = BKE_mesh_from_bmesh_for_eval_nomain(bm, NULL, mesh);
BM_mesh_free(bm);
diff --git a/source/blender/modifiers/intern/MOD_ui_common.c b/source/blender/modifiers/intern/MOD_ui_common.c
index 90652c180c6..eddf4bd03e1 100644
--- a/source/blender/modifiers/intern/MOD_ui_common.c
+++ b/source/blender/modifiers/intern/MOD_ui_common.c
@@ -63,7 +63,7 @@ static void modifier_reorder(bContext *C, Panel *panel, int new_index)
WM_operator_properties_create_ptr(&props_ptr, ot);
RNA_string_set(&props_ptr, "modifier", md->name);
RNA_int_set(&props_ptr, "index", new_index);
- WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &props_ptr);
+ WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &props_ptr, NULL);
WM_operator_properties_free(&props_ptr);
}
diff --git a/source/blender/modifiers/intern/MOD_ui_common.h b/source/blender/modifiers/intern/MOD_ui_common.h
index 16e9dd25253..6548a897be9 100644
--- a/source/blender/modifiers/intern/MOD_ui_common.h
+++ b/source/blender/modifiers/intern/MOD_ui_common.h
@@ -51,8 +51,8 @@ struct PanelType *modifier_panel_register(struct ARegionType *region_type,
/**
* Add a child panel to the parent.
*
- * \note To create the panel type's idname, it appends the \a name argument to the \a parent's
- * idname.
+ * \note To create the panel type's #PanelType.idname,
+ * it appends the \a name argument to the \a parent's `idname`.
*/
struct PanelType *modifier_subpanel_register(struct ARegionType *region_type,
const char *name,
diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_curve_reverse.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_curve_reverse.cc
index 2fe06a17adf..2c801642bd7 100644
--- a/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_curve_reverse.cc
+++ b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_curve_reverse.cc
@@ -41,7 +41,7 @@ static void node_geo_exec(GeoNodeExecParams params)
}
});
- geometry_set.replace_curve(curve_eval_to_curves(*curve));
+ geometry_set.replace_curves(curve_eval_to_curves(*curve));
params.set_output("Curve", geometry_set);
}
diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_curve_set_handles.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_curve_set_handles.cc
index 537c7c42610..56e9068882b 100644
--- a/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_curve_set_handles.cc
+++ b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_curve_set_handles.cc
@@ -101,7 +101,7 @@ static void node_geo_exec(GeoNodeExecParams params)
bezier_spline.mark_cache_invalid();
}
- geometry_set.replace_curve(curve_eval_to_curves(*curve));
+ geometry_set.replace_curves(curve_eval_to_curves(*curve));
if (!has_bezier_spline) {
params.error_message_add(NodeWarningType::Info, TIP_("No Bezier splines in input curve"));
diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_curve_spline_type.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_curve_spline_type.cc
index 4e3b0839da7..002c42c4c82 100644
--- a/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_curve_spline_type.cc
+++ b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_curve_spline_type.cc
@@ -100,7 +100,7 @@ static SplinePtr poly_to_nurbs(const Spline &input)
output->set_resolution(12);
output->set_order(4);
Spline::copy_base_settings(input, *output);
- output->knots_mode = NURBSpline::KnotsMode::Bezier;
+ output->knots_mode = NURBS_KNOT_MODE_BEZIER;
output->attributes = input.attributes;
return output;
}
@@ -128,7 +128,7 @@ static SplinePtr bezier_to_nurbs(const Spline &input)
output->set_resolution(12);
output->set_order(4);
output->set_cyclic(input.is_cyclic());
- output->knots_mode = NURBSpline::KnotsMode::Bezier;
+ output->knots_mode = NURBS_KNOT_MODE_BEZIER;
output->attributes.reallocate(output->size());
copy_attributes(input, *output, [](GSpan src, GMutableSpan dst) {
attribute_math::convert_to_static_type(src.type(), [&](auto dummy) {
diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_mesh_to_curve.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_mesh_to_curve.cc
index 8991261a21a..72cb540df4a 100644
--- a/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_mesh_to_curve.cc
+++ b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_mesh_to_curve.cc
@@ -45,10 +45,8 @@ static void node_geo_exec(GeoNodeExecParams params)
return;
}
- std::unique_ptr<CurveEval> curve = geometry::mesh_to_curve_convert(
- component, IndexMask(selected_edge_indices));
-
- params.set_output("Curve", GeometrySet::create_with_curves(curve_eval_to_curves(*curve)));
+ Curves *curves = geometry::mesh_to_curve_convert(component, IndexMask(selected_edge_indices));
+ params.set_output("Curve", GeometrySet::create_with_curves(curves));
}
} // namespace blender::nodes::node_geo_legacy_mesh_to_curve_cc
diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_fill.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_fill.cc
index 6702ee6c0aa..08aa7415073 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_curve_fill.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_curve_fill.cc
@@ -120,7 +120,7 @@ static void curve_fill_calculate(GeometrySet &geometry_set, const GeometryNodeCu
const std::unique_ptr<CurveEval> curve = curves_to_curve_eval(
*geometry_set.get_curves_for_read());
if (curve->splines().is_empty()) {
- geometry_set.replace_curve(nullptr);
+ geometry_set.replace_curves(nullptr);
return;
}
@@ -132,7 +132,7 @@ static void curve_fill_calculate(GeometrySet &geometry_set, const GeometryNodeCu
Mesh *mesh = cdt_to_mesh(results);
geometry_set.replace_mesh(mesh);
- geometry_set.replace_curve(nullptr);
+ geometry_set.replace_curves(nullptr);
}
static void node_geo_exec(GeoNodeExecParams params)
diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_fillet.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_fillet.cc
index 24d72ad553b..81ca87eec25 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_curve_fillet.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_curve_fillet.cc
@@ -283,7 +283,7 @@ static void limit_radii(FilletData &fd, const bool cyclic)
/* Assign the max_radii to the fillet data's radii. */
for (const int i : IndexRange(size)) {
- radii[i] = max_radii[i];
+ radii[i] = std::min(radii[i], max_radii[i]);
}
}
@@ -606,7 +606,7 @@ static void calculate_curve_fillet(GeometrySet &geometry_set,
const std::unique_ptr<CurveEval> input_curve = curves_to_curve_eval(*component.get_for_read());
std::unique_ptr<CurveEval> output_curve = fillet_curve(*input_curve, fillet_param);
- geometry_set.replace_curve(curve_eval_to_curves(*output_curve));
+ geometry_set.replace_curves(curve_eval_to_curves(*output_curve));
}
static void node_geo_exec(GeoNodeExecParams params)
diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_handle_type_selection.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_handle_type_selection.cc
index ccd3a587e63..0aa603a7736 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_curve_handle_type_selection.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_curve_handle_type_selection.cc
@@ -112,7 +112,6 @@ class HandleTypeFieldInput final : public GeometryFieldInput {
bool is_equal_to(const fn::FieldNode &other) const override
{
- return dynamic_cast<const HandleTypeFieldInput *>(&other) != nullptr;
if (const HandleTypeFieldInput *other_handle_selection =
dynamic_cast<const HandleTypeFieldInput *>(&other)) {
return mode_ == other_handle_selection->mode_ && type_ == other_handle_selection->type_;
diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_primitive_circle.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_primitive_circle.cc
index 874e29dda86..2fb9f724130 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_curve_primitive_circle.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_curve_primitive_circle.cc
@@ -176,7 +176,7 @@ static void node_geo_exec(GeoNodeExecParams params)
const GeometryNodeCurvePrimitiveCircleMode mode = (GeometryNodeCurvePrimitiveCircleMode)
storage.mode;
- Curves *curves;
+ Curves *curves = nullptr;
if (mode == GEO_NODE_CURVE_PRIMITIVE_CIRCLE_TYPE_POINTS) {
float3 center_point;
curves = create_point_circle_curve(params.extract_input<float3>("Point 1"),
diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_resample.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_resample.cc
index c5814a9a1dd..5a4c2ad1660 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_curve_resample.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_curve_resample.cc
@@ -242,7 +242,7 @@ static void geometry_set_curve_resample(GeometrySet &geometry_set,
std::unique_ptr<CurveEval> output_curve = resample_curve(
geometry_set.get_component_for_read<CurveComponent>(), mode_param);
- geometry_set.replace_curve(curve_eval_to_curves(*output_curve));
+ geometry_set.replace_curves(curve_eval_to_curves(*output_curve));
}
static void node_geo_exec(GeoNodeExecParams params)
diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_spline_type.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_spline_type.cc
index 55610ec86ab..4118448b237 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_curve_spline_type.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_curve_spline_type.cc
@@ -58,21 +58,22 @@ static void scale_output_assign(const Span<T> input,
template<class T>
static void nurbs_to_bezier_assign(const Span<T> input,
const MutableSpan<T> r_output,
- const NURBSpline::KnotsMode knotsMode)
+ const KnotsMode knotsMode)
{
const int input_size = input.size();
const int output_size = r_output.size();
switch (knotsMode) {
- case NURBSpline::KnotsMode::Bezier:
+ case NURBS_KNOT_MODE_BEZIER:
scale_input_assign<T>(input, 3, 1, r_output);
break;
- case NURBSpline::KnotsMode::Normal:
+ case NURBS_KNOT_MODE_NORMAL:
for (const int i : IndexRange(output_size)) {
r_output[i] = input[(i + 1) % input_size];
}
break;
- case NURBSpline::KnotsMode::EndPoint:
+ case NURBS_KNOT_MODE_ENDPOINT_BEZIER:
+ case NURBS_KNOT_MODE_ENDPOINT:
for (const int i : IndexRange(1, output_size - 2)) {
r_output[i] = input[i + 1];
}
@@ -107,11 +108,11 @@ static void copy_attributes(const Spline &input_spline, Spline &output_spline, C
}
static Vector<float3> create_nurbs_to_bezier_handles(const Span<float3> nurbs_positions,
- const NURBSpline::KnotsMode knots_mode)
+ const KnotsMode knots_mode)
{
const int nurbs_positions_size = nurbs_positions.size();
Vector<float3> handle_positions;
- if (knots_mode == NURBSpline::KnotsMode::Bezier) {
+ if (knots_mode == NURBS_KNOT_MODE_BEZIER) {
for (const int i : IndexRange(nurbs_positions_size)) {
if (i % 3 == 1) {
continue;
@@ -127,7 +128,7 @@ static Vector<float3> create_nurbs_to_bezier_handles(const Span<float3> nurbs_po
}
}
else {
- const bool is_periodic = knots_mode == NURBSpline::KnotsMode::Normal;
+ const bool is_periodic = knots_mode == NURBS_KNOT_MODE_NORMAL;
if (is_periodic) {
handle_positions.append(nurbs_positions[1] +
((nurbs_positions[0] - nurbs_positions[1]) / 3));
@@ -169,9 +170,9 @@ static Vector<float3> create_nurbs_to_bezier_handles(const Span<float3> nurbs_po
static Array<float3> create_nurbs_to_bezier_positions(const Span<float3> nurbs_positions,
const Span<float3> handle_positions,
- const NURBSpline::KnotsMode knots_mode)
+ const KnotsMode knots_mode)
{
- if (knots_mode == NURBSpline::KnotsMode::Bezier) {
+ if (knots_mode == NURBS_KNOT_MODE_BEZIER) {
/* Every third NURBS position (starting from index 1) should be converted to Bezier position */
const int scale = 3;
const int offset = 1;
@@ -211,7 +212,7 @@ static SplinePtr poly_to_nurbs(const Spline &input)
output->set_resolution(12);
output->set_order(4);
Spline::copy_base_settings(input, *output);
- output->knots_mode = NURBSpline::KnotsMode::Bezier;
+ output->knots_mode = NURBS_KNOT_MODE_BEZIER;
output->attributes = input.attributes;
return output;
}
@@ -239,7 +240,7 @@ static SplinePtr bezier_to_nurbs(const Spline &input)
output->set_resolution(12);
output->set_order(4);
output->set_cyclic(input.is_cyclic());
- output->knots_mode = NURBSpline::KnotsMode::Bezier;
+ output->knots_mode = NURBS_KNOT_MODE_BEZIER;
output->attributes.reallocate(output->size());
copy_attributes(input, *output, [](GSpan src, GMutableSpan dst) {
attribute_math::convert_to_static_type(src.type(), [&](auto dummy) {
@@ -272,13 +273,13 @@ static SplinePtr nurbs_to_bezier(const Spline &input)
const NURBSpline &nurbs_spline = static_cast<const NURBSpline &>(input);
Span<float3> nurbs_positions;
Vector<float3> nurbs_positions_vector;
- NURBSpline::KnotsMode knots_mode;
+ KnotsMode knots_mode;
if (nurbs_spline.is_cyclic()) {
nurbs_positions_vector = nurbs_spline.positions();
nurbs_positions_vector.append(nurbs_spline.positions()[0]);
nurbs_positions_vector.append(nurbs_spline.positions()[1]);
nurbs_positions = nurbs_positions_vector;
- knots_mode = NURBSpline::KnotsMode::Normal;
+ knots_mode = NURBS_KNOT_MODE_NORMAL;
}
else {
nurbs_positions = nurbs_spline.positions();
@@ -403,7 +404,7 @@ static void node_geo_exec(GeoNodeExecParams params)
}
});
new_curve->attributes = curve->attributes;
- geometry_set.replace_curve(curve_eval_to_curves(*new_curve));
+ geometry_set.replace_curves(curve_eval_to_curves(*new_curve));
});
params.set_output("Curve", std::move(geometry_set));
diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_subdivide.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_subdivide.cc
index bbe57b2b3fa..371556c04f1 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_curve_subdivide.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_curve_subdivide.cc
@@ -206,6 +206,10 @@ static void subdivide_bezier_spline(const BezierSpline &src,
}
else {
dst_positions.last() = src_positions.last();
+ dst_type_left.first() = src.handle_types_left().first();
+ dst_type_right.last() = src.handle_types_right().last();
+ dst_handles_left.first() = src_handles_left.first();
+ dst_handles_right.last() = src_handles_right.last();
}
}
@@ -342,7 +346,7 @@ static void node_geo_exec(GeoNodeExecParams params)
}
std::unique_ptr<CurveEval> output_curve = subdivide_curve(
*curves_to_curve_eval(*component.get_for_read()), cuts);
- geometry_set.replace_curve(curve_eval_to_curves(*output_curve));
+ geometry_set.replace_curves(curve_eval_to_curves(*output_curve));
});
params.set_output("Curve", geometry_set);
}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_trim.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_trim.cc
index a3dab1b50fe..df360818313 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_curve_trim.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_curve_trim.cc
@@ -566,7 +566,7 @@ static void geometry_set_curve_trim(GeometrySet &geometry_set,
}
});
- geometry_set.replace_curve(curve_eval_to_curves(*curve));
+ geometry_set.replace_curves(curve_eval_to_curves(*curve));
}
static void node_geo_exec(GeoNodeExecParams params)
diff --git a/source/blender/nodes/geometry/nodes/node_geo_delete_geometry.cc b/source/blender/nodes/geometry/nodes/node_geo_delete_geometry.cc
index 3baee8a25bb..cf6837817c2 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_delete_geometry.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_delete_geometry.cc
@@ -477,10 +477,10 @@ static void separate_curve_selection(GeometrySet &geometry_set,
std::unique_ptr<CurveEval> r_curve = curve_separate(
*curves_to_curve_eval(*src_component.get_for_read()), selection, selection_domain, invert);
if (r_curve) {
- geometry_set.replace_curve(curve_eval_to_curves(*r_curve));
+ geometry_set.replace_curves(curve_eval_to_curves(*r_curve));
}
else {
- geometry_set.replace_curve(nullptr);
+ geometry_set.replace_curves(nullptr);
}
}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_duplicate_elements.cc b/source/blender/nodes/geometry/nodes/node_geo_duplicate_elements.cc
index 1ceab18c01b..eb216c08289 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_duplicate_elements.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_duplicate_elements.cc
@@ -599,7 +599,7 @@ static void duplicate_splines(GeometrySet &geometry_set,
dst_component, ATTR_DOMAIN_CURVE, selection, attributes, curve_offsets);
}
- geometry_set.replace_curve(dst_component.get_for_write());
+ geometry_set.replace_curves(dst_component.get_for_write());
}
static void duplicate_faces(GeometrySet &geometry_set,
diff --git a/source/blender/nodes/geometry/nodes/node_geo_image_texture.cc b/source/blender/nodes/geometry/nodes/node_geo_image_texture.cc
index a87aef358e1..33802d00d2b 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_image_texture.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_image_texture.cc
@@ -257,8 +257,8 @@ class ImageFieldsFunction : public fn::MultiFunction {
const int width = ibuf->x;
const int height = ibuf->y;
int ix, iy;
- const float tx = frac(px * (float)width - 0.5f, &ix);
- const float ty = frac(py * (float)height - 0.5f, &iy);
+ const float tx = frac(px * (float)width, &ix);
+ const float ty = frac(py * (float)height, &iy);
switch (extension) {
case SHD_IMAGE_EXTENSION_REPEAT: {
diff --git a/source/blender/nodes/geometry/nodes/node_geo_input_spline_length.cc b/source/blender/nodes/geometry/nodes/node_geo_input_spline_length.cc
index f952e15fbbe..c3d87055745 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_input_spline_length.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_input_spline_length.cc
@@ -25,13 +25,16 @@ static VArray<float> construct_spline_length_gvarray(const CurveComponent &compo
const std::unique_ptr<CurveEval> curve = curves_to_curve_eval(*component.get_for_read());
Span<SplinePtr> splines = curve->splines();
- auto length_fn = [splines](int i) { return splines[i]->length(); };
+ Array<float> spline_lenghts(splines.size());
+ for (const int i : splines.index_range()) {
+ spline_lenghts[i] = splines[i]->length();
+ }
if (domain == ATTR_DOMAIN_CURVE) {
- return VArray<float>::ForFunc(splines.size(), length_fn);
+ return VArray<float>::ForContainer(std::move(spline_lenghts));
}
if (domain == ATTR_DOMAIN_POINT) {
- VArray<float> length = VArray<float>::ForFunc(splines.size(), length_fn);
+ VArray<float> length = VArray<float>::ForContainer(std::move(spline_lenghts));
return component.attribute_try_adapt_domain<float>(
std::move(length), ATTR_DOMAIN_CURVE, ATTR_DOMAIN_POINT);
}
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 d84a2e73172..b882d4bdf09 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
@@ -510,11 +510,11 @@ static void calculate_selection_outputs(Mesh *mesh,
if (config.bottom_is_point) {
selection[config.last_vert] = true;
}
+ else if (face) {
+ selection.slice(config.bottom_faces_start, config.bottom_faces_len).fill(true);
+ }
else {
- selection
- .slice(config.bottom_faces_start,
- face ? config.bottom_faces_len : config.circle_segments)
- .fill(true);
+ selection.slice(config.last_ring_verts_start + 1, config.circle_segments).fill(true);
}
attribute.save();
}
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 4a09fd8d1d2..4e0e5c7c912 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
@@ -76,10 +76,10 @@ static void calculate_sphere_vertex_data(MutableSpan<MVert> verts,
int vert_index = 1;
for (const int ring : IndexRange(1, rings - 1)) {
const float theta = ring * delta_theta;
+ const float sin_theta = std::sin(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);
diff --git a/source/blender/nodes/geometry/nodes/node_geo_mesh_to_curve.cc b/source/blender/nodes/geometry/nodes/node_geo_mesh_to_curve.cc
index 91cde52f9eb..f6ee3d00dee 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_mesh_to_curve.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_mesh_to_curve.cc
@@ -34,8 +34,7 @@ static void node_geo_exec(GeoNodeExecParams params)
return;
}
- std::unique_ptr<CurveEval> curve = geometry::mesh_to_curve_convert(component, selection);
- geometry_set.replace_curve(curve_eval_to_curves(*curve));
+ geometry_set.replace_curves(geometry::mesh_to_curve_convert(component, selection));
geometry_set.keep_only({GEO_COMPONENT_TYPE_CURVE, GEO_COMPONENT_TYPE_INSTANCES});
});
diff --git a/source/blender/nodes/geometry/nodes/node_geo_transform.cc b/source/blender/nodes/geometry/nodes/node_geo_transform.cc
index 95cec8eab11..9159ac081e0 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_transform.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_transform.cc
@@ -129,7 +129,7 @@ static void translate_geometry_set(GeometrySet &geometry,
if (Curves *curves = geometry.get_curves_for_write()) {
std::unique_ptr<CurveEval> curve = curves_to_curve_eval(*curves);
curve->translate(translation);
- geometry.replace_curve(curve_eval_to_curves(*curve));
+ geometry.replace_curves(curve_eval_to_curves(*curve));
}
if (Mesh *mesh = geometry.get_mesh_for_write()) {
translate_mesh(*mesh, translation);
@@ -152,7 +152,7 @@ void transform_geometry_set(GeometrySet &geometry,
if (Curves *curves = geometry.get_curves_for_write()) {
std::unique_ptr<CurveEval> curve = curves_to_curve_eval(*curves);
curve->transform(transform);
- geometry.replace_curve(curve_eval_to_curves(*curve));
+ geometry.replace_curves(curve_eval_to_curves(*curve));
}
if (Mesh *mesh = geometry.get_mesh_for_write()) {
transform_mesh(*mesh, transform);
diff --git a/source/blender/nodes/shader/nodes/node_shader_bsdf_principled.cc b/source/blender/nodes/shader/nodes/node_shader_bsdf_principled.cc
index 6c2f38fc723..ba98a797f2a 100644
--- a/source/blender/nodes/shader/nodes/node_shader_bsdf_principled.cc
+++ b/source/blender/nodes/shader/nodes/node_shader_bsdf_principled.cc
@@ -43,7 +43,7 @@ static void node_declare(NodeDeclarationBuilder &b)
.max(1.0f)
.subtype(PROP_FACTOR);
b.add_input<decl::Float>(N_("Specular Tint"))
- .default_value(0.5f)
+ .default_value(0.0f)
.min(0.0f)
.max(1.0f)
.subtype(PROP_FACTOR);
diff --git a/source/blender/nodes/shader/nodes/node_shader_object_info.cc b/source/blender/nodes/shader/nodes/node_shader_object_info.cc
index 6ed5a7b715d..03c1a018d37 100644
--- a/source/blender/nodes/shader/nodes/node_shader_object_info.cc
+++ b/source/blender/nodes/shader/nodes/node_shader_object_info.cc
@@ -9,6 +9,7 @@ static void node_declare(NodeDeclarationBuilder &b)
{
b.add_output<decl::Vector>(N_("Location"));
b.add_output<decl::Color>(N_("Color"));
+ b.add_output<decl::Float>(N_("Alpha"));
b.add_output<decl::Float>(N_("Object Index"));
b.add_output<decl::Float>(N_("Material Index"));
b.add_output<decl::Float>(N_("Random"));
diff --git a/source/blender/python/generic/idprop_py_api.c b/source/blender/python/generic/idprop_py_api.c
index c05c003b176..2fbb6b8ee05 100644
--- a/source/blender/python/generic/idprop_py_api.c
+++ b/source/blender/python/generic/idprop_py_api.c
@@ -756,7 +756,16 @@ static int BPy_IDGroup_Map_SetItem(BPy_IDProperty *self, PyObject *key, PyObject
static PyObject *BPy_IDGroup_iter(BPy_IDProperty *self)
{
- return BPy_IDGroup_ViewKeys_CreatePyObject(self);
+ PyObject *iterable = BPy_IDGroup_ViewKeys_CreatePyObject(self);
+ PyObject *ret;
+ if (iterable) {
+ ret = PyObject_GetIter(iterable);
+ Py_DECREF(iterable);
+ }
+ else {
+ ret = NULL;
+ }
+ return ret;
}
PyObject *BPy_IDGroup_MapDataToPy(IDProperty *prop)
diff --git a/source/blender/python/gpu/gpu_py_texture.c b/source/blender/python/gpu/gpu_py_texture.c
index ab038423878..0ad55aeac78 100644
--- a/source/blender/python/gpu/gpu_py_texture.c
+++ b/source/blender/python/gpu/gpu_py_texture.c
@@ -545,11 +545,11 @@ static struct PyMethodDef pygpu_texture__m_methods[] = {
{NULL, NULL, 0, NULL},
};
-PyDoc_STRVAR(pygpu_texure__m_doc, "This module provides utils for textures.");
+PyDoc_STRVAR(pygpu_texture__m_doc, "This module provides utils for textures.");
static PyModuleDef pygpu_texture_module_def = {
PyModuleDef_HEAD_INIT,
.m_name = "gpu.texture",
- .m_doc = pygpu_texure__m_doc,
+ .m_doc = pygpu_texture__m_doc,
.m_methods = pygpu_texture__m_methods,
};
diff --git a/source/blender/python/intern/bpy_app_handlers.c b/source/blender/python/intern/bpy_app_handlers.c
index 3155f3a63bd..ba3e6a3d74b 100644
--- a/source/blender/python/intern/bpy_app_handlers.c
+++ b/source/blender/python/intern/bpy_app_handlers.c
@@ -64,6 +64,8 @@ static PyStructSequence_Field app_cb_info_fields[] = {
{"load_factory_preferences_post", "on loading factory preferences (after)"},
{"load_factory_startup_post", "on loading factory startup (after)"},
{"xr_session_start_pre", "on starting an xr session (before)"},
+ {"annotation_pre", "on drawing an annotation (before)"},
+ {"annotation_post", "on drawing an annotation (after)"},
/* sets the permanent tag */
#define APP_CB_OTHER_FIELDS 1
@@ -276,7 +278,7 @@ void BPY_app_handlers_reset(const short do_all)
}
else {
/* remove */
- /* PySequence_DelItem(ls, i); */ /* more obvious but slower */
+ // PySequence_DelItem(ls, i); /* more obvious but slower */
PyList_SetSlice(ls, i, i + 1, NULL);
}
}
diff --git a/source/blender/python/intern/bpy_driver.c b/source/blender/python/intern/bpy_driver.c
index 61bb183068d..68018d22753 100644
--- a/source/blender/python/intern/bpy_driver.c
+++ b/source/blender/python/intern/bpy_driver.c
@@ -162,9 +162,11 @@ static struct {
/* borrowed reference to the 'self' in 'bpy_pydriver_Dict'
* keep for as long as the same self is used. */
PyObject *self;
+ BPy_StructRNA *depsgraph;
} g_pydriver_state_prev = {
.evaltime = FLT_MAX,
.self = NULL,
+ .depsgraph = NULL,
};
static void bpy_pydriver_namespace_update_frame(const float evaltime)
@@ -199,6 +201,38 @@ static void bpy_pydriver_namespace_clear_self(void)
}
}
+static PyObject *bpy_pydriver_depsgraph_as_pyobject(struct Depsgraph *depsgraph)
+{
+ struct PointerRNA depsgraph_ptr;
+ RNA_pointer_create(NULL, &RNA_Depsgraph, depsgraph, &depsgraph_ptr);
+ return pyrna_struct_CreatePyObject(&depsgraph_ptr);
+}
+
+/**
+ * Adds a variable 'depsgraph' to the name-space. This can then be used to obtain evaluated
+ * data-blocks, and the current view layer and scene. See T75553.
+ */
+static void bpy_pydriver_namespace_update_depsgraph(struct Depsgraph *depsgraph)
+{
+ /* This should never happen, but it's probably better to have None in Python
+ * than a NULL-wrapping Depsgraph Python struct. */
+ BLI_assert(depsgraph != NULL);
+ if (UNLIKELY(depsgraph == NULL)) {
+ PyDict_SetItem(bpy_pydriver_Dict, bpy_intern_str_depsgraph, Py_None);
+ g_pydriver_state_prev.depsgraph = NULL;
+ return;
+ }
+
+ if ((g_pydriver_state_prev.depsgraph == NULL) ||
+ ((depsgraph != g_pydriver_state_prev.depsgraph->ptr.data))) {
+ PyObject *item = bpy_pydriver_depsgraph_as_pyobject(depsgraph);
+ PyDict_SetItem(bpy_pydriver_Dict, bpy_intern_str_depsgraph, item);
+ Py_DECREF(item);
+
+ g_pydriver_state_prev.depsgraph = (BPy_StructRNA *)item;
+ }
+}
+
void BPY_driver_reset(void)
{
PyGILState_STATE gilstate;
@@ -226,6 +260,7 @@ void BPY_driver_reset(void)
/* freed when clearing driver dict */
g_pydriver_state_prev.self = NULL;
+ g_pydriver_state_prev.depsgraph = NULL;
if (use_gil) {
PyGILState_Release(gilstate);
@@ -369,40 +404,6 @@ static bool bpy_driver_secure_bytecode_validate(PyObject *expr_code, PyObject *d
}
#endif /* USE_BYTECODE_WHITELIST */
-
-static PyObject *bpy_pydriver_depsgraph_as_pyobject(struct Depsgraph *depsgraph)
-{
- /* This should never happen, but it's probably better to have None in Python
- * than a NULL-wrapping Depsgraph py struct. */
- BLI_assert(depsgraph != NULL);
- if (depsgraph == NULL) {
- Py_RETURN_NONE;
- }
-
- struct PointerRNA depsgraph_ptr;
- RNA_pointer_create(NULL, &RNA_Depsgraph, depsgraph, &depsgraph_ptr);
- return pyrna_struct_CreatePyObject(&depsgraph_ptr);
-}
-
-/**
- * Adds a variable 'depsgraph' to the driver variables. This can then be used to obtain evaluated
- * data-blocks, and the current view layer and scene. See T75553.
- */
-static void bpy_pydriver_namespace_add_depsgraph(PyObject *driver_vars,
- struct Depsgraph *depsgraph)
-{
- PyObject *py_depsgraph = bpy_pydriver_depsgraph_as_pyobject(depsgraph);
- const char *depsgraph_variable_name = "depsgraph";
-
- if (PyDict_SetItemString(driver_vars, depsgraph_variable_name, py_depsgraph) == -1) {
- fprintf(stderr,
- "\tBPY_driver_eval() - couldn't add variable '%s' to namespace\n",
- depsgraph_variable_name);
- PyErr_Print();
- PyErr_Clear();
- }
-}
-
float BPY_driver_exec(struct PathResolvedRNA *anim_rna,
ChannelDriver *driver,
ChannelDriver *driver_orig,
@@ -488,6 +489,8 @@ float BPY_driver_exec(struct PathResolvedRNA *anim_rna,
bpy_pydriver_namespace_clear_self();
}
+ bpy_pydriver_namespace_update_depsgraph(anim_eval_context->depsgraph);
+
if (driver_orig->expr_comp == NULL) {
driver_orig->flag |= DRIVER_FLAG_RECOMPILE;
}
@@ -612,8 +615,6 @@ float BPY_driver_exec(struct PathResolvedRNA *anim_rna,
}
#endif /* USE_BYTECODE_WHITELIST */
- bpy_pydriver_namespace_add_depsgraph(driver_vars, anim_eval_context->depsgraph);
-
#if 0 /* slow, with this can avoid all Py_CompileString above. */
/* execute expression to get a value */
retval = PyRun_String(expr, Py_eval_input, bpy_pydriver_Dict, driver_vars);
diff --git a/source/blender/python/intern/bpy_interface_run.c b/source/blender/python/intern/bpy_interface_run.c
index 01db0efecfd..500221c3c50 100644
--- a/source/blender/python/intern/bpy_interface_run.c
+++ b/source/blender/python/intern/bpy_interface_run.c
@@ -102,7 +102,8 @@ static bool python_script_exec(
fn_dummy_py = PyC_UnicodeFromByte(fn_dummy);
- buf = txt_to_buf(text, NULL);
+ int buf_len_dummy;
+ buf = txt_to_buf(text, &buf_len_dummy);
text->compiled = Py_CompileStringObject(buf, fn_dummy_py, Py_file_input, NULL, -1);
MEM_freeN(buf);
diff --git a/source/blender/python/intern/bpy_intern_string.c b/source/blender/python/intern/bpy_intern_string.c
index 1cf8f3b65a0..817494cb70a 100644
--- a/source/blender/python/intern/bpy_intern_string.c
+++ b/source/blender/python/intern/bpy_intern_string.c
@@ -14,7 +14,7 @@
#include "BLI_utildefines.h"
-static PyObject *bpy_intern_str_arr[16];
+static PyObject *bpy_intern_str_arr[17];
PyObject *bpy_intern_str___annotations__;
PyObject *bpy_intern_str___doc__;
@@ -31,6 +31,7 @@ PyObject *bpy_intern_str_frame;
PyObject *bpy_intern_str_properties;
PyObject *bpy_intern_str_register;
PyObject *bpy_intern_str_self;
+PyObject *bpy_intern_str_depsgraph;
PyObject *bpy_intern_str_unregister;
void bpy_intern_string_init(void)
@@ -58,6 +59,7 @@ void bpy_intern_string_init(void)
BPY_INTERN_STR(bpy_intern_str_properties, "properties");
BPY_INTERN_STR(bpy_intern_str_register, "register");
BPY_INTERN_STR(bpy_intern_str_self, "self");
+ BPY_INTERN_STR(bpy_intern_str_depsgraph, "depsgraph");
BPY_INTERN_STR(bpy_intern_str_unregister, "unregister");
#undef BPY_INTERN_STR
diff --git a/source/blender/python/intern/bpy_intern_string.h b/source/blender/python/intern/bpy_intern_string.h
index 1d74e8c31c5..cc8bf8a6f3b 100644
--- a/source/blender/python/intern/bpy_intern_string.h
+++ b/source/blender/python/intern/bpy_intern_string.h
@@ -28,6 +28,7 @@ extern PyObject *bpy_intern_str_frame;
extern PyObject *bpy_intern_str_properties;
extern PyObject *bpy_intern_str_register;
extern PyObject *bpy_intern_str_self;
+extern PyObject *bpy_intern_str_depsgraph;
extern PyObject *bpy_intern_str_unregister;
#ifdef __cplusplus
diff --git a/source/blender/python/intern/bpy_operator.c b/source/blender/python/intern/bpy_operator.c
index 61de15b07f5..159ac23bf95 100644
--- a/source/blender/python/intern/bpy_operator.c
+++ b/source/blender/python/intern/bpy_operator.c
@@ -313,7 +313,7 @@ static PyObject *pyop_call(PyObject *UNUSED(self), PyObject *args)
return NULL;
}
- WM_operator_name_call(C, opname, WM_OP_EXEC_DEFAULT, NULL);
+ WM_operator_name_call(C, opname, WM_OP_EXEC_DEFAULT, NULL, NULL);
}
#endif
}
diff --git a/source/blender/python/intern/bpy_rna.c b/source/blender/python/intern/bpy_rna.c
index 316cfe4d8b1..16e90a55844 100644
--- a/source/blender/python/intern/bpy_rna.c
+++ b/source/blender/python/intern/bpy_rna.c
@@ -5897,28 +5897,37 @@ static PyObject *pyrna_param_to_py(PointerRNA *ptr, PropertyRNA *prop, void *dat
break;
case PROP_STRING: {
const char *data_ch;
- PyObject *value_coerce = NULL;
const int subtype = RNA_property_subtype(prop);
+ size_t data_ch_len;
- if (flag & PROP_THICK_WRAP) {
- data_ch = (char *)data;
+ if (flag & PROP_DYNAMIC) {
+ ParameterDynAlloc *data_alloc = data;
+ data_ch = data_alloc->array;
+ data_ch_len = data_alloc->array_tot;
+ BLI_assert((data_ch == NULL) || strlen(data_ch) == data_ch_len);
}
else {
- data_ch = *(char **)data;
+ data_ch = (flag & PROP_THICK_WRAP) ? (char *)data : *(char **)data;
+ data_ch_len = data_ch ? strlen(data_ch) : 0;
}
+ if (UNLIKELY(data_ch == NULL)) {
+ BLI_assert((flag & PROP_NEVER_NULL) == 0);
+ ret = Py_None;
+ Py_INCREF(ret);
+ }
#ifdef USE_STRING_COERCE
- if (subtype == PROP_BYTESTRING) {
- ret = PyBytes_FromString(data_ch);
+ else if (subtype == PROP_BYTESTRING) {
+ ret = PyBytes_FromStringAndSize(data_ch, data_ch_len);
}
else if (ELEM(subtype, PROP_FILEPATH, PROP_DIRPATH, PROP_FILENAME)) {
- ret = PyC_UnicodeFromByte(data_ch);
+ ret = PyC_UnicodeFromByteAndSize(data_ch, data_ch_len);
}
else {
- ret = PyUnicode_FromString(data_ch);
+ ret = PyUnicode_FromStringAndSize(data_ch, data_ch_len);
}
#else
- if (subtype == PROP_BYTESTRING) {
+ else if (subtype == PROP_BYTESTRING) {
ret = PyBytes_FromString(buf);
}
else {
@@ -5926,10 +5935,6 @@ static PyObject *pyrna_param_to_py(PointerRNA *ptr, PropertyRNA *prop, void *dat
}
#endif
-#ifdef USE_STRING_COERCE
- Py_XDECREF(value_coerce);
-#endif
-
break;
}
case PROP_ENUM: {
@@ -6229,7 +6234,7 @@ static PyObject *pyrna_func_call(BPy_FunctionRNA *self, PyObject *args, PyObject
arg_name = PyUnicode_AsUTF8(key);
found = false;
- if (arg_name == NULL) { /* Unlikely the argname is not a string, but ignore if it is. */
+ if (arg_name == NULL) { /* Unlikely the `arg_name` is not a string, but ignore if it is. */
PyErr_Clear();
}
else {
diff --git a/source/blender/render/RE_pipeline.h b/source/blender/render/RE_pipeline.h
index 2d43aa7b27f..f532c705534 100644
--- a/source/blender/render/RE_pipeline.h
+++ b/source/blender/render/RE_pipeline.h
@@ -322,9 +322,13 @@ bool RE_WriteRenderViewsMovie(struct ReportList *reports,
bool preview);
/**
- * Only #RE_NewRender() needed, main Blender render calls.
- *
* General Blender frame render call.
+ *
+ * \note Only #RE_NewRender() needed, main Blender render calls.
+ *
+ * \param write_still: Saves frames to disk (typically disabled). Useful for batch-operations
+ * (rendering from Python for e.g.) when an additional save action for is inconvenient.
+ * This is the default behavior for #RE_RenderAnim.
*/
void RE_RenderFrame(struct Render *re,
struct Main *bmain,
@@ -334,7 +338,7 @@ void RE_RenderFrame(struct Render *re,
int frame,
bool write_still);
/**
- * Saves images to disk.
+ * A version of #RE_RenderFrame that saves images to disk.
*/
void RE_RenderAnim(struct Render *re,
struct Main *bmain,
diff --git a/source/blender/render/intern/pipeline.c b/source/blender/render/intern/pipeline.c
index 2a93fb2c46b..aa006713755 100644
--- a/source/blender/render/intern/pipeline.c
+++ b/source/blender/render/intern/pipeline.c
@@ -116,14 +116,20 @@
* - save file or append in movie
*/
-/* ********* globals ******** */
+/* -------------------------------------------------------------------- */
+/** \name Globals
+ * \{ */
/* here we store all renders */
static struct {
ListBase renderlist;
} RenderGlobal = {{NULL, NULL}};
-/* ********* callbacks ******** */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Callbacks
+ * \{ */
static void render_callback_exec_null(Render *re, Main *bmain, eCbEvent evt)
{
@@ -141,7 +147,11 @@ static void render_callback_exec_id(Render *re, Main *bmain, ID *id, eCbEvent ev
BKE_callback_exec_id(bmain, id, evt);
}
-/* ********* alloc and free ******** */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Allocation & Free
+ * \{ */
static int do_write_image_or_movie(Render *re,
Main *bmain,
@@ -308,7 +318,11 @@ static bool render_scene_has_layers_to_render(Scene *scene, ViewLayer *single_la
return false;
}
-/* *************************************************** */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Public Render API
+ * \{ */
Render *RE_GetRender(const char *name)
{
@@ -686,7 +700,11 @@ void RE_FreePersistentData(const Scene *scene)
}
}
-/* ********* initialize state ******** */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Initialize State
+ * \{ */
static void re_init_resolution(Render *re, Render *source, int winx, int winy, rcti *disprect)
{
@@ -905,7 +923,11 @@ void RE_test_break_cb(Render *re, void *handle, int (*f)(void *handle))
re->tbh = handle;
}
-/* ********* GL Context ******** */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name OpenGL Context
+ * \{ */
void RE_gl_context_create(Render *re)
{
@@ -944,6 +966,16 @@ void *RE_gpu_context_get(Render *re)
return re->gpu_context;
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Render & Composite Scenes (Implementation & Public API)
+ *
+ * Main high-level functions defined here are:
+ * - #RE_RenderFrame
+ * - #RE_RenderAnim
+ * \{ */
+
/* ************ This part uses API, for rendering Blender scenes ********** */
/* make sure disprect is not affected by the render border */
@@ -1940,6 +1972,12 @@ void RE_RenderFreestyleExternal(Render *re)
}
#endif
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Read/Write Render Result (Images & Movies)
+ * \{ */
+
bool RE_WriteRenderViewsImage(
ReportList *reports, RenderResult *rr, Scene *scene, const bool stamp, char *name)
{
@@ -2600,11 +2638,6 @@ bool RE_ReadRenderResult(Scene *scene, Scene *scenode)
return success;
}
-void RE_init_threadcount(Render *re)
-{
- re->r.threads = BKE_render_num_threads(&re->r);
-}
-
void RE_layer_load_from_file(
RenderLayer *layer, ReportList *reports, const char *filename, int x, int y)
{
@@ -2785,6 +2818,12 @@ RenderPass *RE_create_gp_pass(RenderResult *rr, const char *layername, const cha
return render_layer_add_pass(rr, rl, 4, RE_PASSNAME_COMBINED, viewname, "RGBA", true);
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Miscellaneous Public Render API
+ * \{ */
+
bool RE_allow_render_generic_object(Object *ob)
{
/* override not showing object when duplis are used with particles */
@@ -2796,3 +2835,10 @@ bool RE_allow_render_generic_object(Object *ob)
}
return true;
}
+
+void RE_init_threadcount(Render *re)
+{
+ re->r.threads = BKE_render_num_threads(&re->r);
+}
+
+/** \} */
diff --git a/source/blender/render/intern/texture_procedural.c b/source/blender/render/intern/texture_procedural.c
index 4b1439529c1..73dbcfdfeab 100644
--- a/source/blender/render/intern/texture_procedural.c
+++ b/source/blender/render/intern/texture_procedural.c
@@ -102,10 +102,10 @@ static int blend(const Tex *tex, const float texvec[3], TexResult *texres)
y = texvec[1];
}
- if (tex->stype == TEX_LIN) { /* lin */
+ if (tex->stype == TEX_LIN) { /* Linear. */
texres->tin = (1.0f + x) / 2.0f;
}
- else if (tex->stype == TEX_QUAD) { /* quad */
+ else if (tex->stype == TEX_QUAD) { /* Quadratic. */
texres->tin = (1.0f + x) / 2.0f;
if (texres->tin < 0.0f) {
texres->tin = 0.0f;
@@ -114,7 +114,7 @@ static int blend(const Tex *tex, const float texvec[3], TexResult *texres)
texres->tin *= texres->tin;
}
}
- else if (tex->stype == TEX_EASE) { /* ease */
+ else if (tex->stype == TEX_EASE) { /* Ease. */
texres->tin = (1.0f + x) / 2.0f;
if (texres->tin <= 0.0f) {
texres->tin = 0.0f;
@@ -127,10 +127,10 @@ static int blend(const Tex *tex, const float texvec[3], TexResult *texres)
texres->tin = (3.0f * t - 2.0f * t * texres->tin);
}
}
- else if (tex->stype == TEX_DIAG) { /* diag */
+ else if (tex->stype == TEX_DIAG) { /* Diagonal. */
texres->tin = (2.0f + x + y) / 4.0f;
}
- else if (tex->stype == TEX_RAD) { /* radial */
+ else if (tex->stype == TEX_RAD) { /* Radial. */
texres->tin = (atan2f(y, x) / (float)(2 * M_PI) + 0.5f);
}
else { /* sphere TEX_SPHERE */
@@ -139,7 +139,7 @@ static int blend(const Tex *tex, const float texvec[3], TexResult *texres)
texres->tin = 0.0f;
}
if (tex->stype == TEX_HALO) {
- texres->tin *= texres->tin; /* halo */
+ texres->tin *= texres->tin; /* Halo. */
}
}
diff --git a/source/blender/sequencer/intern/effects.c b/source/blender/sequencer/intern/effects.c
index aa433eeed09..01211aeeec6 100644
--- a/source/blender/sequencer/intern/effects.c
+++ b/source/blender/sequencer/intern/effects.c
@@ -58,6 +58,10 @@
static struct SeqEffectHandle get_sequence_effect_impl(int seq_type);
+/* -------------------------------------------------------------------- */
+/** \name Internal Utilities
+ * \{ */
+
static void slice_get_byte_buffers(const SeqRenderData *context,
const ImBuf *ibuf1,
const ImBuf *ibuf2,
@@ -108,7 +112,11 @@ static void slice_get_float_buffers(const SeqRenderData *context,
}
}
-/*********************** Glow effect *************************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Glow Effect
+ * \{ */
enum {
GlowR = 0,
@@ -178,7 +186,11 @@ static ImBuf *prepare_effect_imbufs(const SeqRenderData *context,
return out;
}
-/*********************** Alpha Over *************************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Alpha Over Effect
+ * \{ */
static void init_alpha_over_or_under(Sequence *seq)
{
@@ -288,7 +300,11 @@ static void do_alphaover_effect(const SeqRenderData *context,
}
}
-/*********************** Alpha Under *************************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Alpha Under Effect
+ * \{ */
static void do_alphaunder_effect_byte(
float fac, int x, int y, unsigned char *rect1, unsigned char *rect2, unsigned char *out)
@@ -405,7 +421,11 @@ static void do_alphaunder_effect(const SeqRenderData *context,
}
}
-/*********************** Cross *************************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Cross Effect
+ * \{ */
static void do_cross_effect_byte(
float fac, int x, int y, unsigned char *rect1, unsigned char *rect2, unsigned char *out)
@@ -482,7 +502,11 @@ static void do_cross_effect(const SeqRenderData *context,
}
}
-/*********************** Gamma Cross *************************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Gamma Cross
+ * \{ */
/* copied code from initrender.c */
static unsigned short gamtab[65536];
@@ -726,7 +750,11 @@ static void do_gammacross_effect(const SeqRenderData *context,
}
}
-/*********************** Add *************************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Color Add Effect
+ * \{ */
static void do_add_effect_byte(
float fac, int x, int y, unsigned char *rect1, unsigned char *rect2, unsigned char *out)
@@ -802,7 +830,11 @@ static void do_add_effect(const SeqRenderData *context,
}
}
-/*********************** Sub *************************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Color Subtract Effect
+ * \{ */
static void do_sub_effect_byte(
float fac, int x, int y, unsigned char *rect1, unsigned char *rect2, unsigned char *out)
@@ -880,7 +912,11 @@ static void do_sub_effect(const SeqRenderData *context,
}
}
-/*********************** Drop *************************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Drop Effect
+ * \{ */
/* Must be > 0 or add precopy, etc to the function */
#define XOFF 8
@@ -954,7 +990,11 @@ static void do_drop_effect_float(
memcpy(out, rt1, sizeof(*out) * yoff * 4 * x);
}
-/*********************** Mul *************************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Multiply Effect
+ * \{ */
static void do_mul_effect_byte(
float fac, int x, int y, unsigned char *rect1, unsigned char *rect2, unsigned char *out)
@@ -1035,7 +1075,12 @@ static void do_mul_effect(const SeqRenderData *context,
}
}
-/*********************** Blend Mode ***************************************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Blend Mode Effect
+ * \{ */
+
typedef void (*IMB_blend_func_byte)(unsigned char *dst,
const unsigned char *src1,
const unsigned char *src2);
@@ -1268,7 +1313,13 @@ static void do_blend_mode_effect(const SeqRenderData *context,
fac, context->rectx, total_lines, rect1, rect2, seq->blend_mode, rect_out);
}
}
-/*********************** Color Mix Effect *************************/
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Color Mix Effect
+ * \{ */
+
static void init_colormix_effect(Sequence *seq)
{
ColorMixVars *data;
@@ -1314,7 +1365,11 @@ static void do_colormix_effect(const SeqRenderData *context,
}
}
-/*********************** Wipe *************************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Wipe Effect
+ * \{ */
typedef struct WipeZone {
float angle;
@@ -1334,7 +1389,9 @@ static void precalc_wipe_zone(WipeZone *wipezone, WipeVars *wipe, int xo, int yo
wipezone->pythangle = 1.0f / sqrtf(wipezone->angle * wipezone->angle + 1.0f);
}
-/* This function calculates the blur band for the wipe effects */
+/**
+ * This function calculates the blur band for the wipe effects.
+ */
static float in_band(float width, float dist, int side, int dir)
{
float alpha;
@@ -1757,7 +1814,11 @@ static ImBuf *do_wipe_effect(const SeqRenderData *context,
return out;
}
-/*********************** Transform *************************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Transform Effect
+ * \{ */
static void init_transform_effect(Sequence *seq)
{
@@ -1909,7 +1970,11 @@ static void do_transform_effect(const SeqRenderData *context,
transform->interpolation);
}
-/*********************** Glow *************************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Glow Effect
+ * \{ */
static void RVBlurBitmap2_float(float *map, int width, int height, float blur, int quality)
{
@@ -2229,7 +2294,11 @@ static ImBuf *do_glow_effect(const SeqRenderData *context,
return out;
}
-/*********************** Solid color *************************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Solid Color Effect
+ * \{ */
static void init_solid_color(Sequence *seq)
{
@@ -2324,9 +2393,13 @@ static ImBuf *do_solid_color(const SeqRenderData *context,
return out;
}
-/*********************** Mulitcam *************************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Multi-Camera Effect
+ * \{ */
-/* no effect inputs for multicam, we use give_ibuf_seq */
+/** No effect inputs for multi-camera, we use #give_ibuf_seq. */
static int num_inputs_multicam(void)
{
return 0;
@@ -2367,9 +2440,13 @@ static ImBuf *do_multicam(const SeqRenderData *context,
return out;
}
-/*********************** Adjustment *************************/
+/** \} */
-/* no effect inputs for adjustment, we use give_ibuf_seq */
+/* -------------------------------------------------------------------- */
+/** \name Adjustment Effect
+ * \{ */
+
+/** No effect inputs for adjustment, we use #give_ibuf_seq. */
static int num_inputs_adjustment(void)
{
return 0;
@@ -2438,7 +2515,11 @@ static ImBuf *do_adjustment(const SeqRenderData *context,
return out;
}
-/*********************** Speed *************************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Speed Effect
+ * \{ */
static void init_speed_effect(Sequence *seq)
{
@@ -2639,7 +2720,11 @@ static ImBuf *do_speed_effect(const SeqRenderData *context,
return IMB_dupImBuf(ibuf1);
}
-/*********************** overdrop *************************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Over-Drop Effect
+ * \{ */
static void do_overdrop_effect(const SeqRenderData *context,
Sequence *UNUSED(seq),
@@ -2675,7 +2760,11 @@ static void do_overdrop_effect(const SeqRenderData *context,
}
}
-/*********************** Gaussian Blur *************************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Gaussian Blur
+ * \{ */
/* NOTE: This gaussian blur implementation accumulates values in the square
* kernel rather that doing X direction and then Y direction because of the
@@ -3099,7 +3188,11 @@ static ImBuf *do_gaussian_blur_effect(const SeqRenderData *context,
return out;
}
-/*********************** text *************************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Text Effect
+ * \{ */
static void init_text_effect(Sequence *seq)
{
@@ -3341,7 +3434,11 @@ static ImBuf *do_text_effect(const SeqRenderData *context,
return out;
}
-/*********************** sequence effect factory *************************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Sequence Effect Factory
+ * \{ */
static void init_noop(Sequence *UNUSED(seq))
{
@@ -3592,6 +3689,12 @@ static struct SeqEffectHandle get_sequence_effect_impl(int seq_type)
return rval;
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Public Sequencer Effect API
+ * \{ */
+
struct SeqEffectHandle SEQ_effect_handle_get(Sequence *seq)
{
struct SeqEffectHandle rval = {false, false, NULL};
@@ -3639,3 +3742,5 @@ int SEQ_effect_get_num_inputs(int seq_type)
}
return 0;
}
+
+/** \} */
diff --git a/source/blender/sequencer/intern/effects.h b/source/blender/sequencer/intern/effects.h
index 573f8df4352..c15701a2047 100644
--- a/source/blender/sequencer/intern/effects.h
+++ b/source/blender/sequencer/intern/effects.h
@@ -15,13 +15,6 @@ struct Scene;
struct SeqRenderData;
struct Sequence;
-/* **********************************************************************
- * sequencer.c
- *
- * Sequencer editing functions
- * **********************************************************************
- */
-
struct SeqEffectHandle seq_effect_get_sequence_blend(struct Sequence *seq);
/**
* Build frame map when speed in mode #SEQ_SPEED_MULTIPLY is animated.
diff --git a/source/blender/shader_fx/intern/FX_ui_common.c b/source/blender/shader_fx/intern/FX_ui_common.c
index 3770b796c4d..4c9eaa11ab6 100644
--- a/source/blender/shader_fx/intern/FX_ui_common.c
+++ b/source/blender/shader_fx/intern/FX_ui_common.c
@@ -50,7 +50,7 @@ static void shaderfx_reorder(bContext *C, Panel *panel, int new_index)
WM_operator_properties_create_ptr(&props_ptr, ot);
RNA_string_set(&props_ptr, "shaderfx", fx->name);
RNA_int_set(&props_ptr, "index", new_index);
- WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &props_ptr);
+ WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &props_ptr, NULL);
WM_operator_properties_free(&props_ptr);
}
diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h
index aa380928082..7959c3d6f0b 100644
--- a/source/blender/windowmanager/WM_api.h
+++ b/source/blender/windowmanager/WM_api.h
@@ -242,11 +242,12 @@ void WM_window_set_dpi(const wmWindow *win);
bool WM_stereo3d_enabled(struct wmWindow *win, bool only_fullscreen_test);
-/* files */
+/* wm_files.c */
+
void WM_file_autoexec_init(const char *filepath);
bool WM_file_read(struct bContext *C, const char *filepath, struct ReportList *reports);
-void WM_autosave_init(struct wmWindowManager *wm);
-bool WM_recover_last_session(struct bContext *C, struct ReportList *reports);
+void WM_file_autosave_init(struct wmWindowManager *wm);
+bool WM_file_recover_last_session(struct bContext *C, struct ReportList *reports);
void WM_file_tag_modified(void);
/**
@@ -615,7 +616,8 @@ bool WM_operator_poll_context(struct bContext *C, struct wmOperatorType *ot, sho
/**
* For running operators with frozen context (modal handlers, menus).
*
- * \param store: Store settings for re-use.
+ * \param store: Store properties for re-use when an operator has finished
+ * (unless #PROP_SKIP_SAVE is set).
*
* \warning do not use this within an operator to call itself! T29537.
*/
@@ -644,19 +646,29 @@ bool WM_operator_is_repeat(const struct bContext *C, const struct wmOperator *op
bool WM_operator_name_poll(struct bContext *C, const char *opstring);
/**
* Invokes operator in context.
+ *
+ * \param event: Optionally pass in an event to use when context uses one of the
+ * `WM_OP_INVOKE_*` values. When left unset the #wmWindow.eventstate will be used,
+ * this can cause problems for operators that read the events type - for example,
+ * storing the key that was pressed so as to be able to detect it's release.
+ * In these cases it's necessary to forward the current event being handled.
*/
int WM_operator_name_call_ptr(struct bContext *C,
struct wmOperatorType *ot,
wmOperatorCallContext context,
- struct PointerRNA *properties);
+ struct PointerRNA *properties,
+ const wmEvent *event);
+/** See #WM_operator_name_call_ptr */
int WM_operator_name_call(struct bContext *C,
const char *opstring,
wmOperatorCallContext context,
- struct PointerRNA *properties);
+ struct PointerRNA *properties,
+ const wmEvent *event);
int WM_operator_name_call_with_properties(struct bContext *C,
const char *opstring,
wmOperatorCallContext context,
- struct IDProperty *properties);
+ struct IDProperty *properties,
+ const wmEvent *event);
/**
* Similar to #WM_operator_name_call called with #WM_OP_EXEC_DEFAULT context.
*
@@ -675,6 +687,7 @@ void WM_operator_name_call_ptr_with_depends_on_cursor(struct bContext *C,
wmOperatorType *ot,
wmOperatorCallContext opcontext,
PointerRNA *properties,
+ const wmEvent *event,
const char *drawstr);
/**
@@ -1453,6 +1466,9 @@ bool WM_cursor_test_motion_and_update(const int mval[2]) ATTR_NONNULL(1) ATTR_WA
int WM_event_drag_threshold(const struct wmEvent *event);
bool WM_event_drag_test(const struct wmEvent *event, const int prev_xy[2]);
bool WM_event_drag_test_with_delta(const struct wmEvent *event, const int delta[2]);
+void WM_event_drag_start_mval(const wmEvent *event, const ARegion *region, int r_mval[2]);
+void WM_event_drag_start_mval_fl(const wmEvent *event, const ARegion *region, float r_mval[2]);
+void WM_event_drag_start_xy(const wmEvent *event, int r_xy[2]);
/**
* Event map that takes preferences into account.
diff --git a/source/blender/windowmanager/WM_types.h b/source/blender/windowmanager/WM_types.h
index d7fe34a3b4c..9edbafafdd3 100644
--- a/source/blender/windowmanager/WM_types.h
+++ b/source/blender/windowmanager/WM_types.h
@@ -238,6 +238,7 @@ enum {
KM_SHIFT = (1 << 0),
KM_CTRL = (1 << 1),
KM_ALT = (1 << 2),
+ /** Use for Windows-Key on MS-Windows, Command-key on macOS and Super on Linux. */
KM_OSKEY = (1 << 3),
/* Used for key-map item creation function arguments. */
@@ -267,6 +268,10 @@ enum {
KM_RELEASE = 2,
KM_CLICK = 3,
KM_DBL_CLICK = 4,
+ /**
+ * \note The cursor location at the point dragging starts is set to #wmEvent.prev_press_xy
+ * some operators such as box selection should use this location instead of #wmEvent.xy.
+ */
KM_CLICK_DRAG = 5,
};
@@ -605,6 +610,11 @@ typedef enum eWM_EventFlag {
* See #KMI_REPEAT_IGNORE for details on how key-map handling uses this.
*/
WM_EVENT_IS_REPEAT = (1 << 1),
+ /**
+ * Mouse-move events may have this flag set to force creating a click-drag event
+ * even when the threshold has not been met.
+ */
+ WM_EVENT_FORCE_DRAG_THRESHOLD = (1 << 2),
} eWM_EventFlag;
typedef struct wmTabletData {
@@ -625,23 +635,39 @@ typedef struct wmTabletData {
* event comes from event manager and from keymap.
*
*
- * Previous State
- * ==============
- *
- * Events hold information about the previous event,
- * this is used for detecting click and double-click events (the timer is needed for double-click).
- * See #wm_event_add_ghostevent for implementation details.
+ * Previous State (`prev_*`)
+ * =========================
*
- * Notes:
+ * Events hold information about the previous event.
*
- * - The previous values are only set for mouse button and keyboard events.
- * See: #ISMOUSE_BUTTON & #ISKEYBOARD macros.
+ * - Previous values are only set for events types that generate #KM_PRESS.
+ * See: #ISKEYBOARD_OR_BUTTON.
*
* - Previous x/y are exceptions: #wmEvent.prev
* these are set on mouse motion, see #MOUSEMOVE & track-pad events.
*
* - Modal key-map handling sets `prev_val` & `prev_type` to `val` & `type`,
* this allows modal keys-maps to check the original values (needed in some cases).
+ *
+ *
+ * Press State (`prev_press_*`)
+ * ============================
+ *
+ * Events hold information about the state when the last #KM_PRESS event was added.
+ * This is used for generating #KM_CLICK, #KM_DBL_CLICK & #KM_CLICK_DRAG events.
+ * See #wm_handlers_do for the implementation.
+ *
+ * - Previous values are only set when a #KM_PRESS event is detected.
+ * See: #ISKEYBOARD_OR_BUTTON.
+ *
+ * - The reason to differentiate between "press" and the previous event state is
+ * the previous event may be set by key-release events. In the case of a single key click
+ * this isn't a problem however releasing other keys such as modifiers prevents click/click-drag
+ * events from being detected, see: T89989.
+ *
+ * - Mouse-wheel events are excluded even though they generate #KM_PRESS
+ * as clicking and dragging don't make sense for mouse wheel events.
+ *
*/
typedef struct wmEvent {
struct wmEvent *next, *prev;
@@ -663,38 +689,16 @@ typedef struct wmEvent {
/** From ghost, fallback if utf8 isn't set. */
char ascii;
- /** The previous value of `type`. */
- short prev_type;
- /** The previous value of `val`. */
- short prev_val;
- /**
- * The previous value of #wmEvent.xy,
- * Unlike other previous state variables, this is set on any mouse motion.
- * Use `prev_click` for the value at time of pressing.
- */
- int prev_xy[2];
-
- /** The `type` at the point of the click action. */
- short prev_click_type;
- /** The time when the key is pressed, see #PIL_check_seconds_timer. */
- double prev_click_time;
- /** The location when the key is pressed (used to enforce drag thresholds). */
- int prev_click_xy[2];
- /** The `modifier` at the point of the click action. */
- uint8_t prev_click_modifier;
- /** The `keymodifier` at the point of the click action. */
- short prev_click_keymodifier;
-
- /**
- * Modifier states.
- * #KM_SHIFT, #KM_CTRL, #KM_ALT & #KM_OSKEY is apple or windows-key.
- */
+ /** Modifier states: #KM_SHIFT, #KM_CTRL, #KM_ALT & #KM_OSKEY. */
uint8_t modifier;
/** The direction (for #KM_CLICK_DRAG events only). */
int8_t direction;
- /** Raw-key modifier (allow using any key as a modifier). */
+ /**
+ * Raw-key modifier (allow using any key as a modifier).
+ * Compatible with values in `type`.
+ */
short keymodifier;
/** Tablet info, available for mouse move and button events. */
@@ -703,11 +707,44 @@ typedef struct wmEvent {
eWM_EventFlag flag;
/* Custom data. */
- /** Custom data type, stylus, 6dof, see wm_event_types.h */
+
+ /** Custom data type, stylus, 6-DOF, see `wm_event_types.h`. */
short custom;
short customdata_free;
/** Ascii, unicode, mouse-coords, angles, vectors, NDOF data, drag-drop info. */
void *customdata;
+
+ /* Previous State. */
+
+ /** The previous value of `type`. */
+ short prev_type;
+ /** The previous value of `val`. */
+ short prev_val;
+ /**
+ * The previous value of #wmEvent.xy,
+ * Unlike other previous state variables, this is set on any mouse motion.
+ * Use `prev_press_*` for the value at time of pressing.
+ */
+ int prev_xy[2];
+
+ /* Previous Press State (when `val == KM_PRESS`). */
+
+ /** The `type` at the point of the press action. */
+ short prev_press_type;
+ /**
+ * The location when the key is pressed.
+ * used to enforce drag threshold & calculate the `direction`.
+ */
+ int prev_press_xy[2];
+ /** The `modifier` at the point of the press action. */
+ uint8_t prev_press_modifier;
+ /** The `keymodifier` at the point of the press action. */
+ short prev_press_keymodifier;
+ /**
+ * The time when the key is pressed, see #PIL_check_seconds_timer.
+ * Used to detect double-click events.
+ */
+ double prev_press_time;
} wmEvent;
/**
diff --git a/source/blender/windowmanager/gizmo/WM_gizmo_api.h b/source/blender/windowmanager/gizmo/WM_gizmo_api.h
index 6b497c7462a..fe73daeed29 100644
--- a/source/blender/windowmanager/gizmo/WM_gizmo_api.h
+++ b/source/blender/windowmanager/gizmo/WM_gizmo_api.h
@@ -92,7 +92,10 @@ struct PointerRNA *WM_gizmo_operator_set(struct wmGizmo *gz,
int part_index,
struct wmOperatorType *ot,
struct IDProperty *properties);
-int WM_gizmo_operator_invoke(struct bContext *C, struct wmGizmo *gz, struct wmGizmoOpElem *gzop);
+int WM_gizmo_operator_invoke(struct bContext *C,
+ struct wmGizmo *gz,
+ struct wmGizmoOpElem *gzop,
+ const struct wmEvent *event);
/* Callbacks. */
diff --git a/source/blender/windowmanager/gizmo/intern/wm_gizmo.c b/source/blender/windowmanager/gizmo/intern/wm_gizmo.c
index 05564f3bd0a..db4926f3430 100644
--- a/source/blender/windowmanager/gizmo/intern/wm_gizmo.c
+++ b/source/blender/windowmanager/gizmo/intern/wm_gizmo.c
@@ -225,7 +225,7 @@ PointerRNA *WM_gizmo_operator_set(wmGizmo *gz,
return &gzop->ptr;
}
-int WM_gizmo_operator_invoke(bContext *C, wmGizmo *gz, wmGizmoOpElem *gzop)
+int WM_gizmo_operator_invoke(bContext *C, wmGizmo *gz, wmGizmoOpElem *gzop, const wmEvent *event)
{
if (gz->flag & WM_GIZMO_OPERATOR_TOOL_INIT) {
/* Merge toolsettings into the gizmo properties. */
@@ -239,7 +239,7 @@ int WM_gizmo_operator_invoke(bContext *C, wmGizmo *gz, wmGizmoOpElem *gzop)
IDP_MergeGroup(gzop->ptr.data, tref_ptr.data, false);
}
}
- return WM_operator_name_call_ptr(C, gzop->type, WM_OP_INVOKE_DEFAULT, &gzop->ptr);
+ return WM_operator_name_call_ptr(C, gzop->type, WM_OP_INVOKE_DEFAULT, &gzop->ptr, event);
}
static void wm_gizmo_set_matrix_rotation_from_z_axis__internal(float matrix[4][4],
@@ -425,7 +425,7 @@ void WM_gizmo_modal_set_from_setup(struct wmGizmoMap *gzmap,
}
else {
/* WEAK: but it works. */
- WM_operator_name_call(C, "GIZMOGROUP_OT_gizmo_tweak", WM_OP_INVOKE_DEFAULT, NULL);
+ WM_operator_name_call(C, "GIZMOGROUP_OT_gizmo_tweak", WM_OP_INVOKE_DEFAULT, NULL, event);
}
}
diff --git a/source/blender/windowmanager/gizmo/intern/wm_gizmo_group.c b/source/blender/windowmanager/gizmo/intern/wm_gizmo_group.c
index b3ef9b27667..00615d9d662 100644
--- a/source/blender/windowmanager/gizmo/intern/wm_gizmo_group.c
+++ b/source/blender/windowmanager/gizmo/intern/wm_gizmo_group.c
@@ -441,7 +441,7 @@ static bool gizmo_tweak_start_and_finish(
gz->parent_gzgroup->type->invoke_prepare(C, gz->parent_gzgroup, gz, event);
}
/* Allow for 'button' gizmos, single click to run an action. */
- WM_gizmo_operator_invoke(C, gz, gzop);
+ WM_gizmo_operator_invoke(C, gz, gzop, event);
}
return true;
}
@@ -1137,7 +1137,7 @@ void WM_gizmo_group_refresh(const bContext *C, wmGizmoGroup *gzgroup)
BLI_assert(region->gizmo_map == gzmap);
/* Check if the tweak event originated from this region. */
if ((win->eventstate != NULL) && (win->event_queue_check_drag) &&
- BLI_rcti_isect_pt_v(&region->winrct, win->eventstate->prev_click_xy)) {
+ BLI_rcti_isect_pt_v(&region->winrct, win->eventstate->prev_press_xy)) {
/* We need to run refresh again. */
gzgroup->init_flag &= ~WM_GIZMOGROUP_INIT_REFRESH;
WM_gizmomap_tag_refresh_drawstep(gzmap, WM_gizmomap_drawstep_from_gizmo_group(gzgroup));
diff --git a/source/blender/windowmanager/gizmo/intern/wm_gizmo_map.c b/source/blender/windowmanager/gizmo/intern/wm_gizmo_map.c
index f1ac19f4651..d9f4050c8f1 100644
--- a/source/blender/windowmanager/gizmo/intern/wm_gizmo_map.c
+++ b/source/blender/windowmanager/gizmo/intern/wm_gizmo_map.c
@@ -815,6 +815,14 @@ wmGizmo *wm_gizmomap_highlight_find(wmGizmoMap *gzmap,
BLI_buffer_declare_static(wmGizmo *, visible_3d_gizmos, BLI_BUFFER_NOP, 128);
bool do_step[WM_GIZMOMAP_DRAWSTEP_MAX];
+ int mval[2];
+ if (event->val == KM_CLICK_DRAG) {
+ WM_event_drag_start_mval(event, CTX_wm_region(C), mval);
+ }
+ else {
+ copy_v2_v2_int(mval, event->mval);
+ }
+
for (int i = 0; i < ARRAY_SIZE(do_step); i++) {
do_step[i] = WM_gizmo_context_check_drawstep(C, i);
}
@@ -841,7 +849,7 @@ wmGizmo *wm_gizmomap_highlight_find(wmGizmoMap *gzmap,
}
else if (step == WM_GIZMOMAP_DRAWSTEP_2D) {
if ((gz = wm_gizmogroup_find_intersected_gizmo(
- wm, gzgroup, C, event->modifier, event->mval, r_part))) {
+ wm, gzgroup, C, event->modifier, mval, r_part))) {
break;
}
}
@@ -853,7 +861,7 @@ wmGizmo *wm_gizmomap_highlight_find(wmGizmoMap *gzmap,
/* 2D gizmos get priority. */
if (gz == NULL) {
gz = gizmo_find_intersected_3d(
- C, event->mval, visible_3d_gizmos.data, visible_3d_gizmos.count, r_part);
+ C, mval, visible_3d_gizmos.data, visible_3d_gizmos.count, r_part);
}
}
BLI_buffer_free(&visible_3d_gizmos);
@@ -1149,7 +1157,7 @@ void wm_gizmomap_modal_set(
struct wmGizmoOpElem *gzop = WM_gizmo_operator_get(gz, gz->highlight_part);
if (gzop && gzop->type) {
- const int retval = WM_gizmo_operator_invoke(C, gz, gzop);
+ const int retval = WM_gizmo_operator_invoke(C, gz, gzop, event);
if ((retval & OPERATOR_RUNNING_MODAL) == 0) {
wm_gizmomap_modal_set(gzmap, C, gz, event, false);
}
diff --git a/source/blender/windowmanager/intern/wm.c b/source/blender/windowmanager/intern/wm.c
index a55f5af03d1..40d9b0b9a35 100644
--- a/source/blender/windowmanager/intern/wm.c
+++ b/source/blender/windowmanager/intern/wm.c
@@ -155,6 +155,7 @@ static void window_manager_blend_read_data(BlendDataReader *reader, ID *id)
win->ghostwin = NULL;
win->gpuctx = NULL;
win->eventstate = NULL;
+ win->event_last_handled = NULL;
win->cursor_keymap_status = NULL;
#if defined(WIN32) || defined(__APPLE__)
win->ime_data = NULL;
@@ -484,7 +485,7 @@ void WM_check(bContext *C)
/* Case: file-read. */
if ((wm->initialized & WM_WINDOW_IS_INIT) == 0) {
WM_keyconfig_init(C);
- WM_autosave_init(wm);
+ WM_file_autosave_init(wm);
}
/* Case: no open windows at all, for old file reads. */
diff --git a/source/blender/windowmanager/intern/wm_event_query.c b/source/blender/windowmanager/intern/wm_event_query.c
index ee13e1832ed..9a7d31f8bb8 100644
--- a/source/blender/windowmanager/intern/wm_event_query.c
+++ b/source/blender/windowmanager/intern/wm_event_query.c
@@ -227,8 +227,8 @@ bool WM_event_is_mouse_drag_or_press(const wmEvent *event)
int WM_event_drag_direction(const wmEvent *event)
{
const int delta[2] = {
- event->xy[0] - event->prev_click_xy[0],
- event->xy[1] - event->prev_click_xy[1],
+ event->xy[0] - event->prev_press_xy[0],
+ event->xy[1] - event->prev_press_xy[1],
};
int theta = round_fl_to_int(4.0f * atan2f((float)delta[1], (float)delta[0]) / (float)M_PI);
@@ -306,8 +306,8 @@ bool WM_cursor_test_motion_and_update(const int mval[2])
int WM_event_drag_threshold(const struct wmEvent *event)
{
int drag_threshold;
- if (ISMOUSE(event->prev_click_type)) {
- BLI_assert(event->prev_click_type != MOUSEMOVE);
+ if (ISMOUSE(event->prev_press_type)) {
+ BLI_assert(event->prev_press_type != MOUSEMOVE);
/* Using the previous type is important is we want to check the last pressed/released button,
* The `event->type` would include #MOUSEMOVE which is always the case when dragging
* and does not help us know which threshold to use. */
@@ -338,6 +338,25 @@ bool WM_event_drag_test(const wmEvent *event, const int prev_xy[2])
return WM_event_drag_test_with_delta(event, drag_delta);
}
+void WM_event_drag_start_mval(const wmEvent *event, const ARegion *region, int r_mval[2])
+{
+ const int *xy = (event->val == KM_CLICK_DRAG) ? event->prev_press_xy : event->xy;
+ r_mval[0] = xy[0] - region->winrct.xmin;
+ r_mval[1] = xy[1] - region->winrct.ymin;
+}
+
+void WM_event_drag_start_mval_fl(const wmEvent *event, const ARegion *region, float r_mval[2])
+{
+ const int *xy = (event->val == KM_CLICK_DRAG) ? event->prev_press_xy : event->xy;
+ r_mval[0] = xy[0] - region->winrct.xmin;
+ r_mval[1] = xy[1] - region->winrct.ymin;
+}
+
+void WM_event_drag_start_xy(const wmEvent *event, int r_xy[2])
+{
+ copy_v2_v2_int(r_xy, (event->val == KM_CLICK_DRAG) ? event->prev_press_xy : event->xy);
+}
+
/** \} */
/* -------------------------------------------------------------------- */
diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c
index 0e262f8c388..62aeb8a2928 100644
--- a/source/blender/windowmanager/intern/wm_event_system.c
+++ b/source/blender/windowmanager/intern/wm_event_system.c
@@ -97,9 +97,10 @@ static int wm_operator_call_internal(bContext *C,
ReportList *reports,
const wmOperatorCallContext context,
const bool poll_only,
- wmEvent *event);
+ const wmEvent *event);
static bool wm_operator_check_locked_interface(bContext *C, wmOperatorType *ot);
+static wmEvent *wm_event_add_mousemove_to_head(wmWindow *win);
/* -------------------------------------------------------------------- */
/** \name Event Management
@@ -145,7 +146,7 @@ wmEvent *WM_event_add_simulate(wmWindow *win, const wmEvent *event_to_add)
copy_v2_v2_int(win->eventstate->prev_xy, win->eventstate->xy);
copy_v2_v2_int(event->prev_xy, win->eventstate->xy);
}
- else if (ISMOUSE_BUTTON(event->type) || ISKEYBOARD(event->type)) {
+ else if (ISKEYBOARD_OR_BUTTON(event->type)) {
win->eventstate->prev_val = event->prev_val = win->eventstate->val;
win->eventstate->prev_type = event->prev_type = win->eventstate->type;
@@ -154,13 +155,36 @@ wmEvent *WM_event_add_simulate(wmWindow *win, const wmEvent *event_to_add)
if (event->val == KM_PRESS) {
if ((event->flag & WM_EVENT_IS_REPEAT) == 0) {
- copy_v2_v2_int(win->eventstate->prev_click_xy, event->xy);
+ copy_v2_v2_int(win->eventstate->prev_press_xy, event->xy);
}
}
}
return event;
}
+static void wm_event_custom_free(wmEvent *event)
+{
+ if ((event->customdata && event->customdata_free) == 0) {
+ return;
+ }
+
+ /* NOTE: pointer to #ListBase struct elsewhere. */
+ if (event->custom == EVT_DATA_DRAGDROP) {
+ ListBase *lb = event->customdata;
+ WM_drag_free_list(lb);
+ }
+ else {
+ MEM_freeN(event->customdata);
+ }
+}
+
+static void wm_event_custom_clear(wmEvent *event)
+{
+ event->custom = 0;
+ event->customdata = NULL;
+ event->customdata_free = false;
+}
+
void wm_event_free(wmEvent *event)
{
#ifndef NDEBUG
@@ -172,22 +196,35 @@ void wm_event_free(wmEvent *event)
}
#endif
- if (event->customdata) {
- if (event->customdata_free) {
- /* NOTE: pointer to #ListBase struct elsewhere. */
- if (event->custom == EVT_DATA_DRAGDROP) {
- ListBase *lb = event->customdata;
- WM_drag_free_list(lb);
- }
- else {
- MEM_freeN(event->customdata);
- }
- }
- }
+ wm_event_custom_free(event);
MEM_freeN(event);
}
+/** A version of #wm_event_free that holds the last handled event. */
+static void wm_event_free_last_handled(wmWindow *win, wmEvent *event)
+{
+ /* Don't rely on this pointer being valid,
+ * callers should behave as if the memory has been freed.
+ * As this function should be interchangeable with #wm_event_free. */
+#ifndef NDEBUG
+ {
+ wmEvent *event_copy = MEM_dupallocN(event);
+ MEM_freeN(event);
+ event = event_copy;
+ }
+#endif
+
+ if (win->event_last_handled) {
+ wm_event_free(win->event_last_handled);
+ }
+ /* Don't store custom data in the last handled event as we don't have control how long this event
+ * will be stored and the referenced data may become invalid (also it's not needed currently). */
+ wm_event_custom_free(event);
+ wm_event_custom_clear(event);
+ win->event_last_handled = event;
+}
+
static void wm_event_free_last(wmWindow *win)
{
wmEvent *event = BLI_poptail(&win->event_queue);
@@ -1276,7 +1313,7 @@ static void wm_region_mouse_co(bContext *C, wmEvent *event)
*/
static int wm_operator_invoke(bContext *C,
wmOperatorType *ot,
- wmEvent *event,
+ const wmEvent *event,
PointerRNA *properties,
ReportList *reports,
const bool poll_only,
@@ -1317,7 +1354,9 @@ static int wm_operator_invoke(bContext *C,
}
if (op->type->invoke && event) {
- wm_region_mouse_co(C, event);
+ /* Temporarily write into `mval` (not technically `const` correct) but this is restored. */
+ int mval_prev[2] = {UNPACK2(event->mval)};
+ wm_region_mouse_co(C, (wmEvent *)event);
if (op->type->flag & OPTYPE_UNDO) {
wm->op_undo_depth++;
@@ -1329,6 +1368,8 @@ static int wm_operator_invoke(bContext *C,
if (op->type->flag & OPTYPE_UNDO && CTX_wm_manager(C) == wm) {
wm->op_undo_depth--;
}
+
+ copy_v2_v2_int(((wmEvent *)event)->mval, mval_prev);
}
else if (op->type->exec) {
if (op->type->flag & OPTYPE_UNDO) {
@@ -1440,7 +1481,7 @@ static int wm_operator_call_internal(bContext *C,
ReportList *reports,
const wmOperatorCallContext context,
const bool poll_only,
- wmEvent *event)
+ const wmEvent *event)
{
int retval;
@@ -1572,19 +1613,21 @@ static int wm_operator_call_internal(bContext *C,
int WM_operator_name_call_ptr(bContext *C,
wmOperatorType *ot,
wmOperatorCallContext context,
- PointerRNA *properties)
+ PointerRNA *properties,
+ const wmEvent *event)
{
BLI_assert(ot == WM_operatortype_find(ot->idname, true));
- return wm_operator_call_internal(C, ot, properties, NULL, context, false, NULL);
+ return wm_operator_call_internal(C, ot, properties, NULL, context, false, event);
}
int WM_operator_name_call(bContext *C,
const char *opstring,
wmOperatorCallContext context,
- PointerRNA *properties)
+ PointerRNA *properties,
+ const wmEvent *event)
{
wmOperatorType *ot = WM_operatortype_find(opstring, 0);
if (ot) {
- return WM_operator_name_call_ptr(C, ot, context, properties);
+ return WM_operator_name_call_ptr(C, ot, context, properties, event);
}
return 0;
@@ -1603,12 +1646,13 @@ bool WM_operator_name_poll(bContext *C, const char *opstring)
int WM_operator_name_call_with_properties(struct bContext *C,
const char *opstring,
wmOperatorCallContext context,
- struct IDProperty *properties)
+ struct IDProperty *properties,
+ const wmEvent *event)
{
PointerRNA props_ptr;
wmOperatorType *ot = WM_operatortype_find(opstring, false);
RNA_pointer_create(G_MAIN->wm.first, ot->srna, properties, &props_ptr);
- return WM_operator_name_call_ptr(C, ot, context, &props_ptr);
+ return WM_operator_name_call_ptr(C, ot, context, &props_ptr, event);
}
void WM_menu_name_call(bContext *C, const char *menu_name, short context)
@@ -1617,7 +1661,7 @@ void WM_menu_name_call(bContext *C, const char *menu_name, short context)
PointerRNA ptr;
WM_operator_properties_create_ptr(&ptr, ot);
RNA_string_set(&ptr, "name", menu_name);
- WM_operator_name_call_ptr(C, ot, context, &ptr);
+ WM_operator_name_call_ptr(C, ot, context, &ptr, NULL);
WM_operator_properties_free(&ptr);
}
@@ -1729,7 +1773,8 @@ static int ui_handler_wait_for_input(bContext *C, const wmEvent *event, void *us
WM_operator_name_call_ptr(C,
opwait->optype_params.optype,
opwait->optype_params.opcontext,
- opwait->optype_params.opptr);
+ opwait->optype_params.opptr,
+ event);
CTX_store_set(C, NULL);
}
@@ -1751,6 +1796,7 @@ void WM_operator_name_call_ptr_with_depends_on_cursor(bContext *C,
wmOperatorType *ot,
wmOperatorCallContext opcontext,
PointerRNA *properties,
+ const wmEvent *event,
const char *drawstr)
{
int flag = ot->flag;
@@ -1763,7 +1809,7 @@ void WM_operator_name_call_ptr_with_depends_on_cursor(bContext *C,
}
if ((flag & OPTYPE_DEPENDS_ON_CURSOR) == 0) {
- WM_operator_name_call_ptr(C, ot, opcontext, properties);
+ WM_operator_name_call_ptr(C, ot, opcontext, properties, event);
return;
}
@@ -3062,8 +3108,7 @@ static int wm_handlers_do_intern(bContext *C, wmWindow *win, wmEvent *event, Lis
WM_drag_free_list(lb);
WM_drag_free_list(&single_lb);
- event->customdata = NULL;
- event->custom = 0;
+ wm_event_custom_clear(event);
wm_drop_end(C, drag, drop);
@@ -3165,21 +3210,22 @@ static int wm_handlers_do(bContext *C, wmEvent *event, ListBase *handlers)
* in `action` setting #WM_HANDLER_HANDLED, but not #WM_HANDLER_BREAK. */
if ((action & WM_HANDLER_BREAK) == 0 || wm_action_not_handled(action)) {
if (win->event_queue_check_drag) {
- if (WM_event_drag_test(event, event->prev_click_xy)) {
+ if ((event->flag & WM_EVENT_FORCE_DRAG_THRESHOLD) ||
+ WM_event_drag_test(event, event->prev_press_xy)) {
win->event_queue_check_drag_handled = true;
const int direction = WM_event_drag_direction(event);
- const int prev_xy[2] = {UNPACK2(event->xy)};
+ /* Intentionally leave `event->xy` as-is, event users are expected to use
+ * `event->prev_press_xy` if they need to access the drag start location. */
const short prev_val = event->val;
const short prev_type = event->type;
const uint8_t prev_modifier = event->modifier;
const short prev_keymodifier = event->keymodifier;
- copy_v2_v2_int(event->xy, event->prev_click_xy);
event->val = KM_CLICK_DRAG;
- event->type = event->prev_click_type;
- event->modifier = event->prev_click_modifier;
- event->keymodifier = event->prev_click_keymodifier;
+ event->type = event->prev_press_type;
+ event->modifier = event->prev_press_modifier;
+ event->keymodifier = event->prev_press_keymodifier;
event->direction = direction;
CLOG_INFO(WM_LOG_HANDLERS, 1, "handling PRESS_DRAG");
@@ -3191,7 +3237,6 @@ static int wm_handlers_do(bContext *C, wmEvent *event, ListBase *handlers)
event->modifier = prev_modifier;
event->val = prev_val;
event->type = prev_type;
- copy_v2_v2_int(event->xy, prev_xy);
win->event_queue_check_click = false;
if (!((action & WM_HANDLER_BREAK) == 0 || wm_action_not_handled(action))) {
@@ -3205,7 +3250,7 @@ static int wm_handlers_do(bContext *C, wmEvent *event, ListBase *handlers)
win->event_queue_check_drag = false;
}
}
- else if (ISMOUSE_BUTTON(event->type) || ISKEYBOARD(event->type)) {
+ else if (ISKEYBOARD_OR_BUTTON(event->type)) {
/* All events that don't set #wmEvent.prev_type must be ignored. */
/* Test for CLICK events. */
@@ -3222,8 +3267,8 @@ static int wm_handlers_do(bContext *C, wmEvent *event, ListBase *handlers)
}
else if (event->val == KM_RELEASE) {
if (win->event_queue_check_drag) {
- if ((event->prev_click_type != event->type) &&
- (ISKEYMODIFIER(event->type) || (event->type == event->prev_click_keymodifier))) {
+ if ((event->prev_press_type != event->type) &&
+ (ISKEYMODIFIER(event->type) || (event->type == event->prev_press_keymodifier))) {
/* Support releasing modifier keys without canceling the drag event, see T89989. */
}
else {
@@ -3232,12 +3277,12 @@ static int wm_handlers_do(bContext *C, wmEvent *event, ListBase *handlers)
}
}
- if (event->prev_click_type == event->type) {
+ if (event->prev_press_type == event->type) {
if (event->val == KM_RELEASE) {
if (event->prev_val == KM_PRESS) {
if (win->event_queue_check_click == true) {
- if (WM_event_drag_test(event, event->prev_click_xy)) {
+ if (WM_event_drag_test(event, event->prev_press_xy)) {
win->event_queue_check_click = false;
win->event_queue_check_drag = false;
}
@@ -3246,7 +3291,7 @@ static int wm_handlers_do(bContext *C, wmEvent *event, ListBase *handlers)
* accurate selecting in case the mouse drifts a little. */
int xy[2] = {UNPACK2(event->xy)};
- copy_v2_v2_int(event->xy, event->prev_click_xy);
+ copy_v2_v2_int(event->xy, event->prev_press_xy);
event->val = KM_CLICK;
CLOG_INFO(WM_LOG_HANDLERS, 1, "handling CLICK");
@@ -3406,11 +3451,8 @@ static void wm_event_drag_and_drop_test(wmWindowManager *wm, wmWindow *win, wmEv
event->type = EVT_DROP;
/* Create custom-data, first free existing. */
- if (event->customdata) {
- if (event->customdata_free) {
- MEM_freeN(event->customdata);
- }
- }
+ wm_event_custom_free(event);
+ wm_event_custom_clear(event);
event->custom = EVT_DATA_DRAGDROP;
event->customdata = &wm->drags;
@@ -3653,6 +3695,19 @@ void wm_event_do_handlers(bContext *C)
while ((event = win->event_queue.first)) {
int action = WM_HANDLER_CONTINUE;
+ /* Force handling drag if a key is pressed even if the drag threshold has not been met.
+ * Needed so tablet actions (which typically use a larger threshold) can click-drag
+ * then press keys - activating the drag action early.
+ * Limit to mouse-buttons drag actions interrupted by pressing any non-mouse button.
+ * Otherwise pressing two keys on the keyboard will interpret this as a drag action. */
+ if (win->event_queue_check_drag) {
+ if ((event->val == KM_PRESS) && ((event->flag & WM_EVENT_IS_REPEAT) == 0) &&
+ ISKEYBOARD_OR_BUTTON(event->type) && ISMOUSE_BUTTON(event->prev_press_type)) {
+ event = wm_event_add_mousemove_to_head(win);
+ event->flag |= WM_EVENT_FORCE_DRAG_THRESHOLD;
+ }
+ }
+
/* Active screen might change during handlers, update pointer. */
screen = WM_window_get_active_screen(win);
@@ -3668,7 +3723,7 @@ void wm_event_do_handlers(bContext *C)
CLOG_INFO(WM_LOG_HANDLERS, 1, "event filtered due to pie button pressed");
}
BLI_remlink(&win->event_queue, event);
- wm_event_free(event);
+ wm_event_free_last_handled(win, event);
continue;
}
@@ -3678,7 +3733,7 @@ void wm_event_do_handlers(bContext *C)
if (event->type == EVT_XR_ACTION) {
wm_event_handle_xrevent(C, wm, win, event);
BLI_remlink(&win->event_queue, event);
- wm_event_free(event);
+ wm_event_free_last_handled(win, event);
/* Skip mouse event handling below, which is unnecessary for XR events. */
continue;
}
@@ -3816,7 +3871,7 @@ void wm_event_do_handlers(bContext *C)
/* Un-link and free here, Blender-quit then frees all. */
BLI_remlink(&win->event_queue, event);
- wm_event_free(event);
+ wm_event_free_last_handled(win, event);
}
/* Only add mouse-move when the event queue was read entirely. */
@@ -4692,11 +4747,11 @@ static bool wm_event_is_double_click(const wmEvent *event)
{
if ((event->type == event->prev_type) && (event->prev_val == KM_RELEASE) &&
(event->val == KM_PRESS)) {
- if (ISMOUSE(event->type) && WM_event_drag_test(event, event->prev_click_xy)) {
+ if (ISMOUSE(event->type) && WM_event_drag_test(event, event->prev_press_xy)) {
/* Pass. */
}
else {
- if ((PIL_check_seconds_timer() - event->prev_click_time) * 1000 < U.dbl_click_time) {
+ if ((PIL_check_seconds_timer() - event->prev_press_time) * 1000 < U.dbl_click_time) {
return true;
}
}
@@ -4714,14 +4769,14 @@ static void wm_event_prev_values_set(wmEvent *event, wmEvent *event_state)
event->prev_type = event_state->prev_type = event_state->type;
}
-static void wm_event_prev_click_set(wmEvent *event, wmEvent *event_state)
+static void wm_event_prev_click_set(wmEvent *event_state)
{
- event->prev_click_time = event_state->prev_click_time = PIL_check_seconds_timer();
- event->prev_click_type = event_state->prev_click_type = event_state->type;
- event->prev_click_modifier = event_state->prev_click_modifier = event_state->modifier;
- event->prev_click_keymodifier = event_state->prev_click_keymodifier = event_state->keymodifier;
- event->prev_click_xy[0] = event_state->prev_click_xy[0] = event_state->xy[0];
- event->prev_click_xy[1] = event_state->prev_click_xy[1] = event_state->xy[1];
+ event_state->prev_press_time = PIL_check_seconds_timer();
+ event_state->prev_press_type = event_state->type;
+ event_state->prev_press_modifier = event_state->modifier;
+ event_state->prev_press_keymodifier = event_state->keymodifier;
+ event_state->prev_press_xy[0] = event_state->xy[0];
+ event_state->prev_press_xy[1] = event_state->xy[1];
}
static wmEvent *wm_event_add_mousemove(wmWindow *win, const wmEvent *event)
@@ -4745,6 +4800,38 @@ static wmEvent *wm_event_add_mousemove(wmWindow *win, const wmEvent *event)
return event_new;
}
+static wmEvent *wm_event_add_mousemove_to_head(wmWindow *win)
+{
+ /* Use the last handled event instead of `win->eventstate` because the state of the modifiers
+ * and previous values should be set based on the last state, not using values from the future.
+ * So this gives an accurate simulation of mouse motion before the next event is handled. */
+ const wmEvent *event_last = win->event_last_handled;
+
+ wmEvent tevent;
+ if (event_last) {
+ tevent = *event_last;
+
+ tevent.flag = 0;
+ tevent.ascii = '\0';
+ tevent.utf8_buf[0] = '\0';
+
+ wm_event_custom_clear(&tevent);
+ }
+ else {
+ memset(&tevent, 0x0, sizeof(tevent));
+ }
+
+ tevent.type = MOUSEMOVE;
+ copy_v2_v2_int(tevent.prev_xy, tevent.xy);
+
+ wmEvent *event_new = wm_event_add(win, &tevent);
+ BLI_remlink(&win->event_queue, event_new);
+ BLI_addhead(&win->event_queue, event_new);
+
+ copy_v2_v2_int(event_new->prev_xy, event_last->xy);
+ return event_new;
+}
+
static wmEvent *wm_event_add_trackpad(wmWindow *win, const wmEvent *event, int deltax, int deltay)
{
/* Ignore in between track-pad events for performance, we only need high accuracy
@@ -4765,6 +4852,46 @@ static wmEvent *wm_event_add_trackpad(wmWindow *win, const wmEvent *event, int d
return event_new;
}
+/**
+ * Update the event-state for any kind of event that supports #KM_PRESS / #KM_RELEASE.
+ */
+static void wm_event_state_update_and_click_set(const GHOST_TEventType type,
+ wmEvent *event,
+ wmEvent *event_state)
+{
+ BLI_assert(ISKEYBOARD_OR_BUTTON(event->type));
+ BLI_assert(ELEM(event->val, KM_PRESS, KM_RELEASE));
+
+ /* Only copy these flags into the `event_state`. */
+ const eWM_EventFlag event_state_flag_mask = WM_EVENT_IS_REPEAT;
+
+ wm_event_prev_values_set(event, event_state);
+
+ /* Copy to event state. */
+ event_state->val = event->val;
+ event_state->type = event->type;
+ /* It's important only to write into the `event_state` modifier for keyboard
+ * events because emulate MMB clears one of the modifiers in `event->modifier`,
+ * making the second press not behave as if the modifier is pressed, see T96279. */
+ if (ELEM(type, GHOST_kEventKeyDown, GHOST_kEventKeyUp)) {
+ event_state->modifier = event->modifier;
+ }
+ event_state->flag = (event->flag & event_state_flag_mask);
+ /* NOTE: It's important that `keymodifier` is handled in the keyboard event handling logic
+ * since the `event_state` and the `event` are not kept in sync. */
+
+ /* Double click test. */
+ if (wm_event_is_double_click(event)) {
+ CLOG_INFO(WM_LOG_HANDLERS, 1, "Send double click");
+ event->val = KM_DBL_CLICK;
+ }
+ else if (event->val == KM_PRESS) {
+ if ((event->flag & WM_EVENT_IS_REPEAT) == 0) {
+ wm_event_prev_click_set(event_state);
+ }
+ }
+}
+
void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, void *customdata)
{
if (UNLIKELY(G.f & G_FLAG_EVENT_SIMULATE)) {
@@ -4806,15 +4933,13 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, void
* while not common, avoid a false alarm. */
#ifndef NDEBUG
if ((event_state->type || event_state->val) && /* Ignore cleared event state. */
- !(ISMOUSE_BUTTON(event_state->type) || ISKEYBOARD(event_state->type) ||
- (event_state->type == EVENT_NONE))) {
+ !(ISKEYBOARD_OR_BUTTON(event_state->type) || (event_state->type == EVENT_NONE))) {
CLOG_WARN(WM_LOG_HANDLERS,
"Non-keyboard/mouse button found in 'win->eventstate->type = %d'",
event_state->type);
}
if ((event_state->prev_type || event_state->prev_val) && /* Ignore cleared event state. */
- !(ISMOUSE_BUTTON(event_state->prev_type) || ISKEYBOARD(event_state->prev_type) ||
- (event_state->type == EVENT_NONE))) {
+ !(ISKEYBOARD_OR_BUTTON(event_state->prev_type) || (event_state->type == EVENT_NONE))) {
CLOG_WARN(WM_LOG_HANDLERS,
"Non-keyboard/mouse button found in 'win->eventstate->prev_type = %d'",
event_state->prev_type);
@@ -4924,20 +5049,7 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, void
wm_tablet_data_from_ghost(&bd->tablet, &event.tablet);
wm_eventemulation(&event, false);
- wm_event_prev_values_set(&event, event_state);
-
- /* Copy to event state. */
- event_state->val = event.val;
- event_state->type = event.type;
-
- /* Double click test. */
- if (wm_event_is_double_click(&event)) {
- CLOG_INFO(WM_LOG_HANDLERS, 1, "Send double click");
- event.val = KM_DBL_CLICK;
- }
- if (event.val == KM_PRESS) {
- wm_event_prev_click_set(&event, event_state);
- }
+ wm_event_state_update_and_click_set(type, &event, event_state);
/* Add to other window if event is there (not to both!). */
wmWindow *win_other = wm_event_cursor_other_windows(wm, win, &event);
@@ -4966,9 +5078,6 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, void
case GHOST_kEventKeyDown:
case GHOST_kEventKeyUp: {
GHOST_TEventKeyData *kd = customdata;
- /* Only copy these flags into the `event_state`. */
- const eWM_EventFlag event_state_flag_mask = WM_EVENT_IS_REPEAT;
- bool keymodifier = 0;
event.type = convert_key(kd->key);
event.ascii = kd->ascii;
/* Might be not NULL terminated. */
@@ -4979,12 +5088,6 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, void
event.val = (type == GHOST_kEventKeyDown) ? KM_PRESS : KM_RELEASE;
wm_eventemulation(&event, false);
- wm_event_prev_values_set(&event, event_state);
-
- /* Copy to event state. */
- event_state->val = event.val;
- event_state->type = event.type;
- event_state->flag = (event.flag & event_state_flag_mask);
/* Exclude arrow keys, escape, etc from text input. */
if (type == GHOST_kEventKeyUp) {
@@ -5017,108 +5120,68 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, void
switch (event.type) {
case EVT_LEFTSHIFTKEY:
- case EVT_RIGHTSHIFTKEY:
- if (event.val == KM_PRESS) {
- keymodifier = true;
- }
- if (keymodifier) {
- event.modifier |= KM_SHIFT;
- event_state->modifier |= KM_SHIFT;
- }
- else {
- event.modifier &= ~KM_SHIFT;
- event_state->modifier &= ~KM_SHIFT;
- }
+ case EVT_RIGHTSHIFTKEY: {
+ SET_FLAG_FROM_TEST(event.modifier, (event.val == KM_PRESS), KM_SHIFT);
break;
+ }
case EVT_LEFTCTRLKEY:
- case EVT_RIGHTCTRLKEY:
- if (event.val == KM_PRESS) {
- keymodifier = true;
- }
- if (keymodifier) {
- event.modifier |= KM_CTRL;
- event_state->modifier |= KM_CTRL;
- }
- else {
- event.modifier &= ~KM_CTRL;
- event_state->modifier &= ~KM_CTRL;
- }
+ case EVT_RIGHTCTRLKEY: {
+ SET_FLAG_FROM_TEST(event.modifier, (event.val == KM_PRESS), KM_CTRL);
break;
+ }
case EVT_LEFTALTKEY:
- case EVT_RIGHTALTKEY:
- if (event.val == KM_PRESS) {
- keymodifier = true;
- }
- if (keymodifier) {
- event.modifier |= KM_ALT;
- event_state->modifier |= KM_ALT;
- }
- else {
- event.modifier &= ~KM_ALT;
- event_state->modifier &= ~KM_ALT;
- }
+ case EVT_RIGHTALTKEY: {
+ SET_FLAG_FROM_TEST(event.modifier, (event.val == KM_PRESS), KM_ALT);
+ break;
+ }
+ case EVT_OSKEY: {
+ SET_FLAG_FROM_TEST(event.modifier, (event.val == KM_PRESS), KM_OSKEY);
break;
- case EVT_OSKEY:
+ }
+ default: {
if (event.val == KM_PRESS) {
- keymodifier = true;
- }
- if (keymodifier) {
- event.modifier |= KM_OSKEY;
- event_state->modifier |= KM_OSKEY;
+ if (event.keymodifier == 0) {
+ /* Only set in `eventstate`, for next event. */
+ event_state->keymodifier = event.type;
+ }
}
else {
- event.modifier &= ~KM_OSKEY;
- event_state->modifier &= ~KM_OSKEY;
+ BLI_assert(event.val == KM_RELEASE);
+ if (event.keymodifier == event.type) {
+ event.keymodifier = event_state->keymodifier = 0;
+ }
}
- break;
- default:
- if (event.val == KM_PRESS && event.keymodifier == 0) {
- /* Only set in `eventstate`, for next event. */
- event_state->keymodifier = event.type;
+
+ /* This case happens on holding a key pressed,
+ * it should not generate press events with the same key as modifier. */
+ if (event.keymodifier == event.type) {
+ event.keymodifier = 0;
}
- else if (event.val == KM_RELEASE && event.keymodifier == event.type) {
- event.keymodifier = event_state->keymodifier = 0;
+ else if (event.keymodifier == EVT_UNKNOWNKEY) {
+ /* This case happens with an external number-pad, and also when using 'dead keys'
+ * (to compose complex latin characters e.g.), it's not really clear why.
+ * Since it's impossible to map a key modifier to an unknown key,
+ * it shouldn't harm to clear it. */
+ event_state->keymodifier = event.keymodifier = 0;
}
break;
+ }
}
- /* Double click test. */
- /* If previous event was same type, and previous was release, and now it presses... */
- if (wm_event_is_double_click(&event)) {
- CLOG_INFO(WM_LOG_HANDLERS, 1, "Send double click");
- event.val = KM_DBL_CLICK;
- }
-
- /* This case happens on holding a key pressed,
- * it should not generate press events with the same key as modifier. */
- if (event.keymodifier == event.type) {
- event.keymodifier = 0;
- }
-
- /* This case happens with an external number-pad, and also when using 'dead keys'
- * (to compose complex latin characters e.g.), it's not really clear why.
- * Since it's impossible to map a key modifier to an unknown key,
- * it shouldn't harm to clear it. */
- if (event.keymodifier == EVT_UNKNOWNKEY) {
- event_state->keymodifier = event.keymodifier = 0;
- }
+ /* It's important `event.modifier` has been initialized first. */
+ wm_event_state_update_and_click_set(type, &event, event_state);
/* If test_break set, it catches this. Do not set with modifier presses.
- * XXX Keep global for now? */
- if ((event.type == EVT_ESCKEY && event.val == KM_PRESS) &&
- /* Check other modifiers because ms-windows uses these to bring up the task manager. */
- ((event.modifier & (KM_SHIFT | KM_CTRL | KM_ALT)) == 0)) {
+ * Exclude modifiers because MS-Windows uses these to bring up the task manager.
+ *
+ * NOTE: in general handling events here isn't great design as
+ * event handling should be managed by the event handling loop.
+ * Make an exception for `G.is_break` as it ensures we can always cancel operations
+ * such as rendering or baking no matter which operation is currently handling events. */
+ if ((event.type == EVT_ESCKEY) && (event.val == KM_PRESS) && (event.modifier == 0)) {
G.is_break = true;
}
- /* Double click test - only for press. */
- if (event.val == KM_PRESS) {
- /* Don't reset timer & location when holding the key generates repeat events. */
- if ((event.flag & WM_EVENT_IS_REPEAT) == 0) {
- wm_event_prev_click_set(&event, event_state);
- }
- }
-
wm_event_add(win, &event);
break;
@@ -5173,11 +5236,15 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, void
case GHOST_kRelease:
event.val = KM_RELEASE;
break;
+ default:
+ BLI_assert_unreachable();
}
event.custom = 0;
event.customdata = NULL;
+ wm_event_state_update_and_click_set(type, &event, event_state);
+
wm_event_add(win, &event);
break;
@@ -5230,7 +5297,7 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, void
#ifdef WITH_XR_OPENXR
void wm_event_add_xrevent(wmWindow *win, wmXrActionData *actiondata, short val)
{
- BLI_assert(val == KM_PRESS || val == KM_RELEASE);
+ BLI_assert(ELEM(val, KM_PRESS, KM_RELEASE));
wmEvent event = {
.type = EVT_XR_ACTION,
diff --git a/source/blender/windowmanager/intern/wm_files.c b/source/blender/windowmanager/intern/wm_files.c
index 7471d41b44c..04ce7bcb520 100644
--- a/source/blender/windowmanager/intern/wm_files.c
+++ b/source/blender/windowmanager/intern/wm_files.c
@@ -246,7 +246,9 @@ static void wm_window_substitute_old(wmWindowManager *oldwm,
oldwin->gpuctx = NULL;
win->eventstate = oldwin->eventstate;
+ win->event_last_handled = oldwin->event_last_handled;
oldwin->eventstate = NULL;
+ oldwin->event_last_handled = NULL;
/* Ensure proper screen re-scaling. */
win->sizex = oldwin->sizex;
@@ -1966,7 +1968,7 @@ void wm_autosave_timer_end(wmWindowManager *wm)
}
}
-void WM_autosave_init(wmWindowManager *wm)
+void WM_file_autosave_init(wmWindowManager *wm)
{
wm_autosave_timer_begin(wm);
}
@@ -2422,7 +2424,7 @@ static int wm_homefile_read_exec(bContext *C, wmOperator *op)
static void wm_homefile_read_after_dialog_callback(bContext *C, void *user_data)
{
WM_operator_name_call_with_properties(
- C, "WM_OT_read_homefile", WM_OP_EXEC_DEFAULT, (IDProperty *)user_data);
+ C, "WM_OT_read_homefile", WM_OP_EXEC_DEFAULT, (IDProperty *)user_data, NULL);
}
static int wm_homefile_read_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
@@ -2575,7 +2577,7 @@ static int wm_open_mainfile_dispatch(bContext *C, wmOperator *op);
static void wm_open_mainfile_after_dialog_callback(bContext *C, void *user_data)
{
WM_operator_name_call_with_properties(
- C, "WM_OT_open_mainfile", WM_OP_INVOKE_DEFAULT, (IDProperty *)user_data);
+ C, "WM_OT_open_mainfile", WM_OP_INVOKE_DEFAULT, (IDProperty *)user_data, NULL);
}
static int wm_open_mainfile__discard_changes(bContext *C, wmOperator *op)
@@ -2860,7 +2862,7 @@ void WM_OT_revert_mainfile(wmOperatorType *ot)
/** \name Recover Last Session Operator
* \{ */
-bool WM_recover_last_session(bContext *C, ReportList *reports)
+bool WM_file_recover_last_session(bContext *C, ReportList *reports)
{
char filepath[FILE_MAX];
BLI_join_dirfile(filepath, sizeof(filepath), BKE_tempdir_base(), BLENDER_QUIT_FILE);
@@ -2874,7 +2876,7 @@ static int wm_recover_last_session_exec(bContext *C, wmOperator *op)
{
wm_open_init_use_scripts(op, true);
SET_FLAG_FROM_TEST(G.f, RNA_boolean_get(op->ptr, "use_scripts"), G_FLAG_SCRIPT_AUTOEXEC);
- if (WM_recover_last_session(C, op->reports)) {
+ if (WM_file_recover_last_session(C, op->reports)) {
if (!G.background) {
wmOperatorType *ot = op->type;
PointerRNA *props_ptr = MEM_callocN(sizeof(PointerRNA), __func__);
@@ -2890,7 +2892,7 @@ static int wm_recover_last_session_exec(bContext *C, wmOperator *op)
static void wm_recover_last_session_after_dialog_callback(bContext *C, void *user_data)
{
WM_operator_name_call_with_properties(
- C, "WM_OT_recover_last_session", WM_OP_EXEC_DEFAULT, (IDProperty *)user_data);
+ C, "WM_OT_recover_last_session", WM_OP_EXEC_DEFAULT, (IDProperty *)user_data, NULL);
}
static int wm_recover_last_session_invoke(bContext *C,
@@ -3288,7 +3290,7 @@ static void wm_block_autorun_warning_reload_with_scripts(bContext *C,
/* Save user preferences for permanent execution. */
if ((U.flag & USER_SCRIPT_AUTOEXEC_DISABLE) == 0) {
- WM_operator_name_call(C, "WM_OT_save_userpref", WM_OP_EXEC_DEFAULT, NULL);
+ WM_operator_name_call(C, "WM_OT_save_userpref", WM_OP_EXEC_DEFAULT, NULL, NULL);
}
/* Load file again with scripts enabled.
@@ -3307,7 +3309,7 @@ static void wm_block_autorun_warning_enable_scripts(bContext *C,
/* Save user preferences for permanent execution. */
if ((U.flag & USER_SCRIPT_AUTOEXEC_DISABLE) == 0) {
- WM_operator_name_call(C, "WM_OT_save_userpref", WM_OP_EXEC_DEFAULT, NULL);
+ WM_operator_name_call(C, "WM_OT_save_userpref", WM_OP_EXEC_DEFAULT, NULL, NULL);
}
/* Force a full refresh, but without reloading the file. */
@@ -3476,7 +3478,7 @@ void wm_test_autorun_revert_action_exec(bContext *C)
wm_test_autorun_revert_action_set(ot, ptr);
}
- WM_operator_name_call_ptr(C, ot, WM_OP_EXEC_DEFAULT, ptr);
+ WM_operator_name_call_ptr(C, ot, WM_OP_EXEC_DEFAULT, ptr, NULL);
wm_test_autorun_revert_action_set(NULL, NULL);
}
@@ -3557,13 +3559,13 @@ static void wm_block_file_close_save(bContext *C, void *arg_block, void *arg_dat
bool file_has_been_saved_before = BKE_main_blendfile_path(bmain)[0] != '\0';
if (file_has_been_saved_before) {
- if (WM_operator_name_call(C, "WM_OT_save_mainfile", WM_OP_EXEC_DEFAULT, NULL) &
+ if (WM_operator_name_call(C, "WM_OT_save_mainfile", WM_OP_EXEC_DEFAULT, NULL, NULL) &
OPERATOR_CANCELLED) {
execute_callback = false;
}
}
else {
- WM_operator_name_call(C, "WM_OT_save_mainfile", WM_OP_INVOKE_DEFAULT, NULL);
+ WM_operator_name_call(C, "WM_OT_save_mainfile", WM_OP_INVOKE_DEFAULT, NULL, NULL);
execute_callback = false;
}
diff --git a/source/blender/windowmanager/intern/wm_gesture.c b/source/blender/windowmanager/intern/wm_gesture.c
index a6fbad8b171..ec01e097e98 100644
--- a/source/blender/windowmanager/intern/wm_gesture.c
+++ b/source/blender/windowmanager/intern/wm_gesture.c
@@ -49,6 +49,9 @@ wmGesture *WM_gesture_new(wmWindow *window, const ARegion *region, const wmEvent
gesture->modal_state = GESTURE_MODAL_NOP;
gesture->move = false;
+ int xy[2];
+ WM_event_drag_start_xy(event, xy);
+
if (ELEM(type,
WM_GESTURE_RECT,
WM_GESTURE_CROSS_RECT,
@@ -57,14 +60,14 @@ wmGesture *WM_gesture_new(wmWindow *window, const ARegion *region, const wmEvent
rcti *rect = MEM_callocN(sizeof(rcti), "gesture rect new");
gesture->customdata = rect;
- rect->xmin = event->xy[0] - gesture->winrct.xmin;
- rect->ymin = event->xy[1] - gesture->winrct.ymin;
+ rect->xmin = xy[0] - gesture->winrct.xmin;
+ rect->ymin = xy[1] - gesture->winrct.ymin;
if (type == WM_GESTURE_CIRCLE) {
/* caller is responsible for initializing 'xmax' to radius. */
}
else {
- rect->xmax = event->xy[0] - gesture->winrct.xmin;
- rect->ymax = event->xy[1] - gesture->winrct.ymin;
+ rect->xmax = xy[0] - gesture->winrct.xmin;
+ rect->ymax = xy[1] - gesture->winrct.ymin;
}
}
else if (ELEM(type, WM_GESTURE_LINES, WM_GESTURE_LASSO)) {
@@ -72,8 +75,8 @@ wmGesture *WM_gesture_new(wmWindow *window, const ARegion *region, const wmEvent
gesture->points_alloc = 1024;
gesture->customdata = lasso = MEM_mallocN(sizeof(short[2]) * gesture->points_alloc,
"lasso points");
- lasso[0] = event->xy[0] - gesture->winrct.xmin;
- lasso[1] = event->xy[1] - gesture->winrct.ymin;
+ lasso[0] = xy[0] - gesture->winrct.xmin;
+ lasso[1] = xy[1] - gesture->winrct.ymin;
gesture->points = 1;
}
diff --git a/source/blender/windowmanager/intern/wm_init_exit.c b/source/blender/windowmanager/intern/wm_init_exit.c
index 70e54e3e69d..6a9776c6933 100644
--- a/source/blender/windowmanager/intern/wm_init_exit.c
+++ b/source/blender/windowmanager/intern/wm_init_exit.c
@@ -365,7 +365,7 @@ void WM_init_splash(bContext *C)
if (wm->windows.first) {
CTX_wm_window_set(C, wm->windows.first);
- WM_operator_name_call(C, "WM_OT_splash", WM_OP_INVOKE_DEFAULT, NULL);
+ WM_operator_name_call(C, "WM_OT_splash", WM_OP_INVOKE_DEFAULT, NULL, NULL);
CTX_wm_window_set(C, prevwin);
}
}
diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c
index 0dce8b8f000..7b18d7659e2 100644
--- a/source/blender/windowmanager/intern/wm_operators.c
+++ b/source/blender/windowmanager/intern/wm_operators.c
@@ -383,7 +383,7 @@ static const char *wm_context_member_from_ptr(bContext *C, const PointerRNA *ptr
* since there is no convenient way to calculate partial RNA paths.
*
* \note While the path to the ID is typically sufficient to calculate the remainder of the path,
- * in practice this would cause #WM_context_path_resolve_property_full to crate a path such as:
+ * in practice this would cause #WM_context_path_resolve_property_full to create a path such as:
* `object.data.bones["Bones"].use_deform` such paths are not useful for key-shortcuts,
* so this function supports returning data-paths directly to context members that aren't ID types.
*/
@@ -956,8 +956,13 @@ int WM_generic_select_modal(bContext *C, wmOperator *op, const wmEvent *event)
int WM_generic_select_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- RNA_int_set(op->ptr, "mouse_x", event->mval[0]);
- RNA_int_set(op->ptr, "mouse_y", event->mval[1]);
+ ARegion *region = CTX_wm_region(C);
+
+ int mval[2];
+ WM_event_drag_start_mval(event, region, mval);
+
+ RNA_int_set(op->ptr, "mouse_x", mval[0]);
+ RNA_int_set(op->ptr, "mouse_y", mval[1]);
op->customdata = POINTER_FROM_INT(0);
@@ -3592,8 +3597,11 @@ static int doc_view_manual_ui_context_exec(bContext *C, wmOperator *UNUSED(op))
WM_operator_properties_create(&ptr_props, "WM_OT_doc_view_manual");
RNA_string_set(&ptr_props, "doc_id", buf);
- retval = WM_operator_name_call_ptr(
- C, WM_operatortype_find("WM_OT_doc_view_manual", false), WM_OP_EXEC_DEFAULT, &ptr_props);
+ retval = WM_operator_name_call_ptr(C,
+ WM_operatortype_find("WM_OT_doc_view_manual", false),
+ WM_OP_EXEC_DEFAULT,
+ &ptr_props,
+ NULL);
WM_operator_properties_free(&ptr_props);
}
diff --git a/source/blender/windowmanager/intern/wm_toolsystem.c b/source/blender/windowmanager/intern/wm_toolsystem.c
index 51e4bc9faa8..bc4bbc86367 100644
--- a/source/blender/windowmanager/intern/wm_toolsystem.c
+++ b/source/blender/windowmanager/intern/wm_toolsystem.c
@@ -611,7 +611,7 @@ bToolRef *WM_toolsystem_ref_set_by_id_ex(
RNA_enum_set(&op_props, "space_type", tkey->space_type);
RNA_boolean_set(&op_props, "cycle", cycle);
- WM_operator_name_call_ptr(C, ot, WM_OP_EXEC_DEFAULT, &op_props);
+ WM_operator_name_call_ptr(C, ot, WM_OP_EXEC_DEFAULT, &op_props, NULL);
WM_operator_properties_free(&op_props);
bToolRef *tref = WM_toolsystem_ref_find(workspace, tkey);
@@ -664,7 +664,7 @@ static const char *toolsystem_default_tool(const bToolKey *tkey)
case CTX_MODE_VERTEX_GPENCIL:
return "builtin_brush.Draw";
case CTX_MODE_SCULPT_CURVES:
- return "builtin_brush.Test 1";
+ return "builtin_brush.Comb";
/* end temporary hack. */
case CTX_MODE_PARTICLE:
diff --git a/source/blender/windowmanager/intern/wm_window.c b/source/blender/windowmanager/intern/wm_window.c
index 6c90e0603a5..cbebb856660 100644
--- a/source/blender/windowmanager/intern/wm_window.c
+++ b/source/blender/windowmanager/intern/wm_window.c
@@ -209,6 +209,9 @@ void wm_window_free(bContext *C, wmWindowManager *wm, wmWindow *win)
if (win->eventstate) {
MEM_freeN(win->eventstate);
}
+ if (win->event_last_handled) {
+ MEM_freeN(win->event_last_handled);
+ }
if (win->cursor_keymap_status) {
MEM_freeN(win->cursor_keymap_status);
@@ -1325,7 +1328,7 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr C_void_ptr
WM_operator_properties_create_ptr(&props_ptr, ot);
RNA_string_set(&props_ptr, "filepath", path);
RNA_boolean_set(&props_ptr, "display_file_selector", false);
- WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &props_ptr);
+ WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &props_ptr, NULL);
WM_operator_properties_free(&props_ptr);
CTX_wm_window_set(C, NULL);
diff --git a/source/blender/windowmanager/wm_event_types.h b/source/blender/windowmanager/wm_event_types.h
index d5c8c5022cc..0a0fdfa769a 100644
--- a/source/blender/windowmanager/wm_event_types.h
+++ b/source/blender/windowmanager/wm_event_types.h
@@ -244,6 +244,7 @@ enum {
NDOF_MOTION = 0x0190, /* 400 */
#define _NDOF_MIN NDOF_MOTION
+#define _NDOF_BUTTON_MIN NDOF_BUTTON_MENU
/* used internally, never sent */
NDOF_BUTTON_NONE = NDOF_MOTION,
@@ -274,11 +275,17 @@ enum {
NDOF_BUTTON_DOMINANT = 0x01a3, /* 419 */
NDOF_BUTTON_PLUS = 0x01a4, /* 420 */
NDOF_BUTTON_MINUS = 0x01a5, /* 421 */
+
+/* Disabled as GHOST converts these to keyboard events
+ * which use regular keyboard event handling logic. */
+#if 0
/* keyboard emulation */
NDOF_BUTTON_ESC = 0x01a6, /* 422 */
NDOF_BUTTON_ALT = 0x01a7, /* 423 */
NDOF_BUTTON_SHIFT = 0x01a8, /* 424 */
NDOF_BUTTON_CTRL = 0x01a9, /* 425 */
+#endif
+
/* general-purpose buttons */
NDOF_BUTTON_1 = 0x01aa, /* 426 */
NDOF_BUTTON_2 = 0x01ab, /* 427 */
@@ -296,6 +303,7 @@ enum {
NDOF_BUTTON_C = 0x01b6, /* 438 */
#define _NDOF_MAX NDOF_BUTTON_C
+#define _NDOF_BUTTON_MAX NDOF_BUTTON_C
/* ********** End of Input devices. ********** */
@@ -361,6 +369,17 @@ enum {
(((event_type) >= _EVT_KEYBOARD_MIN && (event_type) <= _EVT_KEYBOARD_MAX) || \
((event_type) >= EVT_F1KEY && (event_type) <= EVT_F24KEY))
+/**
+ * Test whether the event is a key on the keyboard
+ * or any other kind of button that supports press & release
+ * (use for click & click-drag detection).
+ *
+ * \note Mouse wheel events are excluded from this macro, while they do generate press events it
+ * doesn't make sense to have click & click-drag events for a mouse-wheel as it can't be held down.
+ */
+#define ISKEYBOARD_OR_BUTTON(event_type) \
+ (ISMOUSE_BUTTON(event_type) || ISKEYBOARD(event_type) || ISNDOF_BUTTON(event_type))
+
/** Test whether the event is a modifier key. */
#define ISKEYMODIFIER(event_type) \
(((event_type) >= EVT_LEFTCTRLKEY && (event_type) <= EVT_LEFTSHIFTKEY) || \
@@ -386,13 +405,16 @@ enum {
/** Test whether the event is a NDOF event. */
#define ISNDOF(event_type) ((event_type) >= _NDOF_MIN && (event_type) <= _NDOF_MAX)
+#define ISNDOF_BUTTON(event_type) \
+ ((event_type) >= _NDOF_BUTTON_MIN && (event_type) <= _NDOF_BUTTON_MAX)
#define IS_EVENT_ACTIONZONE(event_type) \
ELEM(event_type, EVT_ACTIONZONE_AREA, EVT_ACTIONZONE_REGION, EVT_ACTIONZONE_FULLSCREEN)
/** Test whether event type is acceptable as hotkey (excluding modifiers). */
#define ISHOTKEY(event_type) \
- ((ISKEYBOARD(event_type) || ISMOUSE(event_type) || ISNDOF(event_type)) && \
+ ((ISKEYBOARD(event_type) || ISMOUSE_BUTTON(event_type) || ISMOUSE_WHEEL(event_type) || \
+ ISNDOF_BUTTON(event_type)) && \
(ISKEYMODIFIER(event_type) == false))
enum eEventType_Mask {
diff --git a/source/blender/windowmanager/xr/intern/wm_xr_operators.c b/source/blender/windowmanager/xr/intern/wm_xr_operators.c
index 54800a5cd35..3c090423c41 100644
--- a/source/blender/windowmanager/xr/intern/wm_xr_operators.c
+++ b/source/blender/windowmanager/xr/intern/wm_xr_operators.c
@@ -867,7 +867,7 @@ static void wm_xr_fly_compute_turn(eXrFlyMode mode,
const float nav_inv[4][4],
float r_delta[4][4])
{
- BLI_assert(mode == XR_FLY_TURNLEFT || mode == XR_FLY_TURNRIGHT);
+ BLI_assert(ELEM(mode, XR_FLY_TURNLEFT, XR_FLY_TURNRIGHT));
float z_axis[3], m[3][3], prev[4][4], curr[4][4];
diff --git a/source/creator/creator_args.c b/source/creator/creator_args.c
index 736f1c34de6..6651aa77725 100644
--- a/source/creator/creator_args.c
+++ b/source/creator/creator_args.c
@@ -262,7 +262,7 @@ static int *parse_int_relative_clamp_n(
int i = 0;
while (true) {
const char *str_end = strchr(str, sep);
- if ((*str == sep) || (*str == '\0')) {
+ if (ELEM(*str, sep, '\0')) {
static const char *msg = "incorrect comma use";
*r_err_msg = msg;
goto fail;
diff --git a/tests/python/bl_pyapi_idprop.py b/tests/python/bl_pyapi_idprop.py
index 0e93ba0b690..ac1bd618570 100644
--- a/tests/python/bl_pyapi_idprop.py
+++ b/tests/python/bl_pyapi_idprop.py
@@ -172,6 +172,14 @@ class TestIdPropertyGroupView(TestHelper, unittest.TestCase):
self.assertEqual(list(self.id.items()), [(k, v) for v, k in enumerate(text)])
self.assertEqual(list(reversed(self.id.items())), list(reversed([(k, v) for v, k in enumerate(text)])))
+ # Check direct iteration is working as expected.
+ self.id["group"] = {ch: i for i, ch in enumerate(text)}
+ group = self.id["group"]
+
+ self.assertEqual(len(group), len(text))
+ self.assertEqual(list(iter(group)), text)
+
+
def test_contains(self):
# Check `idprop.types.IDPropertyGroupView{Keys/Values/Items}.__contains__`
text = ["A", "B", "C"]