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:
authorPeter Kim <pk15950@gmail.com>2022-04-03 05:10:23 +0300
committerPeter Kim <pk15950@gmail.com>2022-04-03 05:10:23 +0300
commitd34e2cc3be677ec0e0a26b4239b1d329e6822819 (patch)
treefa933856589ff369ed739f38f603fca4f2458987
parent07b0b6e9b78c9fc99f563244aec202acda536f2d (diff)
parent79ff65d07bac0ecf0170542f86dc03a0228b53d5 (diff)
Merge branch 'master' into xr-dev
-rwxr-xr-xbuild_files/build_environment/install_deps.sh46
-rw-r--r--doc/python_api/examples/bpy.types.UIList.1.py2
-rw-r--r--doc/python_api/examples/bpy.types.UIList.2.py2
-rw-r--r--extern/fmtlib/LICENSE.rst27
-rw-r--r--extern/fmtlib/README.blender8
-rw-r--r--extern/fmtlib/README.rst528
-rw-r--r--extern/fmtlib/include/fmt/core.h3236
-rw-r--r--extern/fmtlib/include/fmt/format-inl.h2643
-rw-r--r--extern/fmtlib/include/fmt/format.h3104
-rw-r--r--intern/cycles/blender/addon/engine.py4
-rw-r--r--intern/cycles/blender/addon/properties.py27
-rw-r--r--intern/cycles/blender/addon/ui.py66
-rw-r--r--intern/cycles/blender/light.cpp9
-rw-r--r--intern/cycles/blender/object.cpp15
-rw-r--r--intern/cycles/blender/shader.cpp2
-rw-r--r--intern/cycles/blender/sync.cpp14
-rw-r--r--intern/cycles/integrator/pass_accessor.cpp17
-rw-r--r--intern/cycles/integrator/pass_accessor.h1
-rw-r--r--intern/cycles/kernel/CMakeLists.txt1
-rw-r--r--intern/cycles/kernel/device/cuda/compat.h7
-rw-r--r--intern/cycles/kernel/device/cuda/config.h1
-rw-r--r--intern/cycles/kernel/device/gpu/image.h12
-rw-r--r--intern/cycles/kernel/device/gpu/kernel.h40
-rw-r--r--intern/cycles/kernel/device/hip/compat.h7
-rw-r--r--intern/cycles/kernel/device/hip/config.h1
-rw-r--r--intern/cycles/kernel/device/metal/compat.h1
-rw-r--r--intern/cycles/kernel/device/metal/context_begin.h15
-rw-r--r--intern/cycles/kernel/device/optix/compat.h7
-rw-r--r--intern/cycles/kernel/film/accumulate.h38
-rw-r--r--intern/cycles/kernel/geom/object.h20
-rw-r--r--intern/cycles/kernel/integrator/init_from_bake.h6
-rw-r--r--intern/cycles/kernel/integrator/intersect_closest.h46
-rw-r--r--intern/cycles/kernel/integrator/mnee.h1150
-rw-r--r--intern/cycles/kernel/integrator/path_state.h4
-rw-r--r--intern/cycles/kernel/integrator/shade_background.h29
-rw-r--r--intern/cycles/kernel/integrator/shade_light.h2
-rw-r--r--intern/cycles/kernel/integrator/shade_surface.h85
-rw-r--r--intern/cycles/kernel/integrator/shade_volume.h9
-rw-r--r--intern/cycles/kernel/integrator/shader_eval.h11
-rw-r--r--intern/cycles/kernel/integrator/shadow_state_template.h2
-rw-r--r--intern/cycles/kernel/integrator/state_template.h2
-rw-r--r--intern/cycles/kernel/integrator/subsurface.h7
-rw-r--r--intern/cycles/kernel/light/light.h18
-rw-r--r--intern/cycles/kernel/svm/closure.h8
-rw-r--r--intern/cycles/kernel/svm/sky.h38
-rw-r--r--intern/cycles/kernel/types.h61
-rw-r--r--intern/cycles/scene/background.cpp11
-rw-r--r--intern/cycles/scene/background.h2
-rw-r--r--intern/cycles/scene/film.cpp41
-rw-r--r--intern/cycles/scene/film.h2
-rw-r--r--intern/cycles/scene/light.cpp12
-rw-r--r--intern/cycles/scene/light.h3
-rw-r--r--intern/cycles/scene/object.cpp27
-rw-r--r--intern/cycles/scene/object.h8
-rw-r--r--intern/cycles/scene/pass.cpp18
-rw-r--r--intern/cycles/scene/pass.h8
-rw-r--r--intern/cycles/scene/scene.cpp31
-rw-r--r--intern/cycles/scene/scene.h3
-rw-r--r--intern/cycles/session/buffers.cpp6
-rw-r--r--intern/cycles/session/buffers.h4
-rw-r--r--intern/cycles/util/debug.h4
-rw-r--r--intern/cycles/util/math_float2.h12
-rw-r--r--intern/cycles/util/texture.h2
-rw-r--r--intern/ghost/intern/GHOST_WindowViewCocoa.h2
-rw-r--r--intern/rigidbody/RBI_api.h4
-rw-r--r--intern/rigidbody/rb_bullet_api.cpp4
-rw-r--r--release/datafiles/blender_icons.svg81
-rw-r--r--release/datafiles/blender_icons16/icon16_editmode_hlt.datbin1048 -> 1048 bytes
-rw-r--r--release/datafiles/blender_icons16/icon16_fake_user_off.datbin1048 -> 1048 bytes
-rw-r--r--release/datafiles/blender_icons16/icon16_fake_user_on.datbin1048 -> 1048 bytes
-rw-r--r--release/datafiles/blender_icons16/icon16_force_boid.datbin1048 -> 1048 bytes
-rw-r--r--release/datafiles/blender_icons16/icon16_hide_off.datbin1048 -> 1048 bytes
-rw-r--r--release/datafiles/blender_icons16/icon16_hide_on.datbin1048 -> 1048 bytes
-rw-r--r--release/datafiles/blender_icons16/icon16_indirect_only_off.datbin1048 -> 1048 bytes
-rw-r--r--release/datafiles/blender_icons16/icon16_indirect_only_on.datbin1048 -> 1048 bytes
-rw-r--r--release/datafiles/blender_icons16/icon16_library_data_indirect.datbin1048 -> 0 bytes
-rw-r--r--release/datafiles/blender_icons16/icon16_object_datamode.datbin1048 -> 1048 bytes
-rw-r--r--release/datafiles/blender_icons16/icon16_particlemode.datbin1048 -> 1048 bytes
-rw-r--r--release/datafiles/blender_icons16/icon16_pose_hlt.datbin1048 -> 1048 bytes
-rw-r--r--release/datafiles/blender_icons16/icon16_restrict_render_off.datbin1048 -> 1048 bytes
-rw-r--r--release/datafiles/blender_icons16/icon16_restrict_render_on.datbin1048 -> 1048 bytes
-rw-r--r--release/datafiles/blender_icons16/icon16_restrict_select_off.datbin1048 -> 1048 bytes
-rw-r--r--release/datafiles/blender_icons16/icon16_restrict_select_on.datbin1048 -> 1048 bytes
-rw-r--r--release/datafiles/blender_icons16/icon16_restrict_view_off.datbin1048 -> 1048 bytes
-rw-r--r--release/datafiles/blender_icons16/icon16_restrict_view_on.datbin1048 -> 1048 bytes
-rw-r--r--release/datafiles/blender_icons16/icon16_sculptmode_hlt.datbin1048 -> 1048 bytes
-rw-r--r--release/datafiles/blender_icons16/icon16_tpaint_hlt.datbin1048 -> 1048 bytes
-rw-r--r--release/datafiles/blender_icons16/icon16_uv_data.datbin1048 -> 1048 bytes
-rw-r--r--release/datafiles/blender_icons16/icon16_vpaint_hlt.datbin1048 -> 1048 bytes
-rw-r--r--release/datafiles/blender_icons16/icon16_wpaint_hlt.datbin1048 -> 1048 bytes
-rw-r--r--release/datafiles/blender_icons32/icon32_editmode_hlt.datbin4120 -> 4120 bytes
-rw-r--r--release/datafiles/blender_icons32/icon32_fake_user_off.datbin4120 -> 4120 bytes
-rw-r--r--release/datafiles/blender_icons32/icon32_fake_user_on.datbin4120 -> 4120 bytes
-rw-r--r--release/datafiles/blender_icons32/icon32_force_boid.datbin4120 -> 4120 bytes
-rw-r--r--release/datafiles/blender_icons32/icon32_hide_off.datbin4120 -> 4120 bytes
-rw-r--r--release/datafiles/blender_icons32/icon32_hide_on.datbin4120 -> 4120 bytes
-rw-r--r--release/datafiles/blender_icons32/icon32_indirect_only_off.datbin4120 -> 4120 bytes
-rw-r--r--release/datafiles/blender_icons32/icon32_indirect_only_on.datbin4120 -> 4120 bytes
-rw-r--r--release/datafiles/blender_icons32/icon32_library_data_indirect.datbin4120 -> 0 bytes
-rw-r--r--release/datafiles/blender_icons32/icon32_object_datamode.datbin4120 -> 4120 bytes
-rw-r--r--release/datafiles/blender_icons32/icon32_particlemode.datbin4120 -> 4120 bytes
-rw-r--r--release/datafiles/blender_icons32/icon32_pose_hlt.datbin4120 -> 4120 bytes
-rw-r--r--release/datafiles/blender_icons32/icon32_restrict_render_off.datbin4120 -> 4120 bytes
-rw-r--r--release/datafiles/blender_icons32/icon32_restrict_render_on.datbin4120 -> 4120 bytes
-rw-r--r--release/datafiles/blender_icons32/icon32_restrict_select_off.datbin4120 -> 4120 bytes
-rw-r--r--release/datafiles/blender_icons32/icon32_restrict_select_on.datbin4120 -> 4120 bytes
-rw-r--r--release/datafiles/blender_icons32/icon32_restrict_view_off.datbin4120 -> 4120 bytes
-rw-r--r--release/datafiles/blender_icons32/icon32_restrict_view_on.datbin4120 -> 4120 bytes
-rw-r--r--release/datafiles/blender_icons32/icon32_sculptmode_hlt.datbin4120 -> 4120 bytes
-rw-r--r--release/datafiles/blender_icons32/icon32_tpaint_hlt.datbin4120 -> 4120 bytes
-rw-r--r--release/datafiles/blender_icons32/icon32_uv_data.datbin4120 -> 4120 bytes
-rw-r--r--release/datafiles/blender_icons32/icon32_vpaint_hlt.datbin4120 -> 4120 bytes
-rw-r--r--release/datafiles/blender_icons32/icon32_wpaint_hlt.datbin4120 -> 4120 bytes
-rw-r--r--release/datafiles/userdef/userdef_default_theme.c2
-rw-r--r--release/license/THIRD-PARTY-LICENSES.txt2
-rw-r--r--release/scripts/modules/bl_i18n_utils/settings.py9
-rw-r--r--release/scripts/modules/bl_i18n_utils/utils_spell_check.py2
-rw-r--r--release/scripts/presets/interface_theme/Blender_Light.xml2
-rw-r--r--release/scripts/presets/keyconfig/keymap_data/blender_default.py26
-rw-r--r--release/scripts/startup/bl_operators/geometry_nodes.py5
-rw-r--r--release/scripts/startup/bl_ui/properties_grease_pencil_common.py4
-rw-r--r--release/scripts/startup/bl_ui/properties_object.py2
-rw-r--r--release/scripts/startup/bl_ui/properties_physics_fluid.py8
-rw-r--r--release/scripts/startup/bl_ui/properties_view_layer.py28
-rw-r--r--release/scripts/startup/bl_ui/space_outliner.py14
-rw-r--r--release/scripts/startup/bl_ui/space_topbar.py3
-rw-r--r--release/scripts/startup/bl_ui/space_view3d.py11
-rw-r--r--release/scripts/templates_py/ui_list.py2
-rw-r--r--release/scripts/templates_py/ui_list_simple.py2
-rw-r--r--source/blender/blenkernel/BKE_blender_version.h2
-rw-r--r--source/blender/blenkernel/BKE_cachefile.h3
-rw-r--r--source/blender/blenkernel/BKE_collection.h14
-rw-r--r--source/blender/blenkernel/BKE_curves.hh74
-rw-r--r--source/blender/blenkernel/BKE_geometry_fields.hh165
-rw-r--r--source/blender/blenkernel/BKE_geometry_set.hh154
-rw-r--r--source/blender/blenkernel/BKE_layer.h35
-rw-r--r--source/blender/blenkernel/BKE_lib_id.h13
-rw-r--r--source/blender/blenkernel/BKE_lib_override.h27
-rw-r--r--source/blender/blenkernel/BKE_mesh.h2
-rw-r--r--source/blender/blenkernel/BKE_modifier.h6
-rw-r--r--source/blender/blenkernel/BKE_object.h19
-rw-r--r--source/blender/blenkernel/CMakeLists.txt7
-rw-r--r--source/blender/blenkernel/intern/attribute_access.cc1
-rw-r--r--source/blender/blenkernel/intern/blendfile.c2
-rw-r--r--source/blender/blenkernel/intern/blendfile_link_append.c2
-rw-r--r--source/blender/blenkernel/intern/cachefile.c8
-rw-r--r--source/blender/blenkernel/intern/collection.c42
-rw-r--r--source/blender/blenkernel/intern/constraint.c2
-rw-r--r--source/blender/blenkernel/intern/crazyspace.c50
-rw-r--r--source/blender/blenkernel/intern/curve.cc4
-rw-r--r--source/blender/blenkernel/intern/curve_bezier.cc129
-rw-r--r--source/blender/blenkernel/intern/curve_catmull_rom.cc12
-rw-r--r--source/blender/blenkernel/intern/curves_geometry.cc100
-rw-r--r--source/blender/blenkernel/intern/curves_geometry_test.cc5
-rw-r--r--source/blender/blenkernel/intern/customdata.cc2
-rw-r--r--source/blender/blenkernel/intern/geometry_component_curves.cc1
-rw-r--r--source/blender/blenkernel/intern/geometry_component_mesh.cc1
-rw-r--r--source/blender/blenkernel/intern/geometry_set.cc1
-rw-r--r--source/blender/blenkernel/intern/gpencil_geom.cc30
-rw-r--r--source/blender/blenkernel/intern/gpencil_modifier.c2
-rw-r--r--source/blender/blenkernel/intern/gpencil_update_cache.c9
-rw-r--r--source/blender/blenkernel/intern/icons.cc2
-rw-r--r--source/blender/blenkernel/intern/image.cc216
-rw-r--r--source/blender/blenkernel/intern/layer.c148
-rw-r--r--source/blender/blenkernel/intern/lib_id.c5
-rw-r--r--source/blender/blenkernel/intern/lib_override.c93
-rw-r--r--source/blender/blenkernel/intern/lib_override_proxy_conversion.c1
-rw-r--r--source/blender/blenkernel/intern/mesh_convert.cc13
-rw-r--r--source/blender/blenkernel/intern/mesh_normals.cc10
-rw-r--r--source/blender/blenkernel/intern/modifier.c4
-rw-r--r--source/blender/blenkernel/intern/object.cc126
-rw-r--r--source/blender/blenkernel/intern/object_dupli.cc65
-rw-r--r--source/blender/blenkernel/intern/object_update.c2
-rw-r--r--source/blender/blenkernel/intern/rigidbody.c5
-rw-r--r--source/blender/blenkernel/intern/scene.cc (renamed from source/blender/blenkernel/intern/scene.c)533
-rw-r--r--source/blender/blenkernel/intern/subsurf_ccg.c2
-rw-r--r--source/blender/blenkernel/intern/world.c12
-rw-r--r--source/blender/blenlib/BLI_bitmap.h28
-rw-r--r--source/blender/blenlib/BLI_cpp_type.hh34
-rw-r--r--source/blender/blenlib/BLI_cpp_type_make.hh12
-rw-r--r--source/blender/blenlib/BLI_enumerable_thread_specific.hh19
-rw-r--r--source/blender/blenlib/BLI_generic_span.hh12
-rw-r--r--source/blender/blenlib/BLI_heap.h2
-rw-r--r--source/blender/blenlib/BLI_heap_simple.h2
-rw-r--r--source/blender/blenlib/BLI_index_mask.hh26
-rw-r--r--source/blender/blenlib/BLI_kdopbvh.h6
-rw-r--r--source/blender/blenlib/BLI_length_parameterize.hh80
-rw-r--r--source/blender/blenlib/BLI_map.hh8
-rw-r--r--source/blender/blenlib/BLI_math_color.hh28
-rw-r--r--source/blender/blenlib/BLI_math_geom.h2
-rw-r--r--source/blender/blenlib/BLI_mempool.h2
-rw-r--r--source/blender/blenlib/BLI_path_util.h6
-rw-r--r--source/blender/blenlib/BLI_polyfill_2d.h8
-rw-r--r--source/blender/blenlib/BLI_polyfill_2d_beautify.h2
-rw-r--r--source/blender/blenlib/BLI_rand.h8
-rw-r--r--source/blender/blenlib/BLI_scanfill.h2
-rw-r--r--source/blender/blenlib/BLI_set.hh9
-rw-r--r--source/blender/blenlib/BLI_task.h6
-rw-r--r--source/blender/blenlib/BLI_utildefines_stack.h14
-rw-r--r--source/blender/blenlib/BLI_vector_set.hh9
-rw-r--r--source/blender/blenlib/CMakeLists.txt4
-rw-r--r--source/blender/blenlib/intern/BLI_heap.c14
-rw-r--r--source/blender/blenlib/intern/BLI_heap_simple.c4
-rw-r--r--source/blender/blenlib/intern/BLI_kdopbvh.c214
-rw-r--r--source/blender/blenlib/intern/BLI_mempool.c16
-rw-r--r--source/blender/blenlib/intern/BLI_mempool_private.h2
-rw-r--r--source/blender/blenlib/intern/DLRB_tree.c2
-rw-r--r--source/blender/blenlib/intern/bitmap.c12
-rw-r--r--source/blender/blenlib/intern/convexhull_2d.c22
-rw-r--r--source/blender/blenlib/intern/delaunay_2d.cc50
-rw-r--r--source/blender/blenlib/intern/filereader_zstd.c34
-rw-r--r--source/blender/blenlib/intern/gsqueue.c10
-rw-r--r--source/blender/blenlib/intern/jitter_2d.c14
-rw-r--r--source/blender/blenlib/intern/length_parameterize.cc80
-rw-r--r--source/blender/blenlib/intern/math_geom.c4
-rw-r--r--source/blender/blenlib/intern/mesh_boolean.cc22
-rw-r--r--source/blender/blenlib/intern/mesh_intersect.cc50
-rw-r--r--source/blender/blenlib/intern/path_util.c34
-rw-r--r--source/blender/blenlib/intern/polyfill_2d.c142
-rw-r--r--source/blender/blenlib/intern/polyfill_2d_beautify.c6
-rw-r--r--source/blender/blenlib/intern/rand.cc24
-rw-r--r--source/blender/blenlib/intern/scanfill.c92
-rw-r--r--source/blender/blenlib/intern/scanfill_utils.c6
-rw-r--r--source/blender/blenlib/intern/stack.c24
-rw-r--r--source/blender/blenlib/intern/string.c8
-rw-r--r--source/blender/blenlib/intern/task_iterator.c70
-rw-r--r--source/blender/blenlib/intern/task_scheduler.cc8
-rw-r--r--source/blender/blenlib/intern/threads.cc10
-rw-r--r--source/blender/blenlib/intern/uuid.cc4
-rw-r--r--source/blender/blenlib/tests/BLI_cpp_type_test.cc34
-rw-r--r--source/blender/blenlib/tests/BLI_delaunay_2d_test.cc30
-rw-r--r--source/blender/blenlib/tests/BLI_length_parameterize_test.cc202
-rw-r--r--source/blender/blenlib/tests/BLI_linklist_lockfree_test.cc18
-rw-r--r--source/blender/blenlib/tests/BLI_listbase_test.cc32
-rw-r--r--source/blender/blenlib/tests/BLI_memiter_test.cc10
-rw-r--r--source/blender/blenlib/tests/BLI_mesh_intersect_test.cc118
-rw-r--r--source/blender/blenlib/tests/BLI_polyfill_2d_test.cc142
-rw-r--r--source/blender/blenlib/tests/BLI_string_test.cc40
-rw-r--r--source/blender/blenlib/tests/BLI_string_utf8_test.cc8
-rw-r--r--source/blender/blenlib/tests/BLI_task_test.cc74
-rw-r--r--source/blender/blenlib/tests/performance/BLI_task_performance_test.cc40
-rw-r--r--source/blender/blenloader/intern/versioning_300.c51
-rw-r--r--source/blender/blenloader/intern/versioning_legacy.c2
-rw-r--r--source/blender/blenloader/intern/versioning_userdef.c4
-rw-r--r--source/blender/bmesh/intern/bmesh_mesh_convert.cc4
-rw-r--r--source/blender/compositor/operations/COM_OutputFileOperation.cc5
-rw-r--r--source/blender/compositor/operations/COM_OutputFileOperation.h1
-rw-r--r--source/blender/compositor/operations/COM_ViewerOperation.cc2
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_nodes.cc2
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_relations.cc9
-rw-r--r--source/blender/depsgraph/intern/depsgraph_query_iter.cc2
-rw-r--r--source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc2
-rw-r--r--source/blender/draw/CMakeLists.txt2
-rw-r--r--source/blender/draw/engines/eevee/eevee_effects.c4
-rw-r--r--source/blender/draw/engines/eevee/eevee_lightprobes.c2
-rw-r--r--source/blender/draw/engines/eevee/eevee_occlusion.c3
-rw-r--r--source/blender/draw/engines/eevee/eevee_shadows.c2
-rw-r--r--source/blender/draw/engines/eevee/eevee_shadows_cascade.c2
-rw-r--r--source/blender/draw/engines/eevee/eevee_volumes.c2
-rw-r--r--source/blender/draw/engines/eevee/shaders/effect_mist_frag.glsl2
-rw-r--r--source/blender/draw/engines/eevee/shaders/effect_motion_blur_frag.glsl2
-rw-r--r--source/blender/draw/engines/eevee/shaders/effect_subsurface_frag.glsl12
-rw-r--r--source/blender/draw/engines/eevee/shaders/effect_temporal_aa.glsl2
-rw-r--r--source/blender/draw/engines/eevee/shaders/effect_translucency_frag.glsl4
-rw-r--r--source/blender/draw/engines/eevee/shaders/effect_velocity_resolve_frag.glsl2
-rw-r--r--source/blender/draw/engines/eevee/shaders/lightprobe_filter_glossy_frag.glsl4
-rw-r--r--source/blender/draw/engines/eevee/shaders/lights_lib.glsl4
-rw-r--r--source/blender/draw/engines/eevee/shaders/renderpass_postprocess_frag.glsl2
-rw-r--r--source/blender/draw/engines/eevee/shaders/shadow_accum_frag.glsl2
-rw-r--r--source/blender/draw/engines/gpencil/gpencil_cache_utils.c2
-rw-r--r--source/blender/draw/engines/gpencil/shaders/gpencil_vert.glsl4
-rw-r--r--source/blender/draw/engines/image/image_drawing_mode.hh4
-rw-r--r--source/blender/draw/engines/image/image_usage.hh2
-rw-r--r--source/blender/draw/engines/overlay/overlay_edit_mesh.c5
-rw-r--r--source/blender/draw/engines/overlay/overlay_extra.c9
-rw-r--r--source/blender/draw/engines/overlay/overlay_outline.c2
-rw-r--r--source/blender/draw/engines/overlay/overlay_shader.c270
-rw-r--r--source/blender/draw/engines/overlay/overlay_wireframe.c2
-rw-r--r--source/blender/draw/engines/overlay/shaders/antialiasing_frag.glsl2
-rw-r--r--source/blender/draw/engines/overlay/shaders/armature_dof_solid_frag.glsl7
-rw-r--r--source/blender/draw/engines/overlay/shaders/armature_dof_vert.glsl23
-rw-r--r--source/blender/draw/engines/overlay/shaders/armature_envelope_outline_vert.glsl23
-rw-r--r--source/blender/draw/engines/overlay/shaders/armature_envelope_solid_frag.glsl10
-rw-r--r--source/blender/draw/engines/overlay/shaders/armature_envelope_solid_vert.glsl21
-rw-r--r--source/blender/draw/engines/overlay/shaders/armature_shape_outline_geom.glsl54
-rw-r--r--source/blender/draw/engines/overlay/shaders/armature_shape_outline_vert.glsl36
-rw-r--r--source/blender/draw/engines/overlay/shaders/armature_shape_solid_frag.glsl8
-rw-r--r--source/blender/draw/engines/overlay/shaders/armature_shape_solid_vert.glsl19
-rw-r--r--source/blender/draw/engines/overlay/shaders/armature_shape_wire_vert.glsl16
-rw-r--r--source/blender/draw/engines/overlay/shaders/armature_sphere_outline_vert.glsl19
-rw-r--r--source/blender/draw/engines/overlay/shaders/armature_sphere_solid_frag.glsl15
-rw-r--r--source/blender/draw/engines/overlay/shaders/armature_sphere_solid_vert.glsl19
-rw-r--r--source/blender/draw/engines/overlay/shaders/armature_stick_frag.glsl9
-rw-r--r--source/blender/draw/engines/overlay/shaders/armature_stick_vert.glsl26
-rw-r--r--source/blender/draw/engines/overlay/shaders/armature_wire_frag.glsl9
-rw-r--r--source/blender/draw/engines/overlay/shaders/armature_wire_vert.glsl18
-rw-r--r--source/blender/draw/engines/overlay/shaders/edit_mesh_analysis_frag.glsl3
-rw-r--r--source/blender/draw/engines/overlay/shaders/edit_mesh_analysis_vert.glsl12
-rw-r--r--source/blender/draw/engines/overlay/shaders/edit_mesh_common_lib.glsl3
-rw-r--r--source/blender/draw/engines/overlay/shaders/edit_mesh_frag.glsl38
-rw-r--r--source/blender/draw/engines/overlay/shaders/edit_mesh_geom.glsl47
-rw-r--r--source/blender/draw/engines/overlay/shaders/edit_mesh_normal_vert.glsl18
-rw-r--r--source/blender/draw/engines/overlay/shaders/edit_mesh_skin_root_vert.glsl14
-rw-r--r--source/blender/draw/engines/overlay/shaders/edit_mesh_vert.glsl31
-rw-r--r--source/blender/draw/engines/overlay/shaders/extra_lightprobe_grid_vert.glsl7
-rw-r--r--source/blender/draw/engines/overlay/shaders/grid_frag.glsl4
-rw-r--r--source/blender/draw/engines/overlay/shaders/infos/armature_info.hh262
-rw-r--r--source/blender/draw/engines/overlay/shaders/infos/edit_mode_info.hh164
-rw-r--r--source/blender/draw/engines/overlay/shaders/wireframe_vert.glsl6
-rw-r--r--source/blender/draw/engines/select/select_draw_utils.c2
-rw-r--r--source/blender/draw/engines/workbench/shaders/infos/workbench_prepass_info.hh2
-rw-r--r--source/blender/draw/engines/workbench/shaders/workbench_prepass_frag.glsl2
-rw-r--r--source/blender/draw/engines/workbench/shaders/workbench_prepass_hair_vert.glsl4
-rw-r--r--source/blender/draw/engines/workbench/shaders/workbench_prepass_pointcloud_vert.glsl2
-rw-r--r--source/blender/draw/engines/workbench/shaders/workbench_prepass_vert.glsl2
-rw-r--r--source/blender/draw/engines/workbench/shaders/workbench_transparent_accum_frag.glsl2
-rw-r--r--source/blender/draw/engines/workbench/workbench_shadow.c8
-rw-r--r--source/blender/draw/intern/DRW_render.h7
-rw-r--r--source/blender/draw/intern/draw_cache.c5
-rw-r--r--source/blender/draw/intern/draw_cache_extract_mesh.cc1
-rw-r--r--source/blender/draw/intern/draw_cache_extract_mesh_render_data.c9
-rw-r--r--source/blender/draw/intern/draw_cache_impl_curves.cc243
-rw-r--r--source/blender/draw/intern/draw_cache_impl_subdivision.cc20
-rw-r--r--source/blender/draw/intern/draw_common.c7
-rw-r--r--source/blender/draw/intern/draw_common.h122
-rw-r--r--source/blender/draw/intern/draw_common_shader_shared.h268
-rw-r--r--source/blender/draw/intern/draw_hair.c10
-rw-r--r--source/blender/draw/intern/draw_hair_private.h10
-rw-r--r--source/blender/draw/intern/draw_manager.c29
-rw-r--r--source/blender/draw/intern/draw_manager_data.c20
-rw-r--r--source/blender/draw/intern/draw_manager_exec.c55
-rw-r--r--source/blender/draw/intern/draw_manager_shader.c6
-rw-r--r--source/blender/draw/intern/draw_subdivision.h2
-rw-r--r--source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_lines_paint_mask.cc77
-rw-r--r--source/blender/draw/intern/shaders/common_colormanagement_lib.glsl18
-rw-r--r--source/blender/draw/intern/shaders/common_gpencil_lib.glsl4
-rw-r--r--source/blender/draw/intern/shaders/common_hair_lib.glsl6
-rw-r--r--source/blender/draw/intern/shaders/common_subdiv_lib.glsl14
-rw-r--r--source/blender/draw/intern/shaders/common_subdiv_vbo_lnor_comp.glsl22
-rw-r--r--source/blender/draw/intern/shaders/common_view_clipping_lib.glsl14
-rw-r--r--source/blender/draw/intern/shaders/common_view_lib.glsl1
-rw-r--r--source/blender/draw/intern/shaders/draw_hair_refine_info.hh2
-rw-r--r--source/blender/draw/intern/shaders/draw_view_info.hh12
-rw-r--r--source/blender/editors/animation/anim_channels_defines.c5
-rw-r--r--source/blender/editors/animation/anim_channels_edit.c5
-rw-r--r--source/blender/editors/animation/anim_filter.c2
-rw-r--r--source/blender/editors/animation/keyframes_draw.c8
-rw-r--r--source/blender/editors/armature/meshlaplacian.c157
-rw-r--r--source/blender/editors/armature/pose_edit.c7
-rw-r--r--source/blender/editors/armature/pose_lib.c4
-rw-r--r--source/blender/editors/armature/pose_lib_2.c3
-rw-r--r--source/blender/editors/asset/ED_asset_type.h4
-rw-r--r--source/blender/editors/asset/intern/asset_type.cc2
-rw-r--r--source/blender/editors/curve/editcurve.c4
-rw-r--r--source/blender/editors/curves/intern/curves_ops.cc281
-rw-r--r--source/blender/editors/datafiles/CMakeLists.txt1
-rw-r--r--source/blender/editors/geometry/geometry_attributes.cc4
-rw-r--r--source/blender/editors/gpencil/CMakeLists.txt4
-rw-r--r--source/blender/editors/gpencil/gpencil_bake_animation.cc (renamed from source/blender/editors/gpencil/gpencil_bake_animation.c)57
-rw-r--r--source/blender/editors/gpencil/gpencil_data.c6
-rw-r--r--source/blender/editors/gpencil/gpencil_fill.c18
-rw-r--r--source/blender/editors/gpencil/gpencil_intern.h8
-rw-r--r--source/blender/editors/gpencil/gpencil_mesh.cc (renamed from source/blender/editors/gpencil/gpencil_mesh.c)71
-rw-r--r--source/blender/editors/gpencil/gpencil_primitive.c4
-rw-r--r--source/blender/editors/gpencil/gpencil_sculpt_paint.c30
-rw-r--r--source/blender/editors/gpencil/gpencil_select.c6
-rw-r--r--source/blender/editors/gpencil/gpencil_utils.c2
-rw-r--r--source/blender/editors/gpencil/gpencil_vertex_paint.c2
-rw-r--r--source/blender/editors/gpencil/gpencil_weight_paint.c2
-rw-r--r--source/blender/editors/include/ED_fileselect.h2
-rw-r--r--source/blender/editors/include/ED_node.h2
-rw-r--r--source/blender/editors/include/ED_object.h2
-rw-r--r--source/blender/editors/include/ED_select_utils.h13
-rw-r--r--source/blender/editors/include/ED_transform_snap_object_context.h16
-rw-r--r--source/blender/editors/include/ED_view3d.h5
-rw-r--r--source/blender/editors/include/UI_icons.h5
-rw-r--r--source/blender/editors/include/UI_interface.h6
-rw-r--r--source/blender/editors/include/UI_view2d.h4
-rw-r--r--source/blender/editors/interface/CMakeLists.txt20
-rw-r--r--source/blender/editors/interface/interface_draw.c24
-rw-r--r--source/blender/editors/interface/interface_eyedropper_depth.c7
-rw-r--r--source/blender/editors/interface/interface_icons.c34
-rw-r--r--source/blender/editors/interface/interface_intern.h6
-rw-r--r--source/blender/editors/interface/interface_query.cc (renamed from source/blender/editors/interface/interface_query.c)99
-rw-r--r--source/blender/editors/interface/interface_region_color_picker.cc (renamed from source/blender/editors/interface/interface_region_color_picker.c)71
-rw-r--r--source/blender/editors/interface/interface_region_hud.cc (renamed from source/blender/editors/interface/interface_region_hud.c)64
-rw-r--r--source/blender/editors/interface/interface_region_menu_pie.cc (renamed from source/blender/editors/interface/interface_region_menu_pie.c)39
-rw-r--r--source/blender/editors/interface/interface_region_menu_popup.cc (renamed from source/blender/editors/interface/interface_region_menu_popup.c)81
-rw-r--r--source/blender/editors/interface/interface_region_popover.cc (renamed from source/blender/editors/interface/interface_region_popover.c)57
-rw-r--r--source/blender/editors/interface/interface_region_popup.cc (renamed from source/blender/editors/interface/interface_region_popup.c)44
-rw-r--r--source/blender/editors/interface/interface_regions.cc (renamed from source/blender/editors/interface/interface_regions.c)4
-rw-r--r--source/blender/editors/interface/interface_style.cc (renamed from source/blender/editors/interface/interface_style.c)50
-rw-r--r--source/blender/editors/interface/interface_utils.cc (renamed from source/blender/editors/interface/interface_utils.c)129
-rw-r--r--source/blender/editors/interface/interface_widgets.c27
-rw-r--r--source/blender/editors/interface/view2d.c83
-rw-r--r--source/blender/editors/lattice/editlattice_select.c1
-rw-r--r--source/blender/editors/mesh/editmesh_tools.c2
-rw-r--r--source/blender/editors/mesh/mesh_data.c7
-rw-r--r--source/blender/editors/mesh/mesh_mirror.c2
-rw-r--r--source/blender/editors/object/object_add.cc215
-rw-r--r--source/blender/editors/object/object_bake.c2
-rw-r--r--source/blender/editors/object/object_bake_api.c106
-rw-r--r--source/blender/editors/object/object_data_transfer.c6
-rw-r--r--source/blender/editors/object/object_edit.c6
-rw-r--r--source/blender/editors/object/object_gpencil_modifier.c6
-rw-r--r--source/blender/editors/object/object_hook.c102
-rw-r--r--source/blender/editors/object/object_intern.h1
-rw-r--r--source/blender/editors/object/object_modifier.c105
-rw-r--r--source/blender/editors/object/object_ops.c1
-rw-r--r--source/blender/editors/object/object_relations.c71
-rw-r--r--source/blender/editors/object/object_remesh.cc2
-rw-r--r--source/blender/editors/object/object_shader_fx.c5
-rw-r--r--source/blender/editors/object/object_transform.cc201
-rw-r--r--source/blender/editors/object/object_vgroup.c2
-rw-r--r--source/blender/editors/physics/particle_edit.c6
-rw-r--r--source/blender/editors/physics/particle_object.c4
-rw-r--r--source/blender/editors/physics/rigidbody_constraint.c19
-rw-r--r--source/blender/editors/physics/rigidbody_object.c23
-rw-r--r--source/blender/editors/physics/rigidbody_world.c2
-rw-r--r--source/blender/editors/render/render_intern.hh2
-rw-r--r--source/blender/editors/render/render_ops.cc2
-rw-r--r--source/blender/editors/render/render_preview.cc55
-rw-r--r--source/blender/editors/render/render_shading.cc80
-rw-r--r--source/blender/editors/screen/screen_draw.c2
-rw-r--r--source/blender/editors/screen/screen_ops.c15
-rw-r--r--source/blender/editors/sculpt_paint/curves_sculpt_snake_hook.cc249
-rw-r--r--source/blender/editors/sculpt_paint/paint_cursor.c2
-rw-r--r--source/blender/editors/sculpt_paint/paint_image.cc5
-rw-r--r--source/blender/editors/sculpt_paint/paint_image_proj.c5
-rw-r--r--source/blender/editors/sculpt_paint/paint_vertex.c2
-rw-r--r--source/blender/editors/sculpt_paint/sculpt.c2
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_ops.c4
-rw-r--r--source/blender/editors/space_buttons/buttons_ops.c8
-rw-r--r--source/blender/editors/space_file/fsmenu.c14
-rw-r--r--source/blender/editors/space_node/drawnode.cc48
-rw-r--r--source/blender/editors/space_node/node_draw.cc23
-rw-r--r--source/blender/editors/space_node/node_geometry_attribute_search.cc161
-rw-r--r--source/blender/editors/space_node/node_group.cc12
-rw-r--r--source/blender/editors/space_node/node_intern.hh1
-rw-r--r--source/blender/editors/space_node/node_templates.cc2
-rw-r--r--source/blender/editors/space_outliner/CMakeLists.txt3
-rw-r--r--source/blender/editors/space_outliner/outliner_collections.cc15
-rw-r--r--source/blender/editors/space_outliner/outliner_dragdrop.cc15
-rw-r--r--source/blender/editors/space_outliner/outliner_draw.cc19
-rw-r--r--source/blender/editors/space_outliner/outliner_edit.cc1
-rw-r--r--source/blender/editors/space_outliner/outliner_select.cc5
-rw-r--r--source/blender/editors/space_outliner/outliner_tools.cc261
-rw-r--r--source/blender/editors/space_outliner/outliner_tree.cc3
-rw-r--r--source/blender/editors/space_outliner/outliner_utils.cc3
-rw-r--r--source/blender/editors/space_outliner/tree/tree_display.cc8
-rw-r--r--source/blender/editors/space_outliner/tree/tree_display.hh24
-rw-r--r--source/blender/editors/space_outliner/tree/tree_display_override_library_hierarchies.cc224
-rw-r--r--source/blender/editors/space_outliner/tree/tree_display_override_library_properties.cc (renamed from source/blender/editors/space_outliner/tree/tree_display_override_library.cc)12
-rw-r--r--source/blender/editors/space_outliner/tree/tree_element.cc7
-rw-r--r--source/blender/editors/space_outliner/tree/tree_element.hh13
-rw-r--r--source/blender/editors/space_outliner/tree/tree_element_id.hh5
-rw-r--r--source/blender/editors/space_sequencer/sequencer_edit.c39
-rw-r--r--source/blender/editors/space_spreadsheet/spreadsheet_data_source_geometry.cc1
-rw-r--r--source/blender/editors/space_text/text_ops.c28
-rw-r--r--source/blender/editors/space_view3d/space_view3d.c84
-rw-r--r--source/blender/editors/space_view3d/view3d_cursor_snap.c5
-rw-r--r--source/blender/editors/space_view3d/view3d_gizmo_camera.c5
-rw-r--r--source/blender/editors/space_view3d/view3d_navigate_fly.c9
-rw-r--r--source/blender/editors/space_view3d/view3d_navigate_walk.c8
-rw-r--r--source/blender/editors/space_view3d/view3d_select.c19
-rw-r--r--source/blender/editors/space_view3d/view3d_utils.c7
-rw-r--r--source/blender/editors/space_view3d/view3d_view.c3
-rw-r--r--source/blender/editors/transform/CMakeLists.txt2
-rw-r--r--source/blender/editors/transform/transform.c39
-rw-r--r--source/blender/editors/transform/transform.h5
-rw-r--r--source/blender/editors/transform/transform_constraints.c15
-rw-r--r--source/blender/editors/transform/transform_convert_node.c4
-rw-r--r--source/blender/editors/transform/transform_convert_object.c4
-rw-r--r--source/blender/editors/transform/transform_convert_object_texspace.c2
-rw-r--r--source/blender/editors/transform/transform_convert_sculpt.c5
-rw-r--r--source/blender/editors/transform/transform_generics.c3
-rw-r--r--source/blender/editors/transform/transform_gizmo_3d.c4
-rw-r--r--source/blender/editors/transform/transform_snap.c104
-rw-r--r--source/blender/editors/transform/transform_snap_object.cc (renamed from source/blender/editors/transform/transform_snap_object.c)468
-rw-r--r--source/blender/editors/util/ed_transverts.c2
-rw-r--r--source/blender/editors/util/ed_util.c6
-rw-r--r--source/blender/editors/util/ed_util_ops.cc3
-rw-r--r--source/blender/editors/util/select_utils.c20
-rw-r--r--source/blender/editors/uvedit/CMakeLists.txt3
-rw-r--r--source/blender/editors/uvedit/uvedit_islands.c2
-rw-r--r--source/blender/editors/uvedit/uvedit_parametrizer.h99
-rw-r--r--source/blender/editors/uvedit/uvedit_select.c15
-rw-r--r--source/blender/editors/uvedit/uvedit_unwrap_ops.c108
-rw-r--r--source/blender/freestyle/intern/python/BPy_Convert.cpp8
-rw-r--r--source/blender/functions/FN_multi_function_builder.hh46
-rw-r--r--source/blender/functions/intern/field.cc2
-rw-r--r--source/blender/geometry/CMakeLists.txt3
-rw-r--r--source/blender/geometry/GEO_uv_parametrizer.h134
-rw-r--r--source/blender/geometry/intern/uv_parametrizer.c (renamed from source/blender/editors/uvedit/uvedit_parametrizer.c)83
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencilarray.c6
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencilbuild.c378
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencilsmooth.c2
-rw-r--r--source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.c4
-rw-r--r--source/blender/gpu/CMakeLists.txt36
-rw-r--r--source/blender/gpu/GPU_primitive.h6
-rw-r--r--source/blender/gpu/intern/gpu_batch_presets.c6
-rw-r--r--source/blender/gpu/intern/gpu_shader_create_info.cc21
-rw-r--r--source/blender/gpu/intern/gpu_shader_create_info.hh20
-rw-r--r--source/blender/gpu/intern/gpu_viewport.c2
-rw-r--r--source/blender/gpu/metal/mtl_backend.mm2
-rw-r--r--source/blender/gpu/opengl/gl_backend.cc15
-rw-r--r--source/blender/gpu/opengl/gl_shader.cc19
-rw-r--r--source/blender/gpu/opengl/gl_shader_log.cc3
-rw-r--r--source/blender/gpu/shaders/gpu_shader_2D_image_rect_vert.glsl26
-rw-r--r--source/blender/gpu/shaders/gpu_shader_cfg_world_clip_lib.glsl14
-rw-r--r--source/blender/gpu/shaders/gpu_shader_colorspace_lib.glsl8
-rw-r--r--source/blender/gpu/shaders/gpu_shader_point_varying_color_frag.glsl4
-rw-r--r--source/blender/gpu/shaders/opengl/glsl_shader_defines.glsl10
-rw-r--r--source/blender/io/alembic/exporter/abc_writer_abstract.cc2
-rw-r--r--source/blender/io/alembic/exporter/abc_writer_curves.cc3
-rw-r--r--source/blender/io/gpencil/intern/gpencil_io_export_pdf.cc2
-rw-r--r--source/blender/io/gpencil/intern/gpencil_io_export_svg.cc2
-rw-r--r--source/blender/io/usd/intern/usd_writer_material.cc8
-rw-r--r--source/blender/io/wavefront_obj/CMakeLists.txt1
-rw-r--r--source/blender/io/wavefront_obj/exporter/obj_export_file_writer.cc15
-rw-r--r--source/blender/io/wavefront_obj/exporter/obj_export_io.hh146
-rw-r--r--source/blender/io/wavefront_obj/exporter/obj_export_mtl.cc15
-rw-r--r--source/blender/io/wavefront_obj/tests/obj_exporter_tests.cc15
-rw-r--r--source/blender/makesdna/DNA_ID.h5
-rw-r--r--source/blender/makesdna/DNA_brush_types.h2
-rw-r--r--source/blender/makesdna/DNA_defs.h31
-rw-r--r--source/blender/makesdna/DNA_gpencil_modifier_types.h16
-rw-r--r--source/blender/makesdna/DNA_gpencil_types.h28
-rw-r--r--source/blender/makesdna/DNA_layer_types.h19
-rw-r--r--source/blender/makesdna/DNA_modifier_defaults.h20
-rw-r--r--source/blender/makesdna/DNA_modifier_types.h22
-rw-r--r--source/blender/makesdna/DNA_node_types.h2
-rw-r--r--source/blender/makesdna/DNA_object_types.h9
-rw-r--r--source/blender/makesdna/DNA_scene_types.h9
-rw-r--r--source/blender/makesdna/DNA_screen_types.h2
-rw-r--r--source/blender/makesdna/DNA_space_types.h20
-rw-r--r--source/blender/makesdna/DNA_world_types.h4
-rw-r--r--source/blender/makesdna/intern/dna_rename_defs.h18
-rw-r--r--source/blender/makesrna/RNA_access.h2
-rw-r--r--source/blender/makesrna/intern/rna_ID.c25
-rw-r--r--source/blender/makesrna/intern/rna_access.c44
-rw-r--r--source/blender/makesrna/intern/rna_access_compare_override.c4
-rw-r--r--source/blender/makesrna/intern/rna_animation.c8
-rw-r--r--source/blender/makesrna/intern/rna_collection.c6
-rw-r--r--source/blender/makesrna/intern/rna_gpencil.c4
-rw-r--r--source/blender/makesrna/intern/rna_gpencil_modifier.c49
-rw-r--r--source/blender/makesrna/intern/rna_internal.h4
-rw-r--r--source/blender/makesrna/intern/rna_main_api.c2
-rw-r--r--source/blender/makesrna/intern/rna_modifier.c24
-rw-r--r--source/blender/makesrna/intern/rna_object.c49
-rw-r--r--source/blender/makesrna/intern/rna_object_api.c2
-rw-r--r--source/blender/makesrna/intern/rna_object_force.c33
-rw-r--r--source/blender/makesrna/intern/rna_pose.c5
-rw-r--r--source/blender/makesrna/intern/rna_rna.c28
-rw-r--r--source/blender/makesrna/intern/rna_scene.c106
-rw-r--r--source/blender/makesrna/intern/rna_space.c22
-rw-r--r--source/blender/makesrna/intern/rna_userdef.c4
-rw-r--r--source/blender/makesrna/intern/rna_world.c23
-rw-r--r--source/blender/modifiers/MOD_nodes.h2
-rw-r--r--source/blender/modifiers/intern/MOD_armature.c21
-rw-r--r--source/blender/modifiers/intern/MOD_array.c34
-rw-r--r--source/blender/modifiers/intern/MOD_build.c56
-rw-r--r--source/blender/modifiers/intern/MOD_cast.c35
-rw-r--r--source/blender/modifiers/intern/MOD_cloth.c10
-rw-r--r--source/blender/modifiers/intern/MOD_collision.c14
-rw-r--r--source/blender/modifiers/intern/MOD_correctivesmooth.c111
-rw-r--r--source/blender/modifiers/intern/MOD_curve.c14
-rw-r--r--source/blender/modifiers/intern/MOD_displace.c29
-rw-r--r--source/blender/modifiers/intern/MOD_dynamicpaint.c4
-rw-r--r--source/blender/modifiers/intern/MOD_explode.c57
-rw-r--r--source/blender/modifiers/intern/MOD_fluid.c4
-rw-r--r--source/blender/modifiers/intern/MOD_hook.c47
-rw-r--r--source/blender/modifiers/intern/MOD_laplaciandeform.c167
-rw-r--r--source/blender/modifiers/intern/MOD_laplaciansmooth.c143
-rw-r--r--source/blender/modifiers/intern/MOD_lattice.c12
-rw-r--r--source/blender/modifiers/intern/MOD_mask.cc167
-rw-r--r--source/blender/modifiers/intern/MOD_meshcache.c43
-rw-r--r--source/blender/modifiers/intern/MOD_meshcache_mdd.c18
-rw-r--r--source/blender/modifiers/intern/MOD_meshcache_pc2.c8
-rw-r--r--source/blender/modifiers/intern/MOD_meshdeform.c102
-rw-r--r--source/blender/modifiers/intern/MOD_meshsequencecache.cc10
-rw-r--r--source/blender/modifiers/intern/MOD_multires.c4
-rw-r--r--source/blender/modifiers/intern/MOD_nodes.cc32
-rw-r--r--source/blender/modifiers/intern/MOD_nodes_evaluator.cc4
-rw-r--r--source/blender/modifiers/intern/MOD_normal_edit.c122
-rw-r--r--source/blender/modifiers/intern/MOD_ocean.c26
-rw-r--r--source/blender/modifiers/intern/MOD_particlesystem.c9
-rw-r--r--source/blender/modifiers/intern/MOD_shapekey.c22
-rw-r--r--source/blender/modifiers/intern/MOD_shrinkwrap.c13
-rw-r--r--source/blender/modifiers/intern/MOD_simpledeform.c19
-rw-r--r--source/blender/modifiers/intern/MOD_skin.c137
-rw-r--r--source/blender/modifiers/intern/MOD_smooth.c48
-rw-r--r--source/blender/modifiers/intern/MOD_softbody.c8
-rw-r--r--source/blender/modifiers/intern/MOD_solidify_extrude.c249
-rw-r--r--source/blender/modifiers/intern/MOD_solidify_nonmanifold.c178
-rw-r--r--source/blender/modifiers/intern/MOD_subsurf.c4
-rw-r--r--source/blender/modifiers/intern/MOD_surface.c24
-rw-r--r--source/blender/modifiers/intern/MOD_surfacedeform.c204
-rw-r--r--source/blender/modifiers/intern/MOD_triangulate.c6
-rw-r--r--source/blender/modifiers/intern/MOD_util.c16
-rw-r--r--source/blender/modifiers/intern/MOD_util.h2
-rw-r--r--source/blender/modifiers/intern/MOD_uvproject.c36
-rw-r--r--source/blender/modifiers/intern/MOD_uvwarp.c12
-rw-r--r--source/blender/modifiers/intern/MOD_volume_displace.cc4
-rw-r--r--source/blender/modifiers/intern/MOD_warp.c22
-rw-r--r--source/blender/modifiers/intern/MOD_wave.c28
-rw-r--r--source/blender/modifiers/intern/MOD_weighted_normal.c162
-rw-r--r--source/blender/modifiers/intern/MOD_weightvg_util.c4
-rw-r--r--source/blender/modifiers/intern/MOD_weightvgedit.c26
-rw-r--r--source/blender/modifiers/intern/MOD_weightvgmix.c101
-rw-r--r--source/blender/modifiers/intern/MOD_weightvgproximity.c85
-rw-r--r--source/blender/nodes/NOD_geometry_exec.hh1
-rw-r--r--source/blender/nodes/NOD_geometry_nodes_eval_log.hh4
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_cryptomatte.cc8
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_normal.cc8
-rw-r--r--source/blender/nodes/geometry/node_geometry_util.hh10
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_convex_hull.cc24
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_curve_fillet.cc4
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_curve_length.cc16
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_curve_resample.cc715
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_curve_set_handle_type.cc98
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_curve_spline_parameter.cc229
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_delete_geometry.cc300
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_extrude_mesh.cc4
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_input_spline_length.cc88
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_raycast.cc2
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_set_curve_handles.cc183
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_set_position.cc8
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_transfer_attribute.cc4
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_transform.cc4
-rw-r--r--source/blender/nodes/intern/geometry_nodes_eval_log.cc10
-rw-r--r--source/blender/python/bmesh/bmesh_py_ops_call.c4
-rw-r--r--source/blender/python/bmesh/bmesh_py_types.c2
-rw-r--r--source/blender/python/gpu/gpu_py_shader.c4
-rw-r--r--source/blender/python/intern/bpy_app_handlers.c10
-rw-r--r--source/blender/python/intern/bpy_interface_run.c73
-rw-r--r--source/blender/python/intern/bpy_rna_array.c8
-rw-r--r--source/blender/python/intern/bpy_traceback.c109
-rw-r--r--source/blender/python/intern/bpy_traceback.h3
-rw-r--r--source/blender/python/mathutils/mathutils.c122
-rw-r--r--source/blender/python/mathutils/mathutils.h4
-rw-r--r--source/blender/python/mathutils/mathutils_Matrix.c396
-rw-r--r--source/blender/python/mathutils/mathutils_Matrix.h24
-rw-r--r--source/blender/python/mathutils/mathutils_Quaternion.c2
-rw-r--r--source/blender/python/mathutils/mathutils_Vector.c428
-rw-r--r--source/blender/python/mathutils/mathutils_Vector.h11
-rw-r--r--source/blender/python/mathutils/mathutils_geometry.c39
-rw-r--r--source/blender/python/mathutils/mathutils_noise.c25
-rw-r--r--source/blender/render/RE_bake.h20
-rw-r--r--source/blender/render/intern/bake.c36
-rw-r--r--source/blender/render/intern/engine.c6
-rw-r--r--source/blender/render/intern/multires_bake.c12
-rw-r--r--source/blender/render/intern/render_result.c2
-rw-r--r--source/blender/render/intern/texture_pointdensity.c2
-rw-r--r--source/blender/sequencer/SEQ_animation.h12
-rw-r--r--source/blender/sequencer/intern/animation.c29
-rw-r--r--source/blender/sequencer/intern/effects.c4
-rw-r--r--source/blender/sequencer/intern/strip_edit.c11
-rw-r--r--source/blender/windowmanager/WM_api.h37
-rw-r--r--source/blender/windowmanager/gizmo/intern/wm_gizmo_group.c7
-rw-r--r--source/blender/windowmanager/intern/wm_event_system.c22
-rw-r--r--source/blender/windowmanager/intern/wm_files.c2
-rw-r--r--source/blender/windowmanager/intern/wm_operator_props.c12
-rw-r--r--source/blender/windowmanager/intern/wm_operators.c15
-rw-r--r--tests/python/cycles_render_tests.py7
665 files changed, 23362 insertions, 7602 deletions
diff --git a/build_files/build_environment/install_deps.sh b/build_files/build_environment/install_deps.sh
index 41c6fa495d8..a9a9e4f4ca0 100755
--- a/build_files/build_environment/install_deps.sh
+++ b/build_files/build_environment/install_deps.sh
@@ -432,8 +432,8 @@ PYTHON_MODULES_PIP=(
)
-BOOST_VERSION="1.73.0"
-BOOST_VERSION_SHORT="1.73"
+BOOST_VERSION="1.78.0"
+BOOST_VERSION_SHORT="1.78"
BOOST_VERSION_MIN="1.49"
BOOST_VERSION_MEX="2.0"
BOOST_FORCE_BUILD=false
@@ -442,15 +442,15 @@ BOOST_SKIP=false
TBB_VERSION="2020"
TBB_VERSION_SHORT="2020"
-TBB_VERSION_UPDATE="_U2" # Used for source packages...
+TBB_VERSION_UPDATE="_U3" # Used for source packages...
TBB_VERSION_MIN="2018"
TBB_VERSION_MEX="2022"
TBB_FORCE_BUILD=false
TBB_FORCE_REBUILD=false
TBB_SKIP=false
-OCIO_VERSION="2.0.0"
-OCIO_VERSION_SHORT="2.0"
+OCIO_VERSION="2.1.1"
+OCIO_VERSION_SHORT="2.1"
OCIO_VERSION_MIN="2.0"
OCIO_VERSION_MEX="3.0"
OCIO_FORCE_BUILD=false
@@ -466,10 +466,10 @@ OPENEXR_FORCE_REBUILD=false
OPENEXR_SKIP=false
_with_built_openexr=false
-OIIO_VERSION="2.2.15.1"
-OIIO_VERSION_SHORT="2.2"
+OIIO_VERSION="2.3.13.0"
+OIIO_VERSION_SHORT="2.3"
OIIO_VERSION_MIN="2.1.12"
-OIIO_VERSION_MEX="2.3.0"
+OIIO_VERSION_MEX="2.4.0"
OIIO_FORCE_BUILD=false
OIIO_FORCE_REBUILD=false
OIIO_SKIP=false
@@ -493,7 +493,7 @@ OSL_FORCE_REBUILD=false
OSL_SKIP=false
# OpenSubdiv needs to be compiled for now
-OSD_VERSION="3.4.3"
+OSD_VERSION="3.4.4"
OSD_VERSION_SHORT="3.4"
OSD_VERSION_MIN="3.4"
OSD_VERSION_MEX="4.0"
@@ -502,19 +502,19 @@ OSD_FORCE_REBUILD=false
OSD_SKIP=false
# OpenVDB needs to be compiled for now
-OPENVDB_BLOSC_VERSION="1.5.0"
+OPENVDB_BLOSC_VERSION="1.21.1"
-OPENVDB_VERSION="8.0.1"
-OPENVDB_VERSION_SHORT="8.0"
-OPENVDB_VERSION_MIN="8.0"
-OPENVDB_VERSION_MEX="8.1"
+OPENVDB_VERSION="9.0.0"
+OPENVDB_VERSION_SHORT="9.0"
+OPENVDB_VERSION_MIN="9.0"
+OPENVDB_VERSION_MEX="9.1"
OPENVDB_FORCE_BUILD=false
OPENVDB_FORCE_REBUILD=false
OPENVDB_SKIP=false
# Alembic needs to be compiled for now
-ALEMBIC_VERSION="1.7.16"
-ALEMBIC_VERSION_SHORT="1.7"
+ALEMBIC_VERSION="1.8.3"
+ALEMBIC_VERSION_SHORT="1.8"
ALEMBIC_VERSION_MIN="1.7"
ALEMBIC_VERSION_MEX="2.0"
ALEMBIC_FORCE_BUILD=false
@@ -537,15 +537,15 @@ OPENCOLLADA_FORCE_BUILD=false
OPENCOLLADA_FORCE_REBUILD=false
OPENCOLLADA_SKIP=false
-EMBREE_VERSION="3.10.0"
-EMBREE_VERSION_SHORT="3.10"
-EMBREE_VERSION_MIN="3.10"
+EMBREE_VERSION="3.13.3"
+EMBREE_VERSION_SHORT="3.13"
+EMBREE_VERSION_MIN="3.13"
EMBREE_VERSION_MEX="4.0"
EMBREE_FORCE_BUILD=false
EMBREE_FORCE_REBUILD=false
EMBREE_SKIP=false
-OIDN_VERSION="1.4.1"
+OIDN_VERSION="1.4.3"
OIDN_VERSION_SHORT="1.4"
OIDN_VERSION_MIN="1.4.0"
OIDN_VERSION_MEX="1.5"
@@ -553,7 +553,7 @@ OIDN_FORCE_BUILD=false
OIDN_FORCE_REBUILD=false
OIDN_SKIP=false
-ISPC_VERSION="1.16.0"
+ISPC_VERSION="1.17.0"
FFMPEG_VERSION="4.4"
FFMPEG_VERSION_SHORT="4.4"
@@ -1029,7 +1029,7 @@ OPENEXR_SOURCE_REPO_UID="0ac2ea34c8f3134148a5df4052e40f155b76f6fb"
#~ OPENEXR_SOURCE=( "https://github.com/openexr/openexr/archive/$OPENEXR_SOURCE_REPO_UID.tar.gz" )
OIIO_USE_REPO=false
-OIIO_SOURCE=( "https://github.com/OpenImageIO/oiio/archive/Release-$OIIO_VERSION.tar.gz" )
+OIIO_SOURCE=( "https://github.com/OpenImageIO/oiio/archive/refs/tags/v$OIIO_VERSION.tar.gz" )
#~ OIIO_SOURCE_REPO=( "https://github.com/OpenImageIO/oiio.git" )
#~ OIIO_SOURCE_REPO_UID="c9e67275a0b248ead96152f6d2221cc0c0f278a4"
@@ -2034,7 +2034,7 @@ compile_OIIO() {
else
download OIIO_SOURCE[@] "$_src.tar.gz"
INFO "Unpacking OpenImageIO-$OIIO_VERSION"
- tar -C $SRC --transform "s,(.*/?)oiio-Release-[^/]*(.*),\1OpenImageIO-$OIIO_VERSION\2,x" -xf $_src.tar.gz
+ tar -C $SRC --transform "s,(.*/?)oiio-[^/]*(.*),\1OpenImageIO-$OIIO_VERSION\2,x" -xf $_src.tar.gz
fi
fi
diff --git a/doc/python_api/examples/bpy.types.UIList.1.py b/doc/python_api/examples/bpy.types.UIList.1.py
index a8b1cfa85a5..2b2a0d90c3b 100644
--- a/doc/python_api/examples/bpy.types.UIList.1.py
+++ b/doc/python_api/examples/bpy.types.UIList.1.py
@@ -41,7 +41,7 @@ class MATERIAL_UL_matslots_example(bpy.types.UIList):
else:
layout.label(text="", translate=False, icon_value=icon)
# 'GRID' layout type should be as compact as possible (typically a single icon!).
- elif self.layout_type in {'GRID'}:
+ elif self.layout_type == 'GRID':
layout.alignment = 'CENTER'
layout.label(text="", icon_value=icon)
diff --git a/doc/python_api/examples/bpy.types.UIList.2.py b/doc/python_api/examples/bpy.types.UIList.2.py
index 5f3ecbf116c..05c9e9b3a17 100644
--- a/doc/python_api/examples/bpy.types.UIList.2.py
+++ b/doc/python_api/examples/bpy.types.UIList.2.py
@@ -73,7 +73,7 @@ class MESH_UL_vgroups_slow(bpy.types.UIList):
layout.prop(vgroup, "name", text="", emboss=False, icon_value=icon)
icon = 'LOCKED' if vgroup.lock_weight else 'UNLOCKED'
layout.prop(vgroup, "lock_weight", text="", icon=icon, emboss=False)
- elif self.layout_type in {'GRID'}:
+ elif self.layout_type == 'GRID':
layout.alignment = 'CENTER'
if flt_flag & self.VGROUP_EMPTY:
layout.enabled = False
diff --git a/extern/fmtlib/LICENSE.rst b/extern/fmtlib/LICENSE.rst
new file mode 100644
index 00000000000..f0ec3db4d2a
--- /dev/null
+++ b/extern/fmtlib/LICENSE.rst
@@ -0,0 +1,27 @@
+Copyright (c) 2012 - present, Victor Zverovich
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+--- Optional exception to the license ---
+
+As an exception, if, as a result of your compiling your source code, portions
+of this Software are embedded into a machine-executable object form of such
+source code, you may redistribute such embedded portions in such object form
+without including the above copyright and permission notices.
diff --git a/extern/fmtlib/README.blender b/extern/fmtlib/README.blender
new file mode 100644
index 00000000000..98c5684305e
--- /dev/null
+++ b/extern/fmtlib/README.blender
@@ -0,0 +1,8 @@
+Project: {fmt}
+URL: https://github.com/fmtlib/fmt
+License: MIT
+Upstream version: 8.1.1 (b6f4cea)
+Local modifications:
+
+- Took only files needed for Blender: LICENSE, README and include/fmt
+ folder's core.h, format-inl.h, format.h
diff --git a/extern/fmtlib/README.rst b/extern/fmtlib/README.rst
new file mode 100644
index 00000000000..394f28d97bb
--- /dev/null
+++ b/extern/fmtlib/README.rst
@@ -0,0 +1,528 @@
+{fmt}
+=====
+
+.. image:: https://github.com/fmtlib/fmt/workflows/linux/badge.svg
+ :target: https://github.com/fmtlib/fmt/actions?query=workflow%3Alinux
+
+.. image:: https://github.com/fmtlib/fmt/workflows/macos/badge.svg
+ :target: https://github.com/fmtlib/fmt/actions?query=workflow%3Amacos
+
+.. image:: https://github.com/fmtlib/fmt/workflows/windows/badge.svg
+ :target: https://github.com/fmtlib/fmt/actions?query=workflow%3Awindows
+
+.. image:: https://ci.appveyor.com/api/projects/status/ehjkiefde6gucy1v?svg=true
+ :target: https://ci.appveyor.com/project/vitaut/fmt
+
+.. image:: https://oss-fuzz-build-logs.storage.googleapis.com/badges/fmt.svg
+ :alt: fmt is continuously fuzzed at oss-fuzz
+ :target: https://bugs.chromium.org/p/oss-fuzz/issues/list?\
+ colspec=ID%20Type%20Component%20Status%20Proj%20Reported%20Owner%20\
+ Summary&q=proj%3Dfmt&can=1
+
+.. image:: https://img.shields.io/badge/stackoverflow-fmt-blue.svg
+ :alt: Ask questions at StackOverflow with the tag fmt
+ :target: https://stackoverflow.com/questions/tagged/fmt
+
+**{fmt}** is an open-source formatting library providing a fast and safe
+alternative to C stdio and C++ iostreams.
+
+If you like this project, please consider donating to the BYSOL
+Foundation that helps victims of political repressions in Belarus:
+https://bysol.org/en/bs/general/.
+
+`Documentation <https://fmt.dev>`__
+
+Q&A: ask questions on `StackOverflow with the tag fmt
+<https://stackoverflow.com/questions/tagged/fmt>`_.
+
+Try {fmt} in `Compiler Explorer <https://godbolt.org/z/Eq5763>`_.
+
+Features
+--------
+
+* Simple `format API <https://fmt.dev/latest/api.html>`_ with positional arguments
+ for localization
+* Implementation of `C++20 std::format
+ <https://en.cppreference.com/w/cpp/utility/format>`__
+* `Format string syntax <https://fmt.dev/latest/syntax.html>`_ similar to Python's
+ `format <https://docs.python.org/3/library/stdtypes.html#str.format>`_
+* Fast IEEE 754 floating-point formatter with correct rounding, shortness and
+ round-trip guarantees
+* Safe `printf implementation
+ <https://fmt.dev/latest/api.html#printf-formatting>`_ including the POSIX
+ extension for positional arguments
+* Extensibility: `support for user-defined types
+ <https://fmt.dev/latest/api.html#formatting-user-defined-types>`_
+* High performance: faster than common standard library implementations of
+ ``(s)printf``, iostreams, ``to_string`` and ``to_chars``, see `Speed tests`_
+ and `Converting a hundred million integers to strings per second
+ <http://www.zverovich.net/2020/06/13/fast-int-to-string-revisited.html>`_
+* Small code size both in terms of source code with the minimum configuration
+ consisting of just three files, ``core.h``, ``format.h`` and ``format-inl.h``,
+ and compiled code; see `Compile time and code bloat`_
+* Reliability: the library has an extensive set of `tests
+ <https://github.com/fmtlib/fmt/tree/master/test>`_ and is `continuously fuzzed
+ <https://bugs.chromium.org/p/oss-fuzz/issues/list?colspec=ID%20Type%20
+ Component%20Status%20Proj%20Reported%20Owner%20Summary&q=proj%3Dfmt&can=1>`_
+* Safety: the library is fully type safe, errors in format strings can be
+ reported at compile time, automatic memory management prevents buffer overflow
+ errors
+* Ease of use: small self-contained code base, no external dependencies,
+ permissive MIT `license
+ <https://github.com/fmtlib/fmt/blob/master/LICENSE.rst>`_
+* `Portability <https://fmt.dev/latest/index.html#portability>`_ with
+ consistent output across platforms and support for older compilers
+* Clean warning-free codebase even on high warning levels such as
+ ``-Wall -Wextra -pedantic``
+* Locale-independence by default
+* Optional header-only configuration enabled with the ``FMT_HEADER_ONLY`` macro
+
+See the `documentation <https://fmt.dev>`_ for more details.
+
+Examples
+--------
+
+**Print to stdout** (`run <https://godbolt.org/z/Tevcjh>`_)
+
+.. code:: c++
+
+ #include <fmt/core.h>
+
+ int main() {
+ fmt::print("Hello, world!\n");
+ }
+
+**Format a string** (`run <https://godbolt.org/z/oK8h33>`_)
+
+.. code:: c++
+
+ std::string s = fmt::format("The answer is {}.", 42);
+ // s == "The answer is 42."
+
+**Format a string using positional arguments** (`run <https://godbolt.org/z/Yn7Txe>`_)
+
+.. code:: c++
+
+ std::string s = fmt::format("I'd rather be {1} than {0}.", "right", "happy");
+ // s == "I'd rather be happy than right."
+
+**Print chrono durations** (`run <https://godbolt.org/z/K8s4Mc>`_)
+
+.. code:: c++
+
+ #include <fmt/chrono.h>
+
+ int main() {
+ using namespace std::literals::chrono_literals;
+ fmt::print("Default format: {} {}\n", 42s, 100ms);
+ fmt::print("strftime-like format: {:%H:%M:%S}\n", 3h + 15min + 30s);
+ }
+
+Output::
+
+ Default format: 42s 100ms
+ strftime-like format: 03:15:30
+
+**Print a container** (`run <https://godbolt.org/z/MjsY7c>`_)
+
+.. code:: c++
+
+ #include <vector>
+ #include <fmt/ranges.h>
+
+ int main() {
+ std::vector<int> v = {1, 2, 3};
+ fmt::print("{}\n", v);
+ }
+
+Output::
+
+ [1, 2, 3]
+
+**Check a format string at compile time**
+
+.. code:: c++
+
+ std::string s = fmt::format("{:d}", "I am not a number");
+
+This gives a compile-time error in C++20 because ``d`` is an invalid format
+specifier for a string.
+
+**Write a file from a single thread**
+
+.. code:: c++
+
+ #include <fmt/os.h>
+
+ int main() {
+ auto out = fmt::output_file("guide.txt");
+ out.print("Don't {}", "Panic");
+ }
+
+This can be `5 to 9 times faster than fprintf
+<http://www.zverovich.net/2020/08/04/optimal-file-buffer-size.html>`_.
+
+**Print with colors and text styles**
+
+.. code:: c++
+
+ #include <fmt/color.h>
+
+ int main() {
+ fmt::print(fg(fmt::color::crimson) | fmt::emphasis::bold,
+ "Hello, {}!\n", "world");
+ fmt::print(fg(fmt::color::floral_white) | bg(fmt::color::slate_gray) |
+ fmt::emphasis::underline, "Hello, {}!\n", "мир");
+ fmt::print(fg(fmt::color::steel_blue) | fmt::emphasis::italic,
+ "Hello, {}!\n", "世界");
+ }
+
+Output on a modern terminal:
+
+.. image:: https://user-images.githubusercontent.com/
+ 576385/88485597-d312f600-cf2b-11ea-9cbe-61f535a86e28.png
+
+Benchmarks
+----------
+
+Speed tests
+~~~~~~~~~~~
+
+================= ============= ===========
+Library Method Run Time, s
+================= ============= ===========
+libc printf 1.04
+libc++ std::ostream 3.05
+{fmt} 6.1.1 fmt::print 0.75
+Boost Format 1.67 boost::format 7.24
+Folly Format folly::format 2.23
+================= ============= ===========
+
+{fmt} is the fastest of the benchmarked methods, ~35% faster than ``printf``.
+
+The above results were generated by building ``tinyformat_test.cpp`` on macOS
+10.14.6 with ``clang++ -O3 -DNDEBUG -DSPEED_TEST -DHAVE_FORMAT``, and taking the
+best of three runs. In the test, the format string ``"%0.10f:%04d:%+g:%s:%p:%c:%%\n"``
+or equivalent is filled 2,000,000 times with output sent to ``/dev/null``; for
+further details refer to the `source
+<https://github.com/fmtlib/format-benchmark/blob/master/src/tinyformat-test.cc>`_.
+
+{fmt} is up to 20-30x faster than ``std::ostringstream`` and ``sprintf`` on
+floating-point formatting (`dtoa-benchmark <https://github.com/fmtlib/dtoa-benchmark>`_)
+and faster than `double-conversion <https://github.com/google/double-conversion>`_ and
+`ryu <https://github.com/ulfjack/ryu>`_:
+
+.. image:: https://user-images.githubusercontent.com/576385/
+ 95684665-11719600-0ba8-11eb-8e5b-972ff4e49428.png
+ :target: https://fmt.dev/unknown_mac64_clang12.0.html
+
+Compile time and code bloat
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The script `bloat-test.py
+<https://github.com/fmtlib/format-benchmark/blob/master/bloat-test.py>`_
+from `format-benchmark <https://github.com/fmtlib/format-benchmark>`_
+tests compile time and code bloat for nontrivial projects.
+It generates 100 translation units and uses ``printf()`` or its alternative
+five times in each to simulate a medium sized project. The resulting
+executable size and compile time (Apple LLVM version 8.1.0 (clang-802.0.42),
+macOS Sierra, best of three) is shown in the following tables.
+
+**Optimized build (-O3)**
+
+============= =============== ==================== ==================
+Method Compile Time, s Executable size, KiB Stripped size, KiB
+============= =============== ==================== ==================
+printf 2.6 29 26
+printf+string 16.4 29 26
+iostreams 31.1 59 55
+{fmt} 19.0 37 34
+Boost Format 91.9 226 203
+Folly Format 115.7 101 88
+============= =============== ==================== ==================
+
+As you can see, {fmt} has 60% less overhead in terms of resulting binary code
+size compared to iostreams and comes pretty close to ``printf``. Boost Format
+and Folly Format have the largest overheads.
+
+``printf+string`` is the same as ``printf`` but with extra ``<string>``
+include to measure the overhead of the latter.
+
+**Non-optimized build**
+
+============= =============== ==================== ==================
+Method Compile Time, s Executable size, KiB Stripped size, KiB
+============= =============== ==================== ==================
+printf 2.2 33 30
+printf+string 16.0 33 30
+iostreams 28.3 56 52
+{fmt} 18.2 59 50
+Boost Format 54.1 365 303
+Folly Format 79.9 445 430
+============= =============== ==================== ==================
+
+``libc``, ``lib(std)c++`` and ``libfmt`` are all linked as shared libraries to
+compare formatting function overhead only. Boost Format is a
+header-only library so it doesn't provide any linkage options.
+
+Running the tests
+~~~~~~~~~~~~~~~~~
+
+Please refer to `Building the library`__ for the instructions on how to build
+the library and run the unit tests.
+
+__ https://fmt.dev/latest/usage.html#building-the-library
+
+Benchmarks reside in a separate repository,
+`format-benchmarks <https://github.com/fmtlib/format-benchmark>`_,
+so to run the benchmarks you first need to clone this repository and
+generate Makefiles with CMake::
+
+ $ git clone --recursive https://github.com/fmtlib/format-benchmark.git
+ $ cd format-benchmark
+ $ cmake .
+
+Then you can run the speed test::
+
+ $ make speed-test
+
+or the bloat test::
+
+ $ make bloat-test
+
+Migrating code
+--------------
+
+`clang-tidy-fmt <https://github.com/mikecrowe/clang-tidy-fmt>`_ provides clang
+tidy checks for converting occurrences of ``printf`` and ``fprintf`` to
+``fmt::print``.
+
+Projects using this library
+---------------------------
+
+* `0 A.D. <https://play0ad.com/>`_: a free, open-source, cross-platform
+ real-time strategy game
+
+* `2GIS <https://2gis.ru/>`_: free business listings with a city map
+
+* `AMPL/MP <https://github.com/ampl/mp>`_:
+ an open-source library for mathematical programming
+
+* `Aseprite <https://github.com/aseprite/aseprite>`_:
+ animated sprite editor & pixel art tool
+
+* `AvioBook <https://www.aviobook.aero/en>`_: a comprehensive aircraft
+ operations suite
+
+* `Blizzard Battle.net <https://battle.net/>`_: an online gaming platform
+
+* `Celestia <https://celestia.space/>`_: real-time 3D visualization of space
+
+* `Ceph <https://ceph.com/>`_: a scalable distributed storage system
+
+* `ccache <https://ccache.dev/>`_: a compiler cache
+
+* `ClickHouse <https://github.com/ClickHouse/ClickHouse>`_: analytical database
+ management system
+
+* `CUAUV <https://cuauv.org/>`_: Cornell University's autonomous underwater
+ vehicle
+
+* `Drake <https://drake.mit.edu/>`_: a planning, control, and analysis toolbox
+ for nonlinear dynamical systems (MIT)
+
+* `Envoy <https://lyft.github.io/envoy/>`_: C++ L7 proxy and communication bus
+ (Lyft)
+
+* `FiveM <https://fivem.net/>`_: a modification framework for GTA V
+
+* `fmtlog <https://github.com/MengRao/fmtlog>`_: a performant fmtlib-style
+ logging library with latency in nanoseconds
+
+* `Folly <https://github.com/facebook/folly>`_: Facebook open-source library
+
+* `Grand Mountain Adventure
+ <https://store.steampowered.com/app/1247360/Grand_Mountain_Adventure/>`_:
+ A beautiful open-world ski & snowboarding game
+
+* `HarpyWar/pvpgn <https://github.com/pvpgn/pvpgn-server>`_:
+ Player vs Player Gaming Network with tweaks
+
+* `KBEngine <https://github.com/kbengine/kbengine>`_: an open-source MMOG server
+ engine
+
+* `Keypirinha <https://keypirinha.com/>`_: a semantic launcher for Windows
+
+* `Kodi <https://kodi.tv/>`_ (formerly xbmc): home theater software
+
+* `Knuth <https://kth.cash/>`_: high-performance Bitcoin full-node
+
+* `Microsoft Verona <https://github.com/microsoft/verona>`_:
+ research programming language for concurrent ownership
+
+* `MongoDB <https://mongodb.com/>`_: distributed document database
+
+* `MongoDB Smasher <https://github.com/duckie/mongo_smasher>`_: a small tool to
+ generate randomized datasets
+
+* `OpenSpace <https://openspaceproject.com/>`_: an open-source
+ astrovisualization framework
+
+* `PenUltima Online (POL) <https://www.polserver.com/>`_:
+ an MMO server, compatible with most Ultima Online clients
+
+* `PyTorch <https://github.com/pytorch/pytorch>`_: an open-source machine
+ learning library
+
+* `quasardb <https://www.quasardb.net/>`_: a distributed, high-performance,
+ associative database
+
+* `Quill <https://github.com/odygrd/quill>`_: asynchronous low-latency logging library
+
+* `QKW <https://github.com/ravijanjam/qkw>`_: generalizing aliasing to simplify
+ navigation, and executing complex multi-line terminal command sequences
+
+* `redis-cerberus <https://github.com/HunanTV/redis-cerberus>`_: a Redis cluster
+ proxy
+
+* `redpanda <https://vectorized.io/redpanda>`_: a 10x faster Kafka® replacement
+ for mission critical systems written in C++
+
+* `rpclib <http://rpclib.net/>`_: a modern C++ msgpack-RPC server and client
+ library
+
+* `Salesforce Analytics Cloud
+ <https://www.salesforce.com/analytics-cloud/overview/>`_:
+ business intelligence software
+
+* `Scylla <https://www.scylladb.com/>`_: a Cassandra-compatible NoSQL data store
+ that can handle 1 million transactions per second on a single server
+
+* `Seastar <http://www.seastar-project.org/>`_: an advanced, open-source C++
+ framework for high-performance server applications on modern hardware
+
+* `spdlog <https://github.com/gabime/spdlog>`_: super fast C++ logging library
+
+* `Stellar <https://www.stellar.org/>`_: financial platform
+
+* `Touch Surgery <https://www.touchsurgery.com/>`_: surgery simulator
+
+* `TrinityCore <https://github.com/TrinityCore/TrinityCore>`_: open-source
+ MMORPG framework
+
+* `Windows Terminal <https://github.com/microsoft/terminal>`_: the new Windows
+ terminal
+
+`More... <https://github.com/search?q=fmtlib&type=Code>`_
+
+If you are aware of other projects using this library, please let me know
+by `email <mailto:victor.zverovich@gmail.com>`_ or by submitting an
+`issue <https://github.com/fmtlib/fmt/issues>`_.
+
+Motivation
+----------
+
+So why yet another formatting library?
+
+There are plenty of methods for doing this task, from standard ones like
+the printf family of function and iostreams to Boost Format and FastFormat
+libraries. The reason for creating a new library is that every existing
+solution that I found either had serious issues or didn't provide
+all the features I needed.
+
+printf
+~~~~~~
+
+The good thing about ``printf`` is that it is pretty fast and readily available
+being a part of the C standard library. The main drawback is that it
+doesn't support user-defined types. ``printf`` also has safety issues although
+they are somewhat mitigated with `__attribute__ ((format (printf, ...))
+<https://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html>`_ in GCC.
+There is a POSIX extension that adds positional arguments required for
+`i18n <https://en.wikipedia.org/wiki/Internationalization_and_localization>`_
+to ``printf`` but it is not a part of C99 and may not be available on some
+platforms.
+
+iostreams
+~~~~~~~~~
+
+The main issue with iostreams is best illustrated with an example:
+
+.. code:: c++
+
+ std::cout << std::setprecision(2) << std::fixed << 1.23456 << "\n";
+
+which is a lot of typing compared to printf:
+
+.. code:: c++
+
+ printf("%.2f\n", 1.23456);
+
+Matthew Wilson, the author of FastFormat, called this "chevron hell". iostreams
+don't support positional arguments by design.
+
+The good part is that iostreams support user-defined types and are safe although
+error handling is awkward.
+
+Boost Format
+~~~~~~~~~~~~
+
+This is a very powerful library which supports both ``printf``-like format
+strings and positional arguments. Its main drawback is performance. According to
+various benchmarks, it is much slower than other methods considered here. Boost
+Format also has excessive build times and severe code bloat issues (see
+`Benchmarks`_).
+
+FastFormat
+~~~~~~~~~~
+
+This is an interesting library which is fast, safe and has positional arguments.
+However, it has significant limitations, citing its author:
+
+ Three features that have no hope of being accommodated within the
+ current design are:
+
+ * Leading zeros (or any other non-space padding)
+ * Octal/hexadecimal encoding
+ * Runtime width/alignment specification
+
+It is also quite big and has a heavy dependency, STLSoft, which might be too
+restrictive for using it in some projects.
+
+Boost Spirit.Karma
+~~~~~~~~~~~~~~~~~~
+
+This is not really a formatting library but I decided to include it here for
+completeness. As iostreams, it suffers from the problem of mixing verbatim text
+with arguments. The library is pretty fast, but slower on integer formatting
+than ``fmt::format_to`` with format string compilation on Karma's own benchmark,
+see `Converting a hundred million integers to strings per second
+<http://www.zverovich.net/2020/06/13/fast-int-to-string-revisited.html>`_.
+
+License
+-------
+
+{fmt} is distributed under the MIT `license
+<https://github.com/fmtlib/fmt/blob/master/LICENSE.rst>`_.
+
+Documentation License
+---------------------
+
+The `Format String Syntax <https://fmt.dev/latest/syntax.html>`_
+section in the documentation is based on the one from Python `string module
+documentation <https://docs.python.org/3/library/string.html#module-string>`_.
+For this reason the documentation is distributed under the Python Software
+Foundation license available in `doc/python-license.txt
+<https://raw.github.com/fmtlib/fmt/master/doc/python-license.txt>`_.
+It only applies if you distribute the documentation of {fmt}.
+
+Maintainers
+-----------
+
+The {fmt} library is maintained by Victor Zverovich (`vitaut
+<https://github.com/vitaut>`_) and Jonathan Müller (`foonathan
+<https://github.com/foonathan>`_) with contributions from many other people.
+See `Contributors <https://github.com/fmtlib/fmt/graphs/contributors>`_ and
+`Releases <https://github.com/fmtlib/fmt/releases>`_ for some of the names.
+Let us know if your contribution is not listed or mentioned incorrectly and
+we'll make it right.
diff --git a/extern/fmtlib/include/fmt/core.h b/extern/fmtlib/include/fmt/core.h
new file mode 100644
index 00000000000..92a7aa1df69
--- /dev/null
+++ b/extern/fmtlib/include/fmt/core.h
@@ -0,0 +1,3236 @@
+// Formatting library for C++ - the core API for char/UTF-8
+//
+// Copyright (c) 2012 - present, Victor Zverovich
+// All rights reserved.
+//
+// For the license information refer to format.h.
+
+#ifndef FMT_CORE_H_
+#define FMT_CORE_H_
+
+#include <cstddef> // std::byte
+#include <cstdio> // std::FILE
+#include <cstring>
+#include <iterator>
+#include <limits>
+#include <string>
+#include <type_traits>
+
+// The fmt library version in the form major * 10000 + minor * 100 + patch.
+#define FMT_VERSION 80101
+
+#if defined(__clang__) && !defined(__ibmxl__)
+# define FMT_CLANG_VERSION (__clang_major__ * 100 + __clang_minor__)
+#else
+# define FMT_CLANG_VERSION 0
+#endif
+
+#if defined(__GNUC__) && !defined(__clang__) && !defined(__INTEL_COMPILER) && \
+ !defined(__NVCOMPILER)
+# define FMT_GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)
+#else
+# define FMT_GCC_VERSION 0
+#endif
+
+#ifndef FMT_GCC_PRAGMA
+// Workaround _Pragma bug https://gcc.gnu.org/bugzilla/show_bug.cgi?id=59884.
+# if FMT_GCC_VERSION >= 504
+# define FMT_GCC_PRAGMA(arg) _Pragma(arg)
+# else
+# define FMT_GCC_PRAGMA(arg)
+# endif
+#endif
+
+#ifdef __ICL
+# define FMT_ICC_VERSION __ICL
+#elif defined(__INTEL_COMPILER)
+# define FMT_ICC_VERSION __INTEL_COMPILER
+#else
+# define FMT_ICC_VERSION 0
+#endif
+
+#ifdef __NVCC__
+# define FMT_NVCC __NVCC__
+#else
+# define FMT_NVCC 0
+#endif
+
+#ifdef _MSC_VER
+# define FMT_MSC_VER _MSC_VER
+# define FMT_MSC_WARNING(...) __pragma(warning(__VA_ARGS__))
+#else
+# define FMT_MSC_VER 0
+# define FMT_MSC_WARNING(...)
+#endif
+
+#ifdef __has_feature
+# define FMT_HAS_FEATURE(x) __has_feature(x)
+#else
+# define FMT_HAS_FEATURE(x) 0
+#endif
+
+#if defined(__has_include) && \
+ (!defined(__INTELLISENSE__) || FMT_MSC_VER > 1900) && \
+ (!FMT_ICC_VERSION || FMT_ICC_VERSION >= 1600)
+# define FMT_HAS_INCLUDE(x) __has_include(x)
+#else
+# define FMT_HAS_INCLUDE(x) 0
+#endif
+
+#ifdef __has_cpp_attribute
+# define FMT_HAS_CPP_ATTRIBUTE(x) __has_cpp_attribute(x)
+#else
+# define FMT_HAS_CPP_ATTRIBUTE(x) 0
+#endif
+
+#ifdef _MSVC_LANG
+# define FMT_CPLUSPLUS _MSVC_LANG
+#else
+# define FMT_CPLUSPLUS __cplusplus
+#endif
+
+#define FMT_HAS_CPP14_ATTRIBUTE(attribute) \
+ (FMT_CPLUSPLUS >= 201402L && FMT_HAS_CPP_ATTRIBUTE(attribute))
+
+#define FMT_HAS_CPP17_ATTRIBUTE(attribute) \
+ (FMT_CPLUSPLUS >= 201703L && FMT_HAS_CPP_ATTRIBUTE(attribute))
+
+// Check if relaxed C++14 constexpr is supported.
+// GCC doesn't allow throw in constexpr until version 6 (bug 67371).
+#ifndef FMT_USE_CONSTEXPR
+# define FMT_USE_CONSTEXPR \
+ (FMT_HAS_FEATURE(cxx_relaxed_constexpr) || FMT_MSC_VER >= 1912 || \
+ (FMT_GCC_VERSION >= 600 && __cplusplus >= 201402L)) && \
+ !FMT_NVCC && !FMT_ICC_VERSION
+#endif
+#if FMT_USE_CONSTEXPR
+# define FMT_CONSTEXPR constexpr
+# define FMT_CONSTEXPR_DECL constexpr
+#else
+# define FMT_CONSTEXPR
+# define FMT_CONSTEXPR_DECL
+#endif
+
+#if ((__cplusplus >= 202002L) && \
+ (!defined(_GLIBCXX_RELEASE) || _GLIBCXX_RELEASE > 9)) || \
+ (__cplusplus >= 201709L && FMT_GCC_VERSION >= 1002)
+# define FMT_CONSTEXPR20 constexpr
+#else
+# define FMT_CONSTEXPR20
+#endif
+
+// Check if constexpr std::char_traits<>::compare,length is supported.
+#if defined(__GLIBCXX__)
+# if __cplusplus >= 201703L && defined(_GLIBCXX_RELEASE) && \
+ _GLIBCXX_RELEASE >= 7 // GCC 7+ libstdc++ has _GLIBCXX_RELEASE.
+# define FMT_CONSTEXPR_CHAR_TRAITS constexpr
+# endif
+#elif defined(_LIBCPP_VERSION) && __cplusplus >= 201703L && \
+ _LIBCPP_VERSION >= 4000
+# define FMT_CONSTEXPR_CHAR_TRAITS constexpr
+#elif FMT_MSC_VER >= 1914 && _MSVC_LANG >= 201703L
+# define FMT_CONSTEXPR_CHAR_TRAITS constexpr
+#endif
+#ifndef FMT_CONSTEXPR_CHAR_TRAITS
+# define FMT_CONSTEXPR_CHAR_TRAITS
+#endif
+
+// Check if exceptions are disabled.
+#ifndef FMT_EXCEPTIONS
+# if (defined(__GNUC__) && !defined(__EXCEPTIONS)) || \
+ FMT_MSC_VER && !_HAS_EXCEPTIONS
+# define FMT_EXCEPTIONS 0
+# else
+# define FMT_EXCEPTIONS 1
+# endif
+#endif
+
+// Define FMT_USE_NOEXCEPT to make fmt use noexcept (C++11 feature).
+#ifndef FMT_USE_NOEXCEPT
+# define FMT_USE_NOEXCEPT 0
+#endif
+
+#if FMT_USE_NOEXCEPT || FMT_HAS_FEATURE(cxx_noexcept) || \
+ FMT_GCC_VERSION >= 408 || FMT_MSC_VER >= 1900
+# define FMT_DETECTED_NOEXCEPT noexcept
+# define FMT_HAS_CXX11_NOEXCEPT 1
+#else
+# define FMT_DETECTED_NOEXCEPT throw()
+# define FMT_HAS_CXX11_NOEXCEPT 0
+#endif
+
+#ifndef FMT_NOEXCEPT
+# if FMT_EXCEPTIONS || FMT_HAS_CXX11_NOEXCEPT
+# define FMT_NOEXCEPT FMT_DETECTED_NOEXCEPT
+# else
+# define FMT_NOEXCEPT
+# endif
+#endif
+
+// [[noreturn]] is disabled on MSVC and NVCC because of bogus unreachable code
+// warnings.
+#if FMT_EXCEPTIONS && FMT_HAS_CPP_ATTRIBUTE(noreturn) && !FMT_MSC_VER && \
+ !FMT_NVCC
+# define FMT_NORETURN [[noreturn]]
+#else
+# define FMT_NORETURN
+#endif
+
+#if __cplusplus == 201103L || __cplusplus == 201402L
+# if defined(__INTEL_COMPILER) || defined(__PGI)
+# define FMT_FALLTHROUGH
+# elif defined(__clang__)
+# define FMT_FALLTHROUGH [[clang::fallthrough]]
+# elif FMT_GCC_VERSION >= 700 && \
+ (!defined(__EDG_VERSION__) || __EDG_VERSION__ >= 520)
+# define FMT_FALLTHROUGH [[gnu::fallthrough]]
+# else
+# define FMT_FALLTHROUGH
+# endif
+#elif FMT_HAS_CPP17_ATTRIBUTE(fallthrough)
+# define FMT_FALLTHROUGH [[fallthrough]]
+#else
+# define FMT_FALLTHROUGH
+#endif
+
+#ifndef FMT_NODISCARD
+# if FMT_HAS_CPP17_ATTRIBUTE(nodiscard)
+# define FMT_NODISCARD [[nodiscard]]
+# else
+# define FMT_NODISCARD
+# endif
+#endif
+
+#ifndef FMT_USE_FLOAT
+# define FMT_USE_FLOAT 1
+#endif
+#ifndef FMT_USE_DOUBLE
+# define FMT_USE_DOUBLE 1
+#endif
+#ifndef FMT_USE_LONG_DOUBLE
+# define FMT_USE_LONG_DOUBLE 1
+#endif
+
+#ifndef FMT_INLINE
+# if FMT_GCC_VERSION || FMT_CLANG_VERSION
+# define FMT_INLINE inline __attribute__((always_inline))
+# else
+# define FMT_INLINE inline
+# endif
+#endif
+
+#ifndef FMT_DEPRECATED
+# if FMT_HAS_CPP14_ATTRIBUTE(deprecated) || FMT_MSC_VER >= 1900
+# define FMT_DEPRECATED [[deprecated]]
+# else
+# if (defined(__GNUC__) && !defined(__LCC__)) || defined(__clang__)
+# define FMT_DEPRECATED __attribute__((deprecated))
+# elif FMT_MSC_VER
+# define FMT_DEPRECATED __declspec(deprecated)
+# else
+# define FMT_DEPRECATED /* deprecated */
+# endif
+# endif
+#endif
+
+#ifndef FMT_BEGIN_NAMESPACE
+# define FMT_BEGIN_NAMESPACE \
+ namespace fmt { \
+ inline namespace v8 {
+# define FMT_END_NAMESPACE \
+ } \
+ }
+#endif
+
+#ifndef FMT_MODULE_EXPORT
+# define FMT_MODULE_EXPORT
+# define FMT_MODULE_EXPORT_BEGIN
+# define FMT_MODULE_EXPORT_END
+# define FMT_BEGIN_DETAIL_NAMESPACE namespace detail {
+# define FMT_END_DETAIL_NAMESPACE }
+#endif
+
+#if !defined(FMT_HEADER_ONLY) && defined(_WIN32)
+# define FMT_CLASS_API FMT_MSC_WARNING(suppress : 4275)
+# ifdef FMT_EXPORT
+# define FMT_API __declspec(dllexport)
+# elif defined(FMT_SHARED)
+# define FMT_API __declspec(dllimport)
+# endif
+#else
+# define FMT_CLASS_API
+# if defined(FMT_EXPORT) || defined(FMT_SHARED)
+# if defined(__GNUC__) || defined(__clang__)
+# define FMT_API __attribute__((visibility("default")))
+# endif
+# endif
+#endif
+#ifndef FMT_API
+# define FMT_API
+#endif
+
+// libc++ supports string_view in pre-c++17.
+#if (FMT_HAS_INCLUDE(<string_view>) && \
+ (__cplusplus > 201402L || defined(_LIBCPP_VERSION))) || \
+ (defined(_MSVC_LANG) && _MSVC_LANG > 201402L && _MSC_VER >= 1910)
+# include <string_view>
+# define FMT_USE_STRING_VIEW
+#elif FMT_HAS_INCLUDE("experimental/string_view") && __cplusplus >= 201402L
+# include <experimental/string_view>
+# define FMT_USE_EXPERIMENTAL_STRING_VIEW
+#endif
+
+#ifndef FMT_UNICODE
+# define FMT_UNICODE !FMT_MSC_VER
+#endif
+
+#ifndef FMT_CONSTEVAL
+# if ((FMT_GCC_VERSION >= 1000 || FMT_CLANG_VERSION >= 1101) && \
+ __cplusplus > 201703L && !defined(__apple_build_version__)) || \
+ (defined(__cpp_consteval) && \
+ (!FMT_MSC_VER || _MSC_FULL_VER >= 193030704))
+// consteval is broken in MSVC before VS2022 and Apple clang 13.
+# define FMT_CONSTEVAL consteval
+# define FMT_HAS_CONSTEVAL
+# else
+# define FMT_CONSTEVAL
+# endif
+#endif
+
+#ifndef FMT_USE_NONTYPE_TEMPLATE_PARAMETERS
+# if defined(__cpp_nontype_template_args) && \
+ ((FMT_GCC_VERSION >= 903 && __cplusplus >= 201709L) || \
+ __cpp_nontype_template_args >= 201911L)
+# define FMT_USE_NONTYPE_TEMPLATE_PARAMETERS 1
+# else
+# define FMT_USE_NONTYPE_TEMPLATE_PARAMETERS 0
+# endif
+#endif
+
+// Enable minimal optimizations for more compact code in debug mode.
+FMT_GCC_PRAGMA("GCC push_options")
+#ifndef __OPTIMIZE__
+FMT_GCC_PRAGMA("GCC optimize(\"Og\")")
+#endif
+
+FMT_BEGIN_NAMESPACE
+FMT_MODULE_EXPORT_BEGIN
+
+// Implementations of enable_if_t and other metafunctions for older systems.
+template <bool B, typename T = void>
+using enable_if_t = typename std::enable_if<B, T>::type;
+template <bool B, typename T, typename F>
+using conditional_t = typename std::conditional<B, T, F>::type;
+template <bool B> using bool_constant = std::integral_constant<bool, B>;
+template <typename T>
+using remove_reference_t = typename std::remove_reference<T>::type;
+template <typename T>
+using remove_const_t = typename std::remove_const<T>::type;
+template <typename T>
+using remove_cvref_t = typename std::remove_cv<remove_reference_t<T>>::type;
+template <typename T> struct type_identity { using type = T; };
+template <typename T> using type_identity_t = typename type_identity<T>::type;
+
+struct monostate {
+ constexpr monostate() {}
+};
+
+// An enable_if helper to be used in template parameters which results in much
+// shorter symbols: https://godbolt.org/z/sWw4vP. Extra parentheses are needed
+// to workaround a bug in MSVC 2019 (see #1140 and #1186).
+#ifdef FMT_DOC
+# define FMT_ENABLE_IF(...)
+#else
+# define FMT_ENABLE_IF(...) enable_if_t<(__VA_ARGS__), int> = 0
+#endif
+
+FMT_BEGIN_DETAIL_NAMESPACE
+
+// Suppress "unused variable" warnings with the method described in
+// https://herbsutter.com/2009/10/18/mailbag-shutting-up-compiler-warnings/.
+// (void)var does not work on many Intel compilers.
+template <typename... T> FMT_CONSTEXPR void ignore_unused(const T&...) {}
+
+constexpr FMT_INLINE auto is_constant_evaluated(bool default_value = false)
+ FMT_NOEXCEPT -> bool {
+#ifdef __cpp_lib_is_constant_evaluated
+ ignore_unused(default_value);
+ return std::is_constant_evaluated();
+#else
+ return default_value;
+#endif
+}
+
+// A function to suppress "conditional expression is constant" warnings.
+template <typename T> constexpr FMT_INLINE auto const_check(T value) -> T {
+ return value;
+}
+
+FMT_NORETURN FMT_API void assert_fail(const char* file, int line,
+ const char* message);
+
+#ifndef FMT_ASSERT
+# ifdef NDEBUG
+// FMT_ASSERT is not empty to avoid -Werror=empty-body.
+# define FMT_ASSERT(condition, message) \
+ ::fmt::detail::ignore_unused((condition), (message))
+# else
+# define FMT_ASSERT(condition, message) \
+ ((condition) /* void() fails with -Winvalid-constexpr on clang 4.0.1 */ \
+ ? (void)0 \
+ : ::fmt::detail::assert_fail(__FILE__, __LINE__, (message)))
+# endif
+#endif
+
+#ifdef __cpp_lib_byte
+using byte = std::byte;
+#else
+enum class byte : unsigned char {};
+#endif
+
+#if defined(FMT_USE_STRING_VIEW)
+template <typename Char> using std_string_view = std::basic_string_view<Char>;
+#elif defined(FMT_USE_EXPERIMENTAL_STRING_VIEW)
+template <typename Char>
+using std_string_view = std::experimental::basic_string_view<Char>;
+#else
+template <typename T> struct std_string_view {};
+#endif
+
+#ifdef FMT_USE_INT128
+// Do nothing.
+#elif defined(__SIZEOF_INT128__) && !FMT_NVCC && \
+ !(FMT_CLANG_VERSION && FMT_MSC_VER)
+# define FMT_USE_INT128 1
+using int128_t = __int128_t;
+using uint128_t = __uint128_t;
+template <typename T> inline auto convert_for_visit(T value) -> T {
+ return value;
+}
+#else
+# define FMT_USE_INT128 0
+#endif
+#if !FMT_USE_INT128
+enum class int128_t {};
+enum class uint128_t {};
+// Reduce template instantiations.
+template <typename T> inline auto convert_for_visit(T) -> monostate {
+ return {};
+}
+#endif
+
+// Casts a nonnegative integer to unsigned.
+template <typename Int>
+FMT_CONSTEXPR auto to_unsigned(Int value) ->
+ typename std::make_unsigned<Int>::type {
+ FMT_ASSERT(value >= 0, "negative value");
+ return static_cast<typename std::make_unsigned<Int>::type>(value);
+}
+
+FMT_MSC_WARNING(suppress : 4566) constexpr unsigned char micro[] = "\u00B5";
+
+constexpr auto is_utf8() -> bool {
+ // Avoid buggy sign extensions in MSVC's constant evaluation mode.
+ // https://developercommunity.visualstudio.com/t/C-difference-in-behavior-for-unsigned/1233612
+ using uchar = unsigned char;
+ return FMT_UNICODE || (sizeof(micro) == 3 && uchar(micro[0]) == 0xC2 &&
+ uchar(micro[1]) == 0xB5);
+}
+FMT_END_DETAIL_NAMESPACE
+
+/**
+ An implementation of ``std::basic_string_view`` for pre-C++17. It provides a
+ subset of the API. ``fmt::basic_string_view`` is used for format strings even
+ if ``std::string_view`` is available to prevent issues when a library is
+ compiled with a different ``-std`` option than the client code (which is not
+ recommended).
+ */
+template <typename Char> class basic_string_view {
+ private:
+ const Char* data_;
+ size_t size_;
+
+ public:
+ using value_type = Char;
+ using iterator = const Char*;
+
+ constexpr basic_string_view() FMT_NOEXCEPT : data_(nullptr), size_(0) {}
+
+ /** Constructs a string reference object from a C string and a size. */
+ constexpr basic_string_view(const Char* s, size_t count) FMT_NOEXCEPT
+ : data_(s),
+ size_(count) {}
+
+ /**
+ \rst
+ Constructs a string reference object from a C string computing
+ the size with ``std::char_traits<Char>::length``.
+ \endrst
+ */
+ FMT_CONSTEXPR_CHAR_TRAITS
+ FMT_INLINE
+ basic_string_view(const Char* s)
+ : data_(s),
+ size_(detail::const_check(std::is_same<Char, char>::value &&
+ !detail::is_constant_evaluated(true))
+ ? std::strlen(reinterpret_cast<const char*>(s))
+ : std::char_traits<Char>::length(s)) {}
+
+ /** Constructs a string reference from a ``std::basic_string`` object. */
+ template <typename Traits, typename Alloc>
+ FMT_CONSTEXPR basic_string_view(
+ const std::basic_string<Char, Traits, Alloc>& s) FMT_NOEXCEPT
+ : data_(s.data()),
+ size_(s.size()) {}
+
+ template <typename S, FMT_ENABLE_IF(std::is_same<
+ S, detail::std_string_view<Char>>::value)>
+ FMT_CONSTEXPR basic_string_view(S s) FMT_NOEXCEPT : data_(s.data()),
+ size_(s.size()) {}
+
+ /** Returns a pointer to the string data. */
+ constexpr auto data() const FMT_NOEXCEPT -> const Char* { return data_; }
+
+ /** Returns the string size. */
+ constexpr auto size() const FMT_NOEXCEPT -> size_t { return size_; }
+
+ constexpr auto begin() const FMT_NOEXCEPT -> iterator { return data_; }
+ constexpr auto end() const FMT_NOEXCEPT -> iterator { return data_ + size_; }
+
+ constexpr auto operator[](size_t pos) const FMT_NOEXCEPT -> const Char& {
+ return data_[pos];
+ }
+
+ FMT_CONSTEXPR void remove_prefix(size_t n) FMT_NOEXCEPT {
+ data_ += n;
+ size_ -= n;
+ }
+
+ // Lexicographically compare this string reference to other.
+ FMT_CONSTEXPR_CHAR_TRAITS auto compare(basic_string_view other) const -> int {
+ size_t str_size = size_ < other.size_ ? size_ : other.size_;
+ int result = std::char_traits<Char>::compare(data_, other.data_, str_size);
+ if (result == 0)
+ result = size_ == other.size_ ? 0 : (size_ < other.size_ ? -1 : 1);
+ return result;
+ }
+
+ FMT_CONSTEXPR_CHAR_TRAITS friend auto operator==(basic_string_view lhs,
+ basic_string_view rhs)
+ -> bool {
+ return lhs.compare(rhs) == 0;
+ }
+ friend auto operator!=(basic_string_view lhs, basic_string_view rhs) -> bool {
+ return lhs.compare(rhs) != 0;
+ }
+ friend auto operator<(basic_string_view lhs, basic_string_view rhs) -> bool {
+ return lhs.compare(rhs) < 0;
+ }
+ friend auto operator<=(basic_string_view lhs, basic_string_view rhs) -> bool {
+ return lhs.compare(rhs) <= 0;
+ }
+ friend auto operator>(basic_string_view lhs, basic_string_view rhs) -> bool {
+ return lhs.compare(rhs) > 0;
+ }
+ friend auto operator>=(basic_string_view lhs, basic_string_view rhs) -> bool {
+ return lhs.compare(rhs) >= 0;
+ }
+};
+
+using string_view = basic_string_view<char>;
+
+/** Specifies if ``T`` is a character type. Can be specialized by users. */
+template <typename T> struct is_char : std::false_type {};
+template <> struct is_char<char> : std::true_type {};
+
+// Returns a string view of `s`.
+template <typename Char, FMT_ENABLE_IF(is_char<Char>::value)>
+FMT_INLINE auto to_string_view(const Char* s) -> basic_string_view<Char> {
+ return s;
+}
+template <typename Char, typename Traits, typename Alloc>
+inline auto to_string_view(const std::basic_string<Char, Traits, Alloc>& s)
+ -> basic_string_view<Char> {
+ return s;
+}
+template <typename Char>
+constexpr auto to_string_view(basic_string_view<Char> s)
+ -> basic_string_view<Char> {
+ return s;
+}
+template <typename Char,
+ FMT_ENABLE_IF(!std::is_empty<detail::std_string_view<Char>>::value)>
+inline auto to_string_view(detail::std_string_view<Char> s)
+ -> basic_string_view<Char> {
+ return s;
+}
+
+// A base class for compile-time strings. It is defined in the fmt namespace to
+// make formatting functions visible via ADL, e.g. format(FMT_STRING("{}"), 42).
+struct compile_string {};
+
+template <typename S>
+struct is_compile_string : std::is_base_of<compile_string, S> {};
+
+template <typename S, FMT_ENABLE_IF(is_compile_string<S>::value)>
+constexpr auto to_string_view(const S& s)
+ -> basic_string_view<typename S::char_type> {
+ return basic_string_view<typename S::char_type>(s);
+}
+
+FMT_BEGIN_DETAIL_NAMESPACE
+
+void to_string_view(...);
+using fmt::to_string_view;
+
+// Specifies whether S is a string type convertible to fmt::basic_string_view.
+// It should be a constexpr function but MSVC 2017 fails to compile it in
+// enable_if and MSVC 2015 fails to compile it as an alias template.
+template <typename S>
+struct is_string : std::is_class<decltype(to_string_view(std::declval<S>()))> {
+};
+
+template <typename S, typename = void> struct char_t_impl {};
+template <typename S> struct char_t_impl<S, enable_if_t<is_string<S>::value>> {
+ using result = decltype(to_string_view(std::declval<S>()));
+ using type = typename result::value_type;
+};
+
+// Reports a compile-time error if S is not a valid format string.
+template <typename..., typename S, FMT_ENABLE_IF(!is_compile_string<S>::value)>
+FMT_INLINE void check_format_string(const S&) {
+#ifdef FMT_ENFORCE_COMPILE_STRING
+ static_assert(is_compile_string<S>::value,
+ "FMT_ENFORCE_COMPILE_STRING requires all format strings to use "
+ "FMT_STRING.");
+#endif
+}
+template <typename..., typename S, FMT_ENABLE_IF(is_compile_string<S>::value)>
+void check_format_string(S);
+
+FMT_NORETURN FMT_API void throw_format_error(const char* message);
+
+struct error_handler {
+ constexpr error_handler() = default;
+ constexpr error_handler(const error_handler&) = default;
+
+ // This function is intentionally not constexpr to give a compile-time error.
+ FMT_NORETURN FMT_API void on_error(const char* message);
+};
+FMT_END_DETAIL_NAMESPACE
+
+/** String's character type. */
+template <typename S> using char_t = typename detail::char_t_impl<S>::type;
+
+/**
+ \rst
+ Parsing context consisting of a format string range being parsed and an
+ argument counter for automatic indexing.
+ You can use the ``format_parse_context`` type alias for ``char`` instead.
+ \endrst
+ */
+template <typename Char, typename ErrorHandler = detail::error_handler>
+class basic_format_parse_context : private ErrorHandler {
+ private:
+ basic_string_view<Char> format_str_;
+ int next_arg_id_;
+
+ public:
+ using char_type = Char;
+ using iterator = typename basic_string_view<Char>::iterator;
+
+ explicit constexpr basic_format_parse_context(
+ basic_string_view<Char> format_str, ErrorHandler eh = {},
+ int next_arg_id = 0)
+ : ErrorHandler(eh), format_str_(format_str), next_arg_id_(next_arg_id) {}
+
+ /**
+ Returns an iterator to the beginning of the format string range being
+ parsed.
+ */
+ constexpr auto begin() const FMT_NOEXCEPT -> iterator {
+ return format_str_.begin();
+ }
+
+ /**
+ Returns an iterator past the end of the format string range being parsed.
+ */
+ constexpr auto end() const FMT_NOEXCEPT -> iterator {
+ return format_str_.end();
+ }
+
+ /** Advances the begin iterator to ``it``. */
+ FMT_CONSTEXPR void advance_to(iterator it) {
+ format_str_.remove_prefix(detail::to_unsigned(it - begin()));
+ }
+
+ /**
+ Reports an error if using the manual argument indexing; otherwise returns
+ the next argument index and switches to the automatic indexing.
+ */
+ FMT_CONSTEXPR auto next_arg_id() -> int {
+ // Don't check if the argument id is valid to avoid overhead and because it
+ // will be checked during formatting anyway.
+ if (next_arg_id_ >= 0) return next_arg_id_++;
+ on_error("cannot switch from manual to automatic argument indexing");
+ return 0;
+ }
+
+ /**
+ Reports an error if using the automatic argument indexing; otherwise
+ switches to the manual indexing.
+ */
+ FMT_CONSTEXPR void check_arg_id(int) {
+ if (next_arg_id_ > 0)
+ on_error("cannot switch from automatic to manual argument indexing");
+ else
+ next_arg_id_ = -1;
+ }
+
+ FMT_CONSTEXPR void check_arg_id(basic_string_view<Char>) {}
+
+ FMT_CONSTEXPR void on_error(const char* message) {
+ ErrorHandler::on_error(message);
+ }
+
+ constexpr auto error_handler() const -> ErrorHandler { return *this; }
+};
+
+using format_parse_context = basic_format_parse_context<char>;
+
+template <typename Context> class basic_format_arg;
+template <typename Context> class basic_format_args;
+template <typename Context> class dynamic_format_arg_store;
+
+// A formatter for objects of type T.
+template <typename T, typename Char = char, typename Enable = void>
+struct formatter {
+ // A deleted default constructor indicates a disabled formatter.
+ formatter() = delete;
+};
+
+// Specifies if T has an enabled formatter specialization. A type can be
+// formattable even if it doesn't have a formatter e.g. via a conversion.
+template <typename T, typename Context>
+using has_formatter =
+ std::is_constructible<typename Context::template formatter_type<T>>;
+
+// Checks whether T is a container with contiguous storage.
+template <typename T> struct is_contiguous : std::false_type {};
+template <typename Char>
+struct is_contiguous<std::basic_string<Char>> : std::true_type {};
+
+class appender;
+
+FMT_BEGIN_DETAIL_NAMESPACE
+
+template <typename Context, typename T>
+constexpr auto has_const_formatter_impl(T*)
+ -> decltype(typename Context::template formatter_type<T>().format(
+ std::declval<const T&>(), std::declval<Context&>()),
+ true) {
+ return true;
+}
+template <typename Context>
+constexpr auto has_const_formatter_impl(...) -> bool {
+ return false;
+}
+template <typename T, typename Context>
+constexpr auto has_const_formatter() -> bool {
+ return has_const_formatter_impl<Context>(static_cast<T*>(nullptr));
+}
+
+// Extracts a reference to the container from back_insert_iterator.
+template <typename Container>
+inline auto get_container(std::back_insert_iterator<Container> it)
+ -> Container& {
+ using bi_iterator = std::back_insert_iterator<Container>;
+ struct accessor : bi_iterator {
+ accessor(bi_iterator iter) : bi_iterator(iter) {}
+ using bi_iterator::container;
+ };
+ return *accessor(it).container;
+}
+
+template <typename Char, typename InputIt, typename OutputIt>
+FMT_CONSTEXPR auto copy_str(InputIt begin, InputIt end, OutputIt out)
+ -> OutputIt {
+ while (begin != end) *out++ = static_cast<Char>(*begin++);
+ return out;
+}
+
+template <typename Char, typename T, typename U,
+ FMT_ENABLE_IF(
+ std::is_same<remove_const_t<T>, U>::value&& is_char<U>::value)>
+FMT_CONSTEXPR auto copy_str(T* begin, T* end, U* out) -> U* {
+ if (is_constant_evaluated()) return copy_str<Char, T*, U*>(begin, end, out);
+ auto size = to_unsigned(end - begin);
+ memcpy(out, begin, size * sizeof(U));
+ return out + size;
+}
+
+/**
+ \rst
+ A contiguous memory buffer with an optional growing ability. It is an internal
+ class and shouldn't be used directly, only via `~fmt::basic_memory_buffer`.
+ \endrst
+ */
+template <typename T> class buffer {
+ private:
+ T* ptr_;
+ size_t size_;
+ size_t capacity_;
+
+ protected:
+ // Don't initialize ptr_ since it is not accessed to save a few cycles.
+ FMT_MSC_WARNING(suppress : 26495)
+ buffer(size_t sz) FMT_NOEXCEPT : size_(sz), capacity_(sz) {}
+
+ FMT_CONSTEXPR20 buffer(T* p = nullptr, size_t sz = 0,
+ size_t cap = 0) FMT_NOEXCEPT : ptr_(p),
+ size_(sz),
+ capacity_(cap) {}
+
+ FMT_CONSTEXPR20 ~buffer() = default;
+ buffer(buffer&&) = default;
+
+ /** Sets the buffer data and capacity. */
+ FMT_CONSTEXPR void set(T* buf_data, size_t buf_capacity) FMT_NOEXCEPT {
+ ptr_ = buf_data;
+ capacity_ = buf_capacity;
+ }
+
+ /** Increases the buffer capacity to hold at least *capacity* elements. */
+ virtual FMT_CONSTEXPR20 void grow(size_t capacity) = 0;
+
+ public:
+ using value_type = T;
+ using const_reference = const T&;
+
+ buffer(const buffer&) = delete;
+ void operator=(const buffer&) = delete;
+
+ auto begin() FMT_NOEXCEPT -> T* { return ptr_; }
+ auto end() FMT_NOEXCEPT -> T* { return ptr_ + size_; }
+
+ auto begin() const FMT_NOEXCEPT -> const T* { return ptr_; }
+ auto end() const FMT_NOEXCEPT -> const T* { return ptr_ + size_; }
+
+ /** Returns the size of this buffer. */
+ constexpr auto size() const FMT_NOEXCEPT -> size_t { return size_; }
+
+ /** Returns the capacity of this buffer. */
+ constexpr auto capacity() const FMT_NOEXCEPT -> size_t { return capacity_; }
+
+ /** Returns a pointer to the buffer data. */
+ FMT_CONSTEXPR auto data() FMT_NOEXCEPT -> T* { return ptr_; }
+
+ /** Returns a pointer to the buffer data. */
+ FMT_CONSTEXPR auto data() const FMT_NOEXCEPT -> const T* { return ptr_; }
+
+ /** Clears this buffer. */
+ void clear() { size_ = 0; }
+
+ // Tries resizing the buffer to contain *count* elements. If T is a POD type
+ // the new elements may not be initialized.
+ FMT_CONSTEXPR20 void try_resize(size_t count) {
+ try_reserve(count);
+ size_ = count <= capacity_ ? count : capacity_;
+ }
+
+ // Tries increasing the buffer capacity to *new_capacity*. It can increase the
+ // capacity by a smaller amount than requested but guarantees there is space
+ // for at least one additional element either by increasing the capacity or by
+ // flushing the buffer if it is full.
+ FMT_CONSTEXPR20 void try_reserve(size_t new_capacity) {
+ if (new_capacity > capacity_) grow(new_capacity);
+ }
+
+ FMT_CONSTEXPR20 void push_back(const T& value) {
+ try_reserve(size_ + 1);
+ ptr_[size_++] = value;
+ }
+
+ /** Appends data to the end of the buffer. */
+ template <typename U> void append(const U* begin, const U* end);
+
+ template <typename I> FMT_CONSTEXPR auto operator[](I index) -> T& {
+ return ptr_[index];
+ }
+ template <typename I>
+ FMT_CONSTEXPR auto operator[](I index) const -> const T& {
+ return ptr_[index];
+ }
+};
+
+struct buffer_traits {
+ explicit buffer_traits(size_t) {}
+ auto count() const -> size_t { return 0; }
+ auto limit(size_t size) -> size_t { return size; }
+};
+
+class fixed_buffer_traits {
+ private:
+ size_t count_ = 0;
+ size_t limit_;
+
+ public:
+ explicit fixed_buffer_traits(size_t limit) : limit_(limit) {}
+ auto count() const -> size_t { return count_; }
+ auto limit(size_t size) -> size_t {
+ size_t n = limit_ > count_ ? limit_ - count_ : 0;
+ count_ += size;
+ return size < n ? size : n;
+ }
+};
+
+// A buffer that writes to an output iterator when flushed.
+template <typename OutputIt, typename T, typename Traits = buffer_traits>
+class iterator_buffer final : public Traits, public buffer<T> {
+ private:
+ OutputIt out_;
+ enum { buffer_size = 256 };
+ T data_[buffer_size];
+
+ protected:
+ FMT_CONSTEXPR20 void grow(size_t) override {
+ if (this->size() == buffer_size) flush();
+ }
+
+ void flush() {
+ auto size = this->size();
+ this->clear();
+ out_ = copy_str<T>(data_, data_ + this->limit(size), out_);
+ }
+
+ public:
+ explicit iterator_buffer(OutputIt out, size_t n = buffer_size)
+ : Traits(n), buffer<T>(data_, 0, buffer_size), out_(out) {}
+ iterator_buffer(iterator_buffer&& other)
+ : Traits(other), buffer<T>(data_, 0, buffer_size), out_(other.out_) {}
+ ~iterator_buffer() { flush(); }
+
+ auto out() -> OutputIt {
+ flush();
+ return out_;
+ }
+ auto count() const -> size_t { return Traits::count() + this->size(); }
+};
+
+template <typename T>
+class iterator_buffer<T*, T, fixed_buffer_traits> final
+ : public fixed_buffer_traits,
+ public buffer<T> {
+ private:
+ T* out_;
+ enum { buffer_size = 256 };
+ T data_[buffer_size];
+
+ protected:
+ FMT_CONSTEXPR20 void grow(size_t) override {
+ if (this->size() == this->capacity()) flush();
+ }
+
+ void flush() {
+ size_t n = this->limit(this->size());
+ if (this->data() == out_) {
+ out_ += n;
+ this->set(data_, buffer_size);
+ }
+ this->clear();
+ }
+
+ public:
+ explicit iterator_buffer(T* out, size_t n = buffer_size)
+ : fixed_buffer_traits(n), buffer<T>(out, 0, n), out_(out) {}
+ iterator_buffer(iterator_buffer&& other)
+ : fixed_buffer_traits(other),
+ buffer<T>(std::move(other)),
+ out_(other.out_) {
+ if (this->data() != out_) {
+ this->set(data_, buffer_size);
+ this->clear();
+ }
+ }
+ ~iterator_buffer() { flush(); }
+
+ auto out() -> T* {
+ flush();
+ return out_;
+ }
+ auto count() const -> size_t {
+ return fixed_buffer_traits::count() + this->size();
+ }
+};
+
+template <typename T> class iterator_buffer<T*, T> final : public buffer<T> {
+ protected:
+ FMT_CONSTEXPR20 void grow(size_t) override {}
+
+ public:
+ explicit iterator_buffer(T* out, size_t = 0) : buffer<T>(out, 0, ~size_t()) {}
+
+ auto out() -> T* { return &*this->end(); }
+};
+
+// A buffer that writes to a container with the contiguous storage.
+template <typename Container>
+class iterator_buffer<std::back_insert_iterator<Container>,
+ enable_if_t<is_contiguous<Container>::value,
+ typename Container::value_type>>
+ final : public buffer<typename Container::value_type> {
+ private:
+ Container& container_;
+
+ protected:
+ FMT_CONSTEXPR20 void grow(size_t capacity) override {
+ container_.resize(capacity);
+ this->set(&container_[0], capacity);
+ }
+
+ public:
+ explicit iterator_buffer(Container& c)
+ : buffer<typename Container::value_type>(c.size()), container_(c) {}
+ explicit iterator_buffer(std::back_insert_iterator<Container> out, size_t = 0)
+ : iterator_buffer(get_container(out)) {}
+ auto out() -> std::back_insert_iterator<Container> {
+ return std::back_inserter(container_);
+ }
+};
+
+// A buffer that counts the number of code units written discarding the output.
+template <typename T = char> class counting_buffer final : public buffer<T> {
+ private:
+ enum { buffer_size = 256 };
+ T data_[buffer_size];
+ size_t count_ = 0;
+
+ protected:
+ FMT_CONSTEXPR20 void grow(size_t) override {
+ if (this->size() != buffer_size) return;
+ count_ += this->size();
+ this->clear();
+ }
+
+ public:
+ counting_buffer() : buffer<T>(data_, 0, buffer_size) {}
+
+ auto count() -> size_t { return count_ + this->size(); }
+};
+
+template <typename T>
+using buffer_appender = conditional_t<std::is_same<T, char>::value, appender,
+ std::back_insert_iterator<buffer<T>>>;
+
+// Maps an output iterator to a buffer.
+template <typename T, typename OutputIt>
+auto get_buffer(OutputIt out) -> iterator_buffer<OutputIt, T> {
+ return iterator_buffer<OutputIt, T>(out);
+}
+
+template <typename Buffer>
+auto get_iterator(Buffer& buf) -> decltype(buf.out()) {
+ return buf.out();
+}
+template <typename T> auto get_iterator(buffer<T>& buf) -> buffer_appender<T> {
+ return buffer_appender<T>(buf);
+}
+
+template <typename T, typename Char = char, typename Enable = void>
+struct fallback_formatter {
+ fallback_formatter() = delete;
+};
+
+// Specifies if T has an enabled fallback_formatter specialization.
+template <typename T, typename Char>
+using has_fallback_formatter =
+ std::is_constructible<fallback_formatter<T, Char>>;
+
+struct view {};
+
+template <typename Char, typename T> struct named_arg : view {
+ const Char* name;
+ const T& value;
+ named_arg(const Char* n, const T& v) : name(n), value(v) {}
+};
+
+template <typename Char> struct named_arg_info {
+ const Char* name;
+ int id;
+};
+
+template <typename T, typename Char, size_t NUM_ARGS, size_t NUM_NAMED_ARGS>
+struct arg_data {
+ // args_[0].named_args points to named_args_ to avoid bloating format_args.
+ // +1 to workaround a bug in gcc 7.5 that causes duplicated-branches warning.
+ T args_[1 + (NUM_ARGS != 0 ? NUM_ARGS : +1)];
+ named_arg_info<Char> named_args_[NUM_NAMED_ARGS];
+
+ template <typename... U>
+ arg_data(const U&... init) : args_{T(named_args_, NUM_NAMED_ARGS), init...} {}
+ arg_data(const arg_data& other) = delete;
+ auto args() const -> const T* { return args_ + 1; }
+ auto named_args() -> named_arg_info<Char>* { return named_args_; }
+};
+
+template <typename T, typename Char, size_t NUM_ARGS>
+struct arg_data<T, Char, NUM_ARGS, 0> {
+ // +1 to workaround a bug in gcc 7.5 that causes duplicated-branches warning.
+ T args_[NUM_ARGS != 0 ? NUM_ARGS : +1];
+
+ template <typename... U>
+ FMT_CONSTEXPR FMT_INLINE arg_data(const U&... init) : args_{init...} {}
+ FMT_CONSTEXPR FMT_INLINE auto args() const -> const T* { return args_; }
+ FMT_CONSTEXPR FMT_INLINE auto named_args() -> std::nullptr_t {
+ return nullptr;
+ }
+};
+
+template <typename Char>
+inline void init_named_args(named_arg_info<Char>*, int, int) {}
+
+template <typename T> struct is_named_arg : std::false_type {};
+template <typename T> struct is_statically_named_arg : std::false_type {};
+
+template <typename T, typename Char>
+struct is_named_arg<named_arg<Char, T>> : std::true_type {};
+
+template <typename Char, typename T, typename... Tail,
+ FMT_ENABLE_IF(!is_named_arg<T>::value)>
+void init_named_args(named_arg_info<Char>* named_args, int arg_count,
+ int named_arg_count, const T&, const Tail&... args) {
+ init_named_args(named_args, arg_count + 1, named_arg_count, args...);
+}
+
+template <typename Char, typename T, typename... Tail,
+ FMT_ENABLE_IF(is_named_arg<T>::value)>
+void init_named_args(named_arg_info<Char>* named_args, int arg_count,
+ int named_arg_count, const T& arg, const Tail&... args) {
+ named_args[named_arg_count++] = {arg.name, arg_count};
+ init_named_args(named_args, arg_count + 1, named_arg_count, args...);
+}
+
+template <typename... Args>
+FMT_CONSTEXPR FMT_INLINE void init_named_args(std::nullptr_t, int, int,
+ const Args&...) {}
+
+template <bool B = false> constexpr auto count() -> size_t { return B ? 1 : 0; }
+template <bool B1, bool B2, bool... Tail> constexpr auto count() -> size_t {
+ return (B1 ? 1 : 0) + count<B2, Tail...>();
+}
+
+template <typename... Args> constexpr auto count_named_args() -> size_t {
+ return count<is_named_arg<Args>::value...>();
+}
+
+template <typename... Args>
+constexpr auto count_statically_named_args() -> size_t {
+ return count<is_statically_named_arg<Args>::value...>();
+}
+
+enum class type {
+ none_type,
+ // Integer types should go first,
+ int_type,
+ uint_type,
+ long_long_type,
+ ulong_long_type,
+ int128_type,
+ uint128_type,
+ bool_type,
+ char_type,
+ last_integer_type = char_type,
+ // followed by floating-point types.
+ float_type,
+ double_type,
+ long_double_type,
+ last_numeric_type = long_double_type,
+ cstring_type,
+ string_type,
+ pointer_type,
+ custom_type
+};
+
+// Maps core type T to the corresponding type enum constant.
+template <typename T, typename Char>
+struct type_constant : std::integral_constant<type, type::custom_type> {};
+
+#define FMT_TYPE_CONSTANT(Type, constant) \
+ template <typename Char> \
+ struct type_constant<Type, Char> \
+ : std::integral_constant<type, type::constant> {}
+
+FMT_TYPE_CONSTANT(int, int_type);
+FMT_TYPE_CONSTANT(unsigned, uint_type);
+FMT_TYPE_CONSTANT(long long, long_long_type);
+FMT_TYPE_CONSTANT(unsigned long long, ulong_long_type);
+FMT_TYPE_CONSTANT(int128_t, int128_type);
+FMT_TYPE_CONSTANT(uint128_t, uint128_type);
+FMT_TYPE_CONSTANT(bool, bool_type);
+FMT_TYPE_CONSTANT(Char, char_type);
+FMT_TYPE_CONSTANT(float, float_type);
+FMT_TYPE_CONSTANT(double, double_type);
+FMT_TYPE_CONSTANT(long double, long_double_type);
+FMT_TYPE_CONSTANT(const Char*, cstring_type);
+FMT_TYPE_CONSTANT(basic_string_view<Char>, string_type);
+FMT_TYPE_CONSTANT(const void*, pointer_type);
+
+constexpr bool is_integral_type(type t) {
+ return t > type::none_type && t <= type::last_integer_type;
+}
+
+constexpr bool is_arithmetic_type(type t) {
+ return t > type::none_type && t <= type::last_numeric_type;
+}
+
+struct unformattable {};
+struct unformattable_char : unformattable {};
+struct unformattable_const : unformattable {};
+struct unformattable_pointer : unformattable {};
+
+template <typename Char> struct string_value {
+ const Char* data;
+ size_t size;
+};
+
+template <typename Char> struct named_arg_value {
+ const named_arg_info<Char>* data;
+ size_t size;
+};
+
+template <typename Context> struct custom_value {
+ using parse_context = typename Context::parse_context_type;
+ void* value;
+ void (*format)(void* arg, parse_context& parse_ctx, Context& ctx);
+};
+
+// A formatting argument value.
+template <typename Context> class value {
+ public:
+ using char_type = typename Context::char_type;
+
+ union {
+ monostate no_value;
+ int int_value;
+ unsigned uint_value;
+ long long long_long_value;
+ unsigned long long ulong_long_value;
+ int128_t int128_value;
+ uint128_t uint128_value;
+ bool bool_value;
+ char_type char_value;
+ float float_value;
+ double double_value;
+ long double long_double_value;
+ const void* pointer;
+ string_value<char_type> string;
+ custom_value<Context> custom;
+ named_arg_value<char_type> named_args;
+ };
+
+ constexpr FMT_INLINE value() : no_value() {}
+ constexpr FMT_INLINE value(int val) : int_value(val) {}
+ constexpr FMT_INLINE value(unsigned val) : uint_value(val) {}
+ constexpr FMT_INLINE value(long long val) : long_long_value(val) {}
+ constexpr FMT_INLINE value(unsigned long long val) : ulong_long_value(val) {}
+ FMT_INLINE value(int128_t val) : int128_value(val) {}
+ FMT_INLINE value(uint128_t val) : uint128_value(val) {}
+ constexpr FMT_INLINE value(float val) : float_value(val) {}
+ constexpr FMT_INLINE value(double val) : double_value(val) {}
+ FMT_INLINE value(long double val) : long_double_value(val) {}
+ constexpr FMT_INLINE value(bool val) : bool_value(val) {}
+ constexpr FMT_INLINE value(char_type val) : char_value(val) {}
+ FMT_CONSTEXPR FMT_INLINE value(const char_type* val) {
+ string.data = val;
+ if (is_constant_evaluated()) string.size = {};
+ }
+ FMT_CONSTEXPR FMT_INLINE value(basic_string_view<char_type> val) {
+ string.data = val.data();
+ string.size = val.size();
+ }
+ FMT_INLINE value(const void* val) : pointer(val) {}
+ FMT_INLINE value(const named_arg_info<char_type>* args, size_t size)
+ : named_args{args, size} {}
+
+ template <typename T> FMT_CONSTEXPR FMT_INLINE value(T& val) {
+ using value_type = remove_cvref_t<T>;
+ custom.value = const_cast<value_type*>(&val);
+ // Get the formatter type through the context to allow different contexts
+ // have different extension points, e.g. `formatter<T>` for `format` and
+ // `printf_formatter<T>` for `printf`.
+ custom.format = format_custom_arg<
+ value_type,
+ conditional_t<has_formatter<value_type, Context>::value,
+ typename Context::template formatter_type<value_type>,
+ fallback_formatter<value_type, char_type>>>;
+ }
+ value(unformattable);
+ value(unformattable_char);
+ value(unformattable_const);
+ value(unformattable_pointer);
+
+ private:
+ // Formats an argument of a custom type, such as a user-defined class.
+ template <typename T, typename Formatter>
+ static void format_custom_arg(void* arg,
+ typename Context::parse_context_type& parse_ctx,
+ Context& ctx) {
+ auto f = Formatter();
+ parse_ctx.advance_to(f.parse(parse_ctx));
+ using qualified_type =
+ conditional_t<has_const_formatter<T, Context>(), const T, T>;
+ ctx.advance_to(f.format(*static_cast<qualified_type*>(arg), ctx));
+ }
+};
+
+template <typename Context, typename T>
+FMT_CONSTEXPR auto make_arg(const T& value) -> basic_format_arg<Context>;
+
+// To minimize the number of types we need to deal with, long is translated
+// either to int or to long long depending on its size.
+enum { long_short = sizeof(long) == sizeof(int) };
+using long_type = conditional_t<long_short, int, long long>;
+using ulong_type = conditional_t<long_short, unsigned, unsigned long long>;
+
+// Maps formatting arguments to core types.
+// arg_mapper reports errors by returning unformattable instead of using
+// static_assert because it's used in the is_formattable trait.
+template <typename Context> struct arg_mapper {
+ using char_type = typename Context::char_type;
+
+ FMT_CONSTEXPR FMT_INLINE auto map(signed char val) -> int { return val; }
+ FMT_CONSTEXPR FMT_INLINE auto map(unsigned char val) -> unsigned {
+ return val;
+ }
+ FMT_CONSTEXPR FMT_INLINE auto map(short val) -> int { return val; }
+ FMT_CONSTEXPR FMT_INLINE auto map(unsigned short val) -> unsigned {
+ return val;
+ }
+ FMT_CONSTEXPR FMT_INLINE auto map(int val) -> int { return val; }
+ FMT_CONSTEXPR FMT_INLINE auto map(unsigned val) -> unsigned { return val; }
+ FMT_CONSTEXPR FMT_INLINE auto map(long val) -> long_type { return val; }
+ FMT_CONSTEXPR FMT_INLINE auto map(unsigned long val) -> ulong_type {
+ return val;
+ }
+ FMT_CONSTEXPR FMT_INLINE auto map(long long val) -> long long { return val; }
+ FMT_CONSTEXPR FMT_INLINE auto map(unsigned long long val)
+ -> unsigned long long {
+ return val;
+ }
+ FMT_CONSTEXPR FMT_INLINE auto map(int128_t val) -> int128_t { return val; }
+ FMT_CONSTEXPR FMT_INLINE auto map(uint128_t val) -> uint128_t { return val; }
+ FMT_CONSTEXPR FMT_INLINE auto map(bool val) -> bool { return val; }
+
+ template <typename T, FMT_ENABLE_IF(std::is_same<T, char>::value ||
+ std::is_same<T, char_type>::value)>
+ FMT_CONSTEXPR FMT_INLINE auto map(T val) -> char_type {
+ return val;
+ }
+ template <typename T, enable_if_t<(std::is_same<T, wchar_t>::value ||
+#ifdef __cpp_char8_t
+ std::is_same<T, char8_t>::value ||
+#endif
+ std::is_same<T, char16_t>::value ||
+ std::is_same<T, char32_t>::value) &&
+ !std::is_same<T, char_type>::value,
+ int> = 0>
+ FMT_CONSTEXPR FMT_INLINE auto map(T) -> unformattable_char {
+ return {};
+ }
+
+ FMT_CONSTEXPR FMT_INLINE auto map(float val) -> float { return val; }
+ FMT_CONSTEXPR FMT_INLINE auto map(double val) -> double { return val; }
+ FMT_CONSTEXPR FMT_INLINE auto map(long double val) -> long double {
+ return val;
+ }
+
+ FMT_CONSTEXPR FMT_INLINE auto map(char_type* val) -> const char_type* {
+ return val;
+ }
+ FMT_CONSTEXPR FMT_INLINE auto map(const char_type* val) -> const char_type* {
+ return val;
+ }
+ template <typename T,
+ FMT_ENABLE_IF(is_string<T>::value && !std::is_pointer<T>::value &&
+ std::is_same<char_type, char_t<T>>::value)>
+ FMT_CONSTEXPR FMT_INLINE auto map(const T& val)
+ -> basic_string_view<char_type> {
+ return to_string_view(val);
+ }
+ template <typename T,
+ FMT_ENABLE_IF(is_string<T>::value && !std::is_pointer<T>::value &&
+ !std::is_same<char_type, char_t<T>>::value)>
+ FMT_CONSTEXPR FMT_INLINE auto map(const T&) -> unformattable_char {
+ return {};
+ }
+ template <typename T,
+ FMT_ENABLE_IF(
+ std::is_constructible<basic_string_view<char_type>, T>::value &&
+ !is_string<T>::value && !has_formatter<T, Context>::value &&
+ !has_fallback_formatter<T, char_type>::value)>
+ FMT_CONSTEXPR FMT_INLINE auto map(const T& val)
+ -> basic_string_view<char_type> {
+ return basic_string_view<char_type>(val);
+ }
+ template <
+ typename T,
+ FMT_ENABLE_IF(
+ std::is_constructible<std_string_view<char_type>, T>::value &&
+ !std::is_constructible<basic_string_view<char_type>, T>::value &&
+ !is_string<T>::value && !has_formatter<T, Context>::value &&
+ !has_fallback_formatter<T, char_type>::value)>
+ FMT_CONSTEXPR FMT_INLINE auto map(const T& val)
+ -> basic_string_view<char_type> {
+ return std_string_view<char_type>(val);
+ }
+
+ using cstring_result = conditional_t<std::is_same<char_type, char>::value,
+ const char*, unformattable_pointer>;
+
+ FMT_DEPRECATED FMT_CONSTEXPR FMT_INLINE auto map(const signed char* val)
+ -> cstring_result {
+ return map(reinterpret_cast<const char*>(val));
+ }
+ FMT_DEPRECATED FMT_CONSTEXPR FMT_INLINE auto map(const unsigned char* val)
+ -> cstring_result {
+ return map(reinterpret_cast<const char*>(val));
+ }
+ FMT_DEPRECATED FMT_CONSTEXPR FMT_INLINE auto map(signed char* val)
+ -> cstring_result {
+ return map(reinterpret_cast<const char*>(val));
+ }
+ FMT_DEPRECATED FMT_CONSTEXPR FMT_INLINE auto map(unsigned char* val)
+ -> cstring_result {
+ return map(reinterpret_cast<const char*>(val));
+ }
+
+ FMT_CONSTEXPR FMT_INLINE auto map(void* val) -> const void* { return val; }
+ FMT_CONSTEXPR FMT_INLINE auto map(const void* val) -> const void* {
+ return val;
+ }
+ FMT_CONSTEXPR FMT_INLINE auto map(std::nullptr_t val) -> const void* {
+ return val;
+ }
+
+ // We use SFINAE instead of a const T* parameter to avoid conflicting with
+ // the C array overload.
+ template <
+ typename T,
+ FMT_ENABLE_IF(
+ std::is_member_pointer<T>::value ||
+ std::is_function<typename std::remove_pointer<T>::type>::value ||
+ (std::is_convertible<const T&, const void*>::value &&
+ !std::is_convertible<const T&, const char_type*>::value))>
+ FMT_CONSTEXPR auto map(const T&) -> unformattable_pointer {
+ return {};
+ }
+
+ template <typename T, std::size_t N,
+ FMT_ENABLE_IF(!std::is_same<T, wchar_t>::value)>
+ FMT_CONSTEXPR FMT_INLINE auto map(const T (&values)[N]) -> const T (&)[N] {
+ return values;
+ }
+
+ template <typename T,
+ FMT_ENABLE_IF(
+ std::is_enum<T>::value&& std::is_convertible<T, int>::value &&
+ !has_formatter<T, Context>::value &&
+ !has_fallback_formatter<T, char_type>::value)>
+ FMT_CONSTEXPR FMT_INLINE auto map(const T& val)
+ -> decltype(std::declval<arg_mapper>().map(
+ static_cast<typename std::underlying_type<T>::type>(val))) {
+ return map(static_cast<typename std::underlying_type<T>::type>(val));
+ }
+
+ FMT_CONSTEXPR FMT_INLINE auto map(detail::byte val) -> unsigned {
+ return map(static_cast<unsigned char>(val));
+ }
+
+ template <typename T, typename U = remove_cvref_t<T>>
+ struct formattable
+ : bool_constant<has_const_formatter<U, Context>() ||
+ !std::is_const<remove_reference_t<T>>::value ||
+ has_fallback_formatter<U, char_type>::value> {};
+
+#if FMT_MSC_VER != 0 && FMT_MSC_VER < 1910
+ // Workaround a bug in MSVC.
+ template <typename T> FMT_CONSTEXPR FMT_INLINE auto do_map(T&& val) -> T& {
+ return val;
+ }
+#else
+ template <typename T, FMT_ENABLE_IF(formattable<T>::value)>
+ FMT_CONSTEXPR FMT_INLINE auto do_map(T&& val) -> T& {
+ return val;
+ }
+ template <typename T, FMT_ENABLE_IF(!formattable<T>::value)>
+ FMT_CONSTEXPR FMT_INLINE auto do_map(T&&) -> unformattable_const {
+ return {};
+ }
+#endif
+
+ template <typename T, typename U = remove_cvref_t<T>,
+ FMT_ENABLE_IF(!is_string<U>::value && !is_char<U>::value &&
+ !std::is_array<U>::value &&
+ (has_formatter<U, Context>::value ||
+ has_fallback_formatter<U, char_type>::value))>
+ FMT_CONSTEXPR FMT_INLINE auto map(T&& val)
+ -> decltype(this->do_map(std::forward<T>(val))) {
+ return do_map(std::forward<T>(val));
+ }
+
+ template <typename T, FMT_ENABLE_IF(is_named_arg<T>::value)>
+ FMT_CONSTEXPR FMT_INLINE auto map(const T& named_arg)
+ -> decltype(std::declval<arg_mapper>().map(named_arg.value)) {
+ return map(named_arg.value);
+ }
+
+ auto map(...) -> unformattable { return {}; }
+};
+
+// A type constant after applying arg_mapper<Context>.
+template <typename T, typename Context>
+using mapped_type_constant =
+ type_constant<decltype(arg_mapper<Context>().map(std::declval<const T&>())),
+ typename Context::char_type>;
+
+enum { packed_arg_bits = 4 };
+// Maximum number of arguments with packed types.
+enum { max_packed_args = 62 / packed_arg_bits };
+enum : unsigned long long { is_unpacked_bit = 1ULL << 63 };
+enum : unsigned long long { has_named_args_bit = 1ULL << 62 };
+
+FMT_END_DETAIL_NAMESPACE
+
+// An output iterator that appends to a buffer.
+// It is used to reduce symbol sizes for the common case.
+class appender : public std::back_insert_iterator<detail::buffer<char>> {
+ using base = std::back_insert_iterator<detail::buffer<char>>;
+
+ template <typename T>
+ friend auto get_buffer(appender out) -> detail::buffer<char>& {
+ return detail::get_container(out);
+ }
+
+ public:
+ using std::back_insert_iterator<detail::buffer<char>>::back_insert_iterator;
+ appender(base it) FMT_NOEXCEPT : base(it) {}
+ using _Unchecked_type = appender; // Mark iterator as checked.
+
+ auto operator++() FMT_NOEXCEPT -> appender& { return *this; }
+
+ auto operator++(int) FMT_NOEXCEPT -> appender { return *this; }
+};
+
+// A formatting argument. It is a trivially copyable/constructible type to
+// allow storage in basic_memory_buffer.
+template <typename Context> class basic_format_arg {
+ private:
+ detail::value<Context> value_;
+ detail::type type_;
+
+ template <typename ContextType, typename T>
+ friend FMT_CONSTEXPR auto detail::make_arg(const T& value)
+ -> basic_format_arg<ContextType>;
+
+ template <typename Visitor, typename Ctx>
+ friend FMT_CONSTEXPR auto visit_format_arg(Visitor&& vis,
+ const basic_format_arg<Ctx>& arg)
+ -> decltype(vis(0));
+
+ friend class basic_format_args<Context>;
+ friend class dynamic_format_arg_store<Context>;
+
+ using char_type = typename Context::char_type;
+
+ template <typename T, typename Char, size_t NUM_ARGS, size_t NUM_NAMED_ARGS>
+ friend struct detail::arg_data;
+
+ basic_format_arg(const detail::named_arg_info<char_type>* args, size_t size)
+ : value_(args, size) {}
+
+ public:
+ class handle {
+ public:
+ explicit handle(detail::custom_value<Context> custom) : custom_(custom) {}
+
+ void format(typename Context::parse_context_type& parse_ctx,
+ Context& ctx) const {
+ custom_.format(custom_.value, parse_ctx, ctx);
+ }
+
+ private:
+ detail::custom_value<Context> custom_;
+ };
+
+ constexpr basic_format_arg() : type_(detail::type::none_type) {}
+
+ constexpr explicit operator bool() const FMT_NOEXCEPT {
+ return type_ != detail::type::none_type;
+ }
+
+ auto type() const -> detail::type { return type_; }
+
+ auto is_integral() const -> bool { return detail::is_integral_type(type_); }
+ auto is_arithmetic() const -> bool {
+ return detail::is_arithmetic_type(type_);
+ }
+};
+
+/**
+ \rst
+ Visits an argument dispatching to the appropriate visit method based on
+ the argument type. For example, if the argument type is ``double`` then
+ ``vis(value)`` will be called with the value of type ``double``.
+ \endrst
+ */
+template <typename Visitor, typename Context>
+FMT_CONSTEXPR FMT_INLINE auto visit_format_arg(
+ Visitor&& vis, const basic_format_arg<Context>& arg) -> decltype(vis(0)) {
+ switch (arg.type_) {
+ case detail::type::none_type:
+ break;
+ case detail::type::int_type:
+ return vis(arg.value_.int_value);
+ case detail::type::uint_type:
+ return vis(arg.value_.uint_value);
+ case detail::type::long_long_type:
+ return vis(arg.value_.long_long_value);
+ case detail::type::ulong_long_type:
+ return vis(arg.value_.ulong_long_value);
+ case detail::type::int128_type:
+ return vis(detail::convert_for_visit(arg.value_.int128_value));
+ case detail::type::uint128_type:
+ return vis(detail::convert_for_visit(arg.value_.uint128_value));
+ case detail::type::bool_type:
+ return vis(arg.value_.bool_value);
+ case detail::type::char_type:
+ return vis(arg.value_.char_value);
+ case detail::type::float_type:
+ return vis(arg.value_.float_value);
+ case detail::type::double_type:
+ return vis(arg.value_.double_value);
+ case detail::type::long_double_type:
+ return vis(arg.value_.long_double_value);
+ case detail::type::cstring_type:
+ return vis(arg.value_.string.data);
+ case detail::type::string_type:
+ using sv = basic_string_view<typename Context::char_type>;
+ return vis(sv(arg.value_.string.data, arg.value_.string.size));
+ case detail::type::pointer_type:
+ return vis(arg.value_.pointer);
+ case detail::type::custom_type:
+ return vis(typename basic_format_arg<Context>::handle(arg.value_.custom));
+ }
+ return vis(monostate());
+}
+
+FMT_BEGIN_DETAIL_NAMESPACE
+
+template <typename Char, typename InputIt>
+auto copy_str(InputIt begin, InputIt end, appender out) -> appender {
+ get_container(out).append(begin, end);
+ return out;
+}
+
+#if FMT_GCC_VERSION && FMT_GCC_VERSION < 500
+// A workaround for gcc 4.8 to make void_t work in a SFINAE context.
+template <typename... Ts> struct void_t_impl { using type = void; };
+template <typename... Ts>
+using void_t = typename detail::void_t_impl<Ts...>::type;
+#else
+template <typename...> using void_t = void;
+#endif
+
+template <typename It, typename T, typename Enable = void>
+struct is_output_iterator : std::false_type {};
+
+template <typename It, typename T>
+struct is_output_iterator<
+ It, T,
+ void_t<typename std::iterator_traits<It>::iterator_category,
+ decltype(*std::declval<It>() = std::declval<T>())>>
+ : std::true_type {};
+
+template <typename OutputIt>
+struct is_back_insert_iterator : std::false_type {};
+template <typename Container>
+struct is_back_insert_iterator<std::back_insert_iterator<Container>>
+ : std::true_type {};
+
+template <typename OutputIt>
+struct is_contiguous_back_insert_iterator : std::false_type {};
+template <typename Container>
+struct is_contiguous_back_insert_iterator<std::back_insert_iterator<Container>>
+ : is_contiguous<Container> {};
+template <>
+struct is_contiguous_back_insert_iterator<appender> : std::true_type {};
+
+// A type-erased reference to an std::locale to avoid heavy <locale> include.
+class locale_ref {
+ private:
+ const void* locale_; // A type-erased pointer to std::locale.
+
+ public:
+ constexpr locale_ref() : locale_(nullptr) {}
+ template <typename Locale> explicit locale_ref(const Locale& loc);
+
+ explicit operator bool() const FMT_NOEXCEPT { return locale_ != nullptr; }
+
+ template <typename Locale> auto get() const -> Locale;
+};
+
+template <typename> constexpr auto encode_types() -> unsigned long long {
+ return 0;
+}
+
+template <typename Context, typename Arg, typename... Args>
+constexpr auto encode_types() -> unsigned long long {
+ return static_cast<unsigned>(mapped_type_constant<Arg, Context>::value) |
+ (encode_types<Context, Args...>() << packed_arg_bits);
+}
+
+template <typename Context, typename T>
+FMT_CONSTEXPR auto make_arg(const T& value) -> basic_format_arg<Context> {
+ basic_format_arg<Context> arg;
+ arg.type_ = mapped_type_constant<T, Context>::value;
+ arg.value_ = arg_mapper<Context>().map(value);
+ return arg;
+}
+
+// The type template parameter is there to avoid an ODR violation when using
+// a fallback formatter in one translation unit and an implicit conversion in
+// another (not recommended).
+template <bool IS_PACKED, typename Context, type, typename T,
+ FMT_ENABLE_IF(IS_PACKED)>
+FMT_CONSTEXPR FMT_INLINE auto make_arg(T&& val) -> value<Context> {
+ const auto& arg = arg_mapper<Context>().map(std::forward<T>(val));
+
+ constexpr bool formattable_char =
+ !std::is_same<decltype(arg), const unformattable_char&>::value;
+ static_assert(formattable_char, "Mixing character types is disallowed.");
+
+ constexpr bool formattable_const =
+ !std::is_same<decltype(arg), const unformattable_const&>::value;
+ static_assert(formattable_const, "Cannot format a const argument.");
+
+ // Formatting of arbitrary pointers is disallowed. If you want to output
+ // a pointer cast it to "void *" or "const void *". In particular, this
+ // forbids formatting of "[const] volatile char *" which is printed as bool
+ // by iostreams.
+ constexpr bool formattable_pointer =
+ !std::is_same<decltype(arg), const unformattable_pointer&>::value;
+ static_assert(formattable_pointer,
+ "Formatting of non-void pointers is disallowed.");
+
+ constexpr bool formattable =
+ !std::is_same<decltype(arg), const unformattable&>::value;
+ static_assert(
+ formattable,
+ "Cannot format an argument. To make type T formattable provide a "
+ "formatter<T> specialization: https://fmt.dev/latest/api.html#udt");
+ return {arg};
+}
+
+template <bool IS_PACKED, typename Context, type, typename T,
+ FMT_ENABLE_IF(!IS_PACKED)>
+inline auto make_arg(const T& value) -> basic_format_arg<Context> {
+ return make_arg<Context>(value);
+}
+FMT_END_DETAIL_NAMESPACE
+
+// Formatting context.
+template <typename OutputIt, typename Char> class basic_format_context {
+ public:
+ /** The character type for the output. */
+ using char_type = Char;
+
+ private:
+ OutputIt out_;
+ basic_format_args<basic_format_context> args_;
+ detail::locale_ref loc_;
+
+ public:
+ using iterator = OutputIt;
+ using format_arg = basic_format_arg<basic_format_context>;
+ using parse_context_type = basic_format_parse_context<Char>;
+ template <typename T> using formatter_type = formatter<T, char_type>;
+
+ basic_format_context(basic_format_context&&) = default;
+ basic_format_context(const basic_format_context&) = delete;
+ void operator=(const basic_format_context&) = delete;
+ /**
+ Constructs a ``basic_format_context`` object. References to the arguments are
+ stored in the object so make sure they have appropriate lifetimes.
+ */
+ constexpr basic_format_context(
+ OutputIt out, basic_format_args<basic_format_context> ctx_args,
+ detail::locale_ref loc = detail::locale_ref())
+ : out_(out), args_(ctx_args), loc_(loc) {}
+
+ constexpr auto arg(int id) const -> format_arg { return args_.get(id); }
+ FMT_CONSTEXPR auto arg(basic_string_view<char_type> name) -> format_arg {
+ return args_.get(name);
+ }
+ FMT_CONSTEXPR auto arg_id(basic_string_view<char_type> name) -> int {
+ return args_.get_id(name);
+ }
+ auto args() const -> const basic_format_args<basic_format_context>& {
+ return args_;
+ }
+
+ FMT_CONSTEXPR auto error_handler() -> detail::error_handler { return {}; }
+ void on_error(const char* message) { error_handler().on_error(message); }
+
+ // Returns an iterator to the beginning of the output range.
+ FMT_CONSTEXPR auto out() -> iterator { return out_; }
+
+ // Advances the begin iterator to ``it``.
+ void advance_to(iterator it) {
+ if (!detail::is_back_insert_iterator<iterator>()) out_ = it;
+ }
+
+ FMT_CONSTEXPR auto locale() -> detail::locale_ref { return loc_; }
+};
+
+template <typename Char>
+using buffer_context =
+ basic_format_context<detail::buffer_appender<Char>, Char>;
+using format_context = buffer_context<char>;
+
+// Workaround an alias issue: https://stackoverflow.com/q/62767544/471164.
+#define FMT_BUFFER_CONTEXT(Char) \
+ basic_format_context<detail::buffer_appender<Char>, Char>
+
+template <typename T, typename Char = char>
+using is_formattable = bool_constant<
+ !std::is_base_of<detail::unformattable,
+ decltype(detail::arg_mapper<buffer_context<Char>>().map(
+ std::declval<T>()))>::value &&
+ !detail::has_fallback_formatter<T, Char>::value>;
+
+/**
+ \rst
+ An array of references to arguments. It can be implicitly converted into
+ `~fmt::basic_format_args` for passing into type-erased formatting functions
+ such as `~fmt::vformat`.
+ \endrst
+ */
+template <typename Context, typename... Args>
+class format_arg_store
+#if FMT_GCC_VERSION && FMT_GCC_VERSION < 409
+ // Workaround a GCC template argument substitution bug.
+ : public basic_format_args<Context>
+#endif
+{
+ private:
+ static const size_t num_args = sizeof...(Args);
+ static const size_t num_named_args = detail::count_named_args<Args...>();
+ static const bool is_packed = num_args <= detail::max_packed_args;
+
+ using value_type = conditional_t<is_packed, detail::value<Context>,
+ basic_format_arg<Context>>;
+
+ detail::arg_data<value_type, typename Context::char_type, num_args,
+ num_named_args>
+ data_;
+
+ friend class basic_format_args<Context>;
+
+ static constexpr unsigned long long desc =
+ (is_packed ? detail::encode_types<Context, Args...>()
+ : detail::is_unpacked_bit | num_args) |
+ (num_named_args != 0
+ ? static_cast<unsigned long long>(detail::has_named_args_bit)
+ : 0);
+
+ public:
+ template <typename... T>
+ FMT_CONSTEXPR FMT_INLINE format_arg_store(T&&... args)
+ :
+#if FMT_GCC_VERSION && FMT_GCC_VERSION < 409
+ basic_format_args<Context>(*this),
+#endif
+ data_{detail::make_arg<
+ is_packed, Context,
+ detail::mapped_type_constant<remove_cvref_t<T>, Context>::value>(
+ std::forward<T>(args))...} {
+ detail::init_named_args(data_.named_args(), 0, 0, args...);
+ }
+};
+
+/**
+ \rst
+ Constructs a `~fmt::format_arg_store` object that contains references to
+ arguments and can be implicitly converted to `~fmt::format_args`. `Context`
+ can be omitted in which case it defaults to `~fmt::context`.
+ See `~fmt::arg` for lifetime considerations.
+ \endrst
+ */
+template <typename Context = format_context, typename... Args>
+constexpr auto make_format_args(Args&&... args)
+ -> format_arg_store<Context, remove_cvref_t<Args>...> {
+ return {std::forward<Args>(args)...};
+}
+
+/**
+ \rst
+ Returns a named argument to be used in a formatting function.
+ It should only be used in a call to a formatting function or
+ `dynamic_format_arg_store::push_back`.
+
+ **Example**::
+
+ fmt::print("Elapsed time: {s:.2f} seconds", fmt::arg("s", 1.23));
+ \endrst
+ */
+template <typename Char, typename T>
+inline auto arg(const Char* name, const T& arg) -> detail::named_arg<Char, T> {
+ static_assert(!detail::is_named_arg<T>(), "nested named arguments");
+ return {name, arg};
+}
+
+/**
+ \rst
+ A view of a collection of formatting arguments. To avoid lifetime issues it
+ should only be used as a parameter type in type-erased functions such as
+ ``vformat``::
+
+ void vlog(string_view format_str, format_args args); // OK
+ format_args args = make_format_args(42); // Error: dangling reference
+ \endrst
+ */
+template <typename Context> class basic_format_args {
+ public:
+ using size_type = int;
+ using format_arg = basic_format_arg<Context>;
+
+ private:
+ // A descriptor that contains information about formatting arguments.
+ // If the number of arguments is less or equal to max_packed_args then
+ // argument types are passed in the descriptor. This reduces binary code size
+ // per formatting function call.
+ unsigned long long desc_;
+ union {
+ // If is_packed() returns true then argument values are stored in values_;
+ // otherwise they are stored in args_. This is done to improve cache
+ // locality and reduce compiled code size since storing larger objects
+ // may require more code (at least on x86-64) even if the same amount of
+ // data is actually copied to stack. It saves ~10% on the bloat test.
+ const detail::value<Context>* values_;
+ const format_arg* args_;
+ };
+
+ constexpr auto is_packed() const -> bool {
+ return (desc_ & detail::is_unpacked_bit) == 0;
+ }
+ auto has_named_args() const -> bool {
+ return (desc_ & detail::has_named_args_bit) != 0;
+ }
+
+ FMT_CONSTEXPR auto type(int index) const -> detail::type {
+ int shift = index * detail::packed_arg_bits;
+ unsigned int mask = (1 << detail::packed_arg_bits) - 1;
+ return static_cast<detail::type>((desc_ >> shift) & mask);
+ }
+
+ constexpr FMT_INLINE basic_format_args(unsigned long long desc,
+ const detail::value<Context>* values)
+ : desc_(desc), values_(values) {}
+ constexpr basic_format_args(unsigned long long desc, const format_arg* args)
+ : desc_(desc), args_(args) {}
+
+ public:
+ constexpr basic_format_args() : desc_(0), args_(nullptr) {}
+
+ /**
+ \rst
+ Constructs a `basic_format_args` object from `~fmt::format_arg_store`.
+ \endrst
+ */
+ template <typename... Args>
+ constexpr FMT_INLINE basic_format_args(
+ const format_arg_store<Context, Args...>& store)
+ : basic_format_args(format_arg_store<Context, Args...>::desc,
+ store.data_.args()) {}
+
+ /**
+ \rst
+ Constructs a `basic_format_args` object from
+ `~fmt::dynamic_format_arg_store`.
+ \endrst
+ */
+ constexpr FMT_INLINE basic_format_args(
+ const dynamic_format_arg_store<Context>& store)
+ : basic_format_args(store.get_types(), store.data()) {}
+
+ /**
+ \rst
+ Constructs a `basic_format_args` object from a dynamic set of arguments.
+ \endrst
+ */
+ constexpr basic_format_args(const format_arg* args, int count)
+ : basic_format_args(detail::is_unpacked_bit | detail::to_unsigned(count),
+ args) {}
+
+ /** Returns the argument with the specified id. */
+ FMT_CONSTEXPR auto get(int id) const -> format_arg {
+ format_arg arg;
+ if (!is_packed()) {
+ if (id < max_size()) arg = args_[id];
+ return arg;
+ }
+ if (id >= detail::max_packed_args) return arg;
+ arg.type_ = type(id);
+ if (arg.type_ == detail::type::none_type) return arg;
+ arg.value_ = values_[id];
+ return arg;
+ }
+
+ template <typename Char>
+ auto get(basic_string_view<Char> name) const -> format_arg {
+ int id = get_id(name);
+ return id >= 0 ? get(id) : format_arg();
+ }
+
+ template <typename Char>
+ auto get_id(basic_string_view<Char> name) const -> int {
+ if (!has_named_args()) return -1;
+ const auto& named_args =
+ (is_packed() ? values_[-1] : args_[-1].value_).named_args;
+ for (size_t i = 0; i < named_args.size; ++i) {
+ if (named_args.data[i].name == name) return named_args.data[i].id;
+ }
+ return -1;
+ }
+
+ auto max_size() const -> int {
+ unsigned long long max_packed = detail::max_packed_args;
+ return static_cast<int>(is_packed() ? max_packed
+ : desc_ & ~detail::is_unpacked_bit);
+ }
+};
+
+/** An alias to ``basic_format_args<format_context>``. */
+// A separate type would result in shorter symbols but break ABI compatibility
+// between clang and gcc on ARM (#1919).
+using format_args = basic_format_args<format_context>;
+
+// We cannot use enum classes as bit fields because of a gcc bug
+// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61414.
+namespace align {
+enum type { none, left, right, center, numeric };
+}
+using align_t = align::type;
+namespace sign {
+enum type { none, minus, plus, space };
+}
+using sign_t = sign::type;
+
+FMT_BEGIN_DETAIL_NAMESPACE
+
+// Workaround an array initialization issue in gcc 4.8.
+template <typename Char> struct fill_t {
+ private:
+ enum { max_size = 4 };
+ Char data_[max_size] = {Char(' '), Char(0), Char(0), Char(0)};
+ unsigned char size_ = 1;
+
+ public:
+ FMT_CONSTEXPR void operator=(basic_string_view<Char> s) {
+ auto size = s.size();
+ if (size > max_size) return throw_format_error("invalid fill");
+ for (size_t i = 0; i < size; ++i) data_[i] = s[i];
+ size_ = static_cast<unsigned char>(size);
+ }
+
+ constexpr auto size() const -> size_t { return size_; }
+ constexpr auto data() const -> const Char* { return data_; }
+
+ FMT_CONSTEXPR auto operator[](size_t index) -> Char& { return data_[index]; }
+ FMT_CONSTEXPR auto operator[](size_t index) const -> const Char& {
+ return data_[index];
+ }
+};
+FMT_END_DETAIL_NAMESPACE
+
+enum class presentation_type : unsigned char {
+ none,
+ // Integer types should go first,
+ dec, // 'd'
+ oct, // 'o'
+ hex_lower, // 'x'
+ hex_upper, // 'X'
+ bin_lower, // 'b'
+ bin_upper, // 'B'
+ hexfloat_lower, // 'a'
+ hexfloat_upper, // 'A'
+ exp_lower, // 'e'
+ exp_upper, // 'E'
+ fixed_lower, // 'f'
+ fixed_upper, // 'F'
+ general_lower, // 'g'
+ general_upper, // 'G'
+ chr, // 'c'
+ string, // 's'
+ pointer // 'p'
+};
+
+// Format specifiers for built-in and string types.
+template <typename Char> struct basic_format_specs {
+ int width;
+ int precision;
+ presentation_type type;
+ align_t align : 4;
+ sign_t sign : 3;
+ bool alt : 1; // Alternate form ('#').
+ bool localized : 1;
+ detail::fill_t<Char> fill;
+
+ constexpr basic_format_specs()
+ : width(0),
+ precision(-1),
+ type(presentation_type::none),
+ align(align::none),
+ sign(sign::none),
+ alt(false),
+ localized(false) {}
+};
+
+using format_specs = basic_format_specs<char>;
+
+FMT_BEGIN_DETAIL_NAMESPACE
+
+enum class arg_id_kind { none, index, name };
+
+// An argument reference.
+template <typename Char> struct arg_ref {
+ FMT_CONSTEXPR arg_ref() : kind(arg_id_kind::none), val() {}
+
+ FMT_CONSTEXPR explicit arg_ref(int index)
+ : kind(arg_id_kind::index), val(index) {}
+ FMT_CONSTEXPR explicit arg_ref(basic_string_view<Char> name)
+ : kind(arg_id_kind::name), val(name) {}
+
+ FMT_CONSTEXPR auto operator=(int idx) -> arg_ref& {
+ kind = arg_id_kind::index;
+ val.index = idx;
+ return *this;
+ }
+
+ arg_id_kind kind;
+ union value {
+ FMT_CONSTEXPR value(int id = 0) : index{id} {}
+ FMT_CONSTEXPR value(basic_string_view<Char> n) : name(n) {}
+
+ int index;
+ basic_string_view<Char> name;
+ } val;
+};
+
+// Format specifiers with width and precision resolved at formatting rather
+// than parsing time to allow re-using the same parsed specifiers with
+// different sets of arguments (precompilation of format strings).
+template <typename Char>
+struct dynamic_format_specs : basic_format_specs<Char> {
+ arg_ref<Char> width_ref;
+ arg_ref<Char> precision_ref;
+};
+
+struct auto_id {};
+
+// A format specifier handler that sets fields in basic_format_specs.
+template <typename Char> class specs_setter {
+ protected:
+ basic_format_specs<Char>& specs_;
+
+ public:
+ explicit FMT_CONSTEXPR specs_setter(basic_format_specs<Char>& specs)
+ : specs_(specs) {}
+
+ FMT_CONSTEXPR specs_setter(const specs_setter& other)
+ : specs_(other.specs_) {}
+
+ FMT_CONSTEXPR void on_align(align_t align) { specs_.align = align; }
+ FMT_CONSTEXPR void on_fill(basic_string_view<Char> fill) {
+ specs_.fill = fill;
+ }
+ FMT_CONSTEXPR void on_sign(sign_t s) { specs_.sign = s; }
+ FMT_CONSTEXPR void on_hash() { specs_.alt = true; }
+ FMT_CONSTEXPR void on_localized() { specs_.localized = true; }
+
+ FMT_CONSTEXPR void on_zero() {
+ if (specs_.align == align::none) specs_.align = align::numeric;
+ specs_.fill[0] = Char('0');
+ }
+
+ FMT_CONSTEXPR void on_width(int width) { specs_.width = width; }
+ FMT_CONSTEXPR void on_precision(int precision) {
+ specs_.precision = precision;
+ }
+ FMT_CONSTEXPR void end_precision() {}
+
+ FMT_CONSTEXPR void on_type(presentation_type type) { specs_.type = type; }
+};
+
+// Format spec handler that saves references to arguments representing dynamic
+// width and precision to be resolved at formatting time.
+template <typename ParseContext>
+class dynamic_specs_handler
+ : public specs_setter<typename ParseContext::char_type> {
+ public:
+ using char_type = typename ParseContext::char_type;
+
+ FMT_CONSTEXPR dynamic_specs_handler(dynamic_format_specs<char_type>& specs,
+ ParseContext& ctx)
+ : specs_setter<char_type>(specs), specs_(specs), context_(ctx) {}
+
+ FMT_CONSTEXPR dynamic_specs_handler(const dynamic_specs_handler& other)
+ : specs_setter<char_type>(other),
+ specs_(other.specs_),
+ context_(other.context_) {}
+
+ template <typename Id> FMT_CONSTEXPR void on_dynamic_width(Id arg_id) {
+ specs_.width_ref = make_arg_ref(arg_id);
+ }
+
+ template <typename Id> FMT_CONSTEXPR void on_dynamic_precision(Id arg_id) {
+ specs_.precision_ref = make_arg_ref(arg_id);
+ }
+
+ FMT_CONSTEXPR void on_error(const char* message) {
+ context_.on_error(message);
+ }
+
+ private:
+ dynamic_format_specs<char_type>& specs_;
+ ParseContext& context_;
+
+ using arg_ref_type = arg_ref<char_type>;
+
+ FMT_CONSTEXPR auto make_arg_ref(int arg_id) -> arg_ref_type {
+ context_.check_arg_id(arg_id);
+ return arg_ref_type(arg_id);
+ }
+
+ FMT_CONSTEXPR auto make_arg_ref(auto_id) -> arg_ref_type {
+ return arg_ref_type(context_.next_arg_id());
+ }
+
+ FMT_CONSTEXPR auto make_arg_ref(basic_string_view<char_type> arg_id)
+ -> arg_ref_type {
+ context_.check_arg_id(arg_id);
+ basic_string_view<char_type> format_str(
+ context_.begin(), to_unsigned(context_.end() - context_.begin()));
+ return arg_ref_type(arg_id);
+ }
+};
+
+template <typename Char> constexpr bool is_ascii_letter(Char c) {
+ return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
+}
+
+// Converts a character to ASCII. Returns a number > 127 on conversion failure.
+template <typename Char, FMT_ENABLE_IF(std::is_integral<Char>::value)>
+constexpr auto to_ascii(Char value) -> Char {
+ return value;
+}
+template <typename Char, FMT_ENABLE_IF(std::is_enum<Char>::value)>
+constexpr auto to_ascii(Char value) ->
+ typename std::underlying_type<Char>::type {
+ return value;
+}
+
+template <typename Char>
+FMT_CONSTEXPR auto code_point_length(const Char* begin) -> int {
+ if (const_check(sizeof(Char) != 1)) return 1;
+ auto lengths =
+ "\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\0\0\0\0\0\0\0\0\2\2\2\2\3\3\4";
+ int len = lengths[static_cast<unsigned char>(*begin) >> 3];
+
+ // Compute the pointer to the next character early so that the next
+ // iteration can start working on the next character. Neither Clang
+ // nor GCC figure out this reordering on their own.
+ return len + !len;
+}
+
+// Return the result via the out param to workaround gcc bug 77539.
+template <bool IS_CONSTEXPR, typename T, typename Ptr = const T*>
+FMT_CONSTEXPR auto find(Ptr first, Ptr last, T value, Ptr& out) -> bool {
+ for (out = first; out != last; ++out) {
+ if (*out == value) return true;
+ }
+ return false;
+}
+
+template <>
+inline auto find<false, char>(const char* first, const char* last, char value,
+ const char*& out) -> bool {
+ out = static_cast<const char*>(
+ std::memchr(first, value, to_unsigned(last - first)));
+ return out != nullptr;
+}
+
+// Parses the range [begin, end) as an unsigned integer. This function assumes
+// that the range is non-empty and the first character is a digit.
+template <typename Char>
+FMT_CONSTEXPR auto parse_nonnegative_int(const Char*& begin, const Char* end,
+ int error_value) noexcept -> int {
+ FMT_ASSERT(begin != end && '0' <= *begin && *begin <= '9', "");
+ unsigned value = 0, prev = 0;
+ auto p = begin;
+ do {
+ prev = value;
+ value = value * 10 + unsigned(*p - '0');
+ ++p;
+ } while (p != end && '0' <= *p && *p <= '9');
+ auto num_digits = p - begin;
+ begin = p;
+ if (num_digits <= std::numeric_limits<int>::digits10)
+ return static_cast<int>(value);
+ // Check for overflow.
+ const unsigned max = to_unsigned((std::numeric_limits<int>::max)());
+ return num_digits == std::numeric_limits<int>::digits10 + 1 &&
+ prev * 10ull + unsigned(p[-1] - '0') <= max
+ ? static_cast<int>(value)
+ : error_value;
+}
+
+// Parses fill and alignment.
+template <typename Char, typename Handler>
+FMT_CONSTEXPR auto parse_align(const Char* begin, const Char* end,
+ Handler&& handler) -> const Char* {
+ FMT_ASSERT(begin != end, "");
+ auto align = align::none;
+ auto p = begin + code_point_length(begin);
+ if (p >= end) p = begin;
+ for (;;) {
+ switch (to_ascii(*p)) {
+ case '<':
+ align = align::left;
+ break;
+ case '>':
+ align = align::right;
+ break;
+ case '^':
+ align = align::center;
+ break;
+ default:
+ break;
+ }
+ if (align != align::none) {
+ if (p != begin) {
+ auto c = *begin;
+ if (c == '{')
+ return handler.on_error("invalid fill character '{'"), begin;
+ handler.on_fill(basic_string_view<Char>(begin, to_unsigned(p - begin)));
+ begin = p + 1;
+ } else
+ ++begin;
+ handler.on_align(align);
+ break;
+ } else if (p == begin) {
+ break;
+ }
+ p = begin;
+ }
+ return begin;
+}
+
+template <typename Char> FMT_CONSTEXPR bool is_name_start(Char c) {
+ return ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || '_' == c;
+}
+
+template <typename Char, typename IDHandler>
+FMT_CONSTEXPR auto do_parse_arg_id(const Char* begin, const Char* end,
+ IDHandler&& handler) -> const Char* {
+ FMT_ASSERT(begin != end, "");
+ Char c = *begin;
+ if (c >= '0' && c <= '9') {
+ int index = 0;
+ if (c != '0')
+ index =
+ parse_nonnegative_int(begin, end, (std::numeric_limits<int>::max)());
+ else
+ ++begin;
+ if (begin == end || (*begin != '}' && *begin != ':'))
+ handler.on_error("invalid format string");
+ else
+ handler(index);
+ return begin;
+ }
+ if (!is_name_start(c)) {
+ handler.on_error("invalid format string");
+ return begin;
+ }
+ auto it = begin;
+ do {
+ ++it;
+ } while (it != end && (is_name_start(c = *it) || ('0' <= c && c <= '9')));
+ handler(basic_string_view<Char>(begin, to_unsigned(it - begin)));
+ return it;
+}
+
+template <typename Char, typename IDHandler>
+FMT_CONSTEXPR FMT_INLINE auto parse_arg_id(const Char* begin, const Char* end,
+ IDHandler&& handler) -> const Char* {
+ Char c = *begin;
+ if (c != '}' && c != ':') return do_parse_arg_id(begin, end, handler);
+ handler();
+ return begin;
+}
+
+template <typename Char, typename Handler>
+FMT_CONSTEXPR auto parse_width(const Char* begin, const Char* end,
+ Handler&& handler) -> const Char* {
+ using detail::auto_id;
+ struct width_adapter {
+ Handler& handler;
+
+ FMT_CONSTEXPR void operator()() { handler.on_dynamic_width(auto_id()); }
+ FMT_CONSTEXPR void operator()(int id) { handler.on_dynamic_width(id); }
+ FMT_CONSTEXPR void operator()(basic_string_view<Char> id) {
+ handler.on_dynamic_width(id);
+ }
+ FMT_CONSTEXPR void on_error(const char* message) {
+ if (message) handler.on_error(message);
+ }
+ };
+
+ FMT_ASSERT(begin != end, "");
+ if ('0' <= *begin && *begin <= '9') {
+ int width = parse_nonnegative_int(begin, end, -1);
+ if (width != -1)
+ handler.on_width(width);
+ else
+ handler.on_error("number is too big");
+ } else if (*begin == '{') {
+ ++begin;
+ if (begin != end) begin = parse_arg_id(begin, end, width_adapter{handler});
+ if (begin == end || *begin != '}')
+ return handler.on_error("invalid format string"), begin;
+ ++begin;
+ }
+ return begin;
+}
+
+template <typename Char, typename Handler>
+FMT_CONSTEXPR auto parse_precision(const Char* begin, const Char* end,
+ Handler&& handler) -> const Char* {
+ using detail::auto_id;
+ struct precision_adapter {
+ Handler& handler;
+
+ FMT_CONSTEXPR void operator()() { handler.on_dynamic_precision(auto_id()); }
+ FMT_CONSTEXPR void operator()(int id) { handler.on_dynamic_precision(id); }
+ FMT_CONSTEXPR void operator()(basic_string_view<Char> id) {
+ handler.on_dynamic_precision(id);
+ }
+ FMT_CONSTEXPR void on_error(const char* message) {
+ if (message) handler.on_error(message);
+ }
+ };
+
+ ++begin;
+ auto c = begin != end ? *begin : Char();
+ if ('0' <= c && c <= '9') {
+ auto precision = parse_nonnegative_int(begin, end, -1);
+ if (precision != -1)
+ handler.on_precision(precision);
+ else
+ handler.on_error("number is too big");
+ } else if (c == '{') {
+ ++begin;
+ if (begin != end)
+ begin = parse_arg_id(begin, end, precision_adapter{handler});
+ if (begin == end || *begin++ != '}')
+ return handler.on_error("invalid format string"), begin;
+ } else {
+ return handler.on_error("missing precision specifier"), begin;
+ }
+ handler.end_precision();
+ return begin;
+}
+
+template <typename Char>
+FMT_CONSTEXPR auto parse_presentation_type(Char type) -> presentation_type {
+ switch (to_ascii(type)) {
+ case 'd':
+ return presentation_type::dec;
+ case 'o':
+ return presentation_type::oct;
+ case 'x':
+ return presentation_type::hex_lower;
+ case 'X':
+ return presentation_type::hex_upper;
+ case 'b':
+ return presentation_type::bin_lower;
+ case 'B':
+ return presentation_type::bin_upper;
+ case 'a':
+ return presentation_type::hexfloat_lower;
+ case 'A':
+ return presentation_type::hexfloat_upper;
+ case 'e':
+ return presentation_type::exp_lower;
+ case 'E':
+ return presentation_type::exp_upper;
+ case 'f':
+ return presentation_type::fixed_lower;
+ case 'F':
+ return presentation_type::fixed_upper;
+ case 'g':
+ return presentation_type::general_lower;
+ case 'G':
+ return presentation_type::general_upper;
+ case 'c':
+ return presentation_type::chr;
+ case 's':
+ return presentation_type::string;
+ case 'p':
+ return presentation_type::pointer;
+ default:
+ return presentation_type::none;
+ }
+}
+
+// Parses standard format specifiers and sends notifications about parsed
+// components to handler.
+template <typename Char, typename SpecHandler>
+FMT_CONSTEXPR FMT_INLINE auto parse_format_specs(const Char* begin,
+ const Char* end,
+ SpecHandler&& handler)
+ -> const Char* {
+ if (1 < end - begin && begin[1] == '}' && is_ascii_letter(*begin) &&
+ *begin != 'L') {
+ presentation_type type = parse_presentation_type(*begin++);
+ if (type == presentation_type::none)
+ handler.on_error("invalid type specifier");
+ handler.on_type(type);
+ return begin;
+ }
+
+ if (begin == end) return begin;
+
+ begin = parse_align(begin, end, handler);
+ if (begin == end) return begin;
+
+ // Parse sign.
+ switch (to_ascii(*begin)) {
+ case '+':
+ handler.on_sign(sign::plus);
+ ++begin;
+ break;
+ case '-':
+ handler.on_sign(sign::minus);
+ ++begin;
+ break;
+ case ' ':
+ handler.on_sign(sign::space);
+ ++begin;
+ break;
+ default:
+ break;
+ }
+ if (begin == end) return begin;
+
+ if (*begin == '#') {
+ handler.on_hash();
+ if (++begin == end) return begin;
+ }
+
+ // Parse zero flag.
+ if (*begin == '0') {
+ handler.on_zero();
+ if (++begin == end) return begin;
+ }
+
+ begin = parse_width(begin, end, handler);
+ if (begin == end) return begin;
+
+ // Parse precision.
+ if (*begin == '.') {
+ begin = parse_precision(begin, end, handler);
+ if (begin == end) return begin;
+ }
+
+ if (*begin == 'L') {
+ handler.on_localized();
+ ++begin;
+ }
+
+ // Parse type.
+ if (begin != end && *begin != '}') {
+ presentation_type type = parse_presentation_type(*begin++);
+ if (type == presentation_type::none)
+ handler.on_error("invalid type specifier");
+ handler.on_type(type);
+ }
+ return begin;
+}
+
+template <typename Char, typename Handler>
+FMT_CONSTEXPR auto parse_replacement_field(const Char* begin, const Char* end,
+ Handler&& handler) -> const Char* {
+ struct id_adapter {
+ Handler& handler;
+ int arg_id;
+
+ FMT_CONSTEXPR void operator()() { arg_id = handler.on_arg_id(); }
+ FMT_CONSTEXPR void operator()(int id) { arg_id = handler.on_arg_id(id); }
+ FMT_CONSTEXPR void operator()(basic_string_view<Char> id) {
+ arg_id = handler.on_arg_id(id);
+ }
+ FMT_CONSTEXPR void on_error(const char* message) {
+ if (message) handler.on_error(message);
+ }
+ };
+
+ ++begin;
+ if (begin == end) return handler.on_error("invalid format string"), end;
+ if (*begin == '}') {
+ handler.on_replacement_field(handler.on_arg_id(), begin);
+ } else if (*begin == '{') {
+ handler.on_text(begin, begin + 1);
+ } else {
+ auto adapter = id_adapter{handler, 0};
+ begin = parse_arg_id(begin, end, adapter);
+ Char c = begin != end ? *begin : Char();
+ if (c == '}') {
+ handler.on_replacement_field(adapter.arg_id, begin);
+ } else if (c == ':') {
+ begin = handler.on_format_specs(adapter.arg_id, begin + 1, end);
+ if (begin == end || *begin != '}')
+ return handler.on_error("unknown format specifier"), end;
+ } else {
+ return handler.on_error("missing '}' in format string"), end;
+ }
+ }
+ return begin + 1;
+}
+
+template <bool IS_CONSTEXPR, typename Char, typename Handler>
+FMT_CONSTEXPR FMT_INLINE void parse_format_string(
+ basic_string_view<Char> format_str, Handler&& handler) {
+ // Workaround a name-lookup bug in MSVC's modules implementation.
+ using detail::find;
+
+ auto begin = format_str.data();
+ auto end = begin + format_str.size();
+ if (end - begin < 32) {
+ // Use a simple loop instead of memchr for small strings.
+ const Char* p = begin;
+ while (p != end) {
+ auto c = *p++;
+ if (c == '{') {
+ handler.on_text(begin, p - 1);
+ begin = p = parse_replacement_field(p - 1, end, handler);
+ } else if (c == '}') {
+ if (p == end || *p != '}')
+ return handler.on_error("unmatched '}' in format string");
+ handler.on_text(begin, p);
+ begin = ++p;
+ }
+ }
+ handler.on_text(begin, end);
+ return;
+ }
+ struct writer {
+ FMT_CONSTEXPR void operator()(const Char* pbegin, const Char* pend) {
+ if (pbegin == pend) return;
+ for (;;) {
+ const Char* p = nullptr;
+ if (!find<IS_CONSTEXPR>(pbegin, pend, Char('}'), p))
+ return handler_.on_text(pbegin, pend);
+ ++p;
+ if (p == pend || *p != '}')
+ return handler_.on_error("unmatched '}' in format string");
+ handler_.on_text(pbegin, p);
+ pbegin = p + 1;
+ }
+ }
+ Handler& handler_;
+ } write{handler};
+ while (begin != end) {
+ // Doing two passes with memchr (one for '{' and another for '}') is up to
+ // 2.5x faster than the naive one-pass implementation on big format strings.
+ const Char* p = begin;
+ if (*begin != '{' && !find<IS_CONSTEXPR>(begin + 1, end, Char('{'), p))
+ return write(begin, end);
+ write(begin, p);
+ begin = parse_replacement_field(p, end, handler);
+ }
+}
+
+template <typename T, typename ParseContext>
+FMT_CONSTEXPR auto parse_format_specs(ParseContext& ctx)
+ -> decltype(ctx.begin()) {
+ using char_type = typename ParseContext::char_type;
+ using context = buffer_context<char_type>;
+ using mapped_type = conditional_t<
+ mapped_type_constant<T, context>::value != type::custom_type,
+ decltype(arg_mapper<context>().map(std::declval<const T&>())), T>;
+ auto f = conditional_t<has_formatter<mapped_type, context>::value,
+ formatter<mapped_type, char_type>,
+ fallback_formatter<T, char_type>>();
+ return f.parse(ctx);
+}
+
+// A parse context with extra argument id checks. It is only used at compile
+// time because adding checks at runtime would introduce substantial overhead
+// and would be redundant since argument ids are checked when arguments are
+// retrieved anyway.
+template <typename Char, typename ErrorHandler = error_handler>
+class compile_parse_context
+ : public basic_format_parse_context<Char, ErrorHandler> {
+ private:
+ int num_args_;
+ using base = basic_format_parse_context<Char, ErrorHandler>;
+
+ public:
+ explicit FMT_CONSTEXPR compile_parse_context(
+ basic_string_view<Char> format_str,
+ int num_args = (std::numeric_limits<int>::max)(), ErrorHandler eh = {})
+ : base(format_str, eh), num_args_(num_args) {}
+
+ FMT_CONSTEXPR auto next_arg_id() -> int {
+ int id = base::next_arg_id();
+ if (id >= num_args_) this->on_error("argument not found");
+ return id;
+ }
+
+ FMT_CONSTEXPR void check_arg_id(int id) {
+ base::check_arg_id(id);
+ if (id >= num_args_) this->on_error("argument not found");
+ }
+ using base::check_arg_id;
+};
+
+template <typename ErrorHandler>
+FMT_CONSTEXPR void check_int_type_spec(presentation_type type,
+ ErrorHandler&& eh) {
+ if (type > presentation_type::bin_upper && type != presentation_type::chr)
+ eh.on_error("invalid type specifier");
+}
+
+// Checks char specs and returns true if the type spec is char (and not int).
+template <typename Char, typename ErrorHandler = error_handler>
+FMT_CONSTEXPR auto check_char_specs(const basic_format_specs<Char>& specs,
+ ErrorHandler&& eh = {}) -> bool {
+ if (specs.type != presentation_type::none &&
+ specs.type != presentation_type::chr) {
+ check_int_type_spec(specs.type, eh);
+ return false;
+ }
+ if (specs.align == align::numeric || specs.sign != sign::none || specs.alt)
+ eh.on_error("invalid format specifier for char");
+ return true;
+}
+
+// A floating-point presentation format.
+enum class float_format : unsigned char {
+ general, // General: exponent notation or fixed point based on magnitude.
+ exp, // Exponent notation with the default precision of 6, e.g. 1.2e-3.
+ fixed, // Fixed point with the default precision of 6, e.g. 0.0012.
+ hex
+};
+
+struct float_specs {
+ int precision;
+ float_format format : 8;
+ sign_t sign : 8;
+ bool upper : 1;
+ bool locale : 1;
+ bool binary32 : 1;
+ bool fallback : 1;
+ bool showpoint : 1;
+};
+
+template <typename ErrorHandler = error_handler, typename Char>
+FMT_CONSTEXPR auto parse_float_type_spec(const basic_format_specs<Char>& specs,
+ ErrorHandler&& eh = {})
+ -> float_specs {
+ auto result = float_specs();
+ result.showpoint = specs.alt;
+ result.locale = specs.localized;
+ switch (specs.type) {
+ case presentation_type::none:
+ result.format = float_format::general;
+ break;
+ case presentation_type::general_upper:
+ result.upper = true;
+ FMT_FALLTHROUGH;
+ case presentation_type::general_lower:
+ result.format = float_format::general;
+ break;
+ case presentation_type::exp_upper:
+ result.upper = true;
+ FMT_FALLTHROUGH;
+ case presentation_type::exp_lower:
+ result.format = float_format::exp;
+ result.showpoint |= specs.precision != 0;
+ break;
+ case presentation_type::fixed_upper:
+ result.upper = true;
+ FMT_FALLTHROUGH;
+ case presentation_type::fixed_lower:
+ result.format = float_format::fixed;
+ result.showpoint |= specs.precision != 0;
+ break;
+ case presentation_type::hexfloat_upper:
+ result.upper = true;
+ FMT_FALLTHROUGH;
+ case presentation_type::hexfloat_lower:
+ result.format = float_format::hex;
+ break;
+ default:
+ eh.on_error("invalid type specifier");
+ break;
+ }
+ return result;
+}
+
+template <typename ErrorHandler = error_handler>
+FMT_CONSTEXPR auto check_cstring_type_spec(presentation_type type,
+ ErrorHandler&& eh = {}) -> bool {
+ if (type == presentation_type::none || type == presentation_type::string)
+ return true;
+ if (type != presentation_type::pointer) eh.on_error("invalid type specifier");
+ return false;
+}
+
+template <typename ErrorHandler = error_handler>
+FMT_CONSTEXPR void check_string_type_spec(presentation_type type,
+ ErrorHandler&& eh = {}) {
+ if (type != presentation_type::none && type != presentation_type::string)
+ eh.on_error("invalid type specifier");
+}
+
+template <typename ErrorHandler>
+FMT_CONSTEXPR void check_pointer_type_spec(presentation_type type,
+ ErrorHandler&& eh) {
+ if (type != presentation_type::none && type != presentation_type::pointer)
+ eh.on_error("invalid type specifier");
+}
+
+// A parse_format_specs handler that checks if specifiers are consistent with
+// the argument type.
+template <typename Handler> class specs_checker : public Handler {
+ private:
+ detail::type arg_type_;
+
+ FMT_CONSTEXPR void require_numeric_argument() {
+ if (!is_arithmetic_type(arg_type_))
+ this->on_error("format specifier requires numeric argument");
+ }
+
+ public:
+ FMT_CONSTEXPR specs_checker(const Handler& handler, detail::type arg_type)
+ : Handler(handler), arg_type_(arg_type) {}
+
+ FMT_CONSTEXPR void on_align(align_t align) {
+ if (align == align::numeric) require_numeric_argument();
+ Handler::on_align(align);
+ }
+
+ FMT_CONSTEXPR void on_sign(sign_t s) {
+ require_numeric_argument();
+ if (is_integral_type(arg_type_) && arg_type_ != type::int_type &&
+ arg_type_ != type::long_long_type && arg_type_ != type::char_type) {
+ this->on_error("format specifier requires signed argument");
+ }
+ Handler::on_sign(s);
+ }
+
+ FMT_CONSTEXPR void on_hash() {
+ require_numeric_argument();
+ Handler::on_hash();
+ }
+
+ FMT_CONSTEXPR void on_localized() {
+ require_numeric_argument();
+ Handler::on_localized();
+ }
+
+ FMT_CONSTEXPR void on_zero() {
+ require_numeric_argument();
+ Handler::on_zero();
+ }
+
+ FMT_CONSTEXPR void end_precision() {
+ if (is_integral_type(arg_type_) || arg_type_ == type::pointer_type)
+ this->on_error("precision not allowed for this argument type");
+ }
+};
+
+constexpr int invalid_arg_index = -1;
+
+#if FMT_USE_NONTYPE_TEMPLATE_PARAMETERS
+template <int N, typename T, typename... Args, typename Char>
+constexpr auto get_arg_index_by_name(basic_string_view<Char> name) -> int {
+ if constexpr (detail::is_statically_named_arg<T>()) {
+ if (name == T::name) return N;
+ }
+ if constexpr (sizeof...(Args) > 0)
+ return get_arg_index_by_name<N + 1, Args...>(name);
+ (void)name; // Workaround an MSVC bug about "unused" parameter.
+ return invalid_arg_index;
+}
+#endif
+
+template <typename... Args, typename Char>
+FMT_CONSTEXPR auto get_arg_index_by_name(basic_string_view<Char> name) -> int {
+#if FMT_USE_NONTYPE_TEMPLATE_PARAMETERS
+ if constexpr (sizeof...(Args) > 0)
+ return get_arg_index_by_name<0, Args...>(name);
+#endif
+ (void)name;
+ return invalid_arg_index;
+}
+
+template <typename Char, typename ErrorHandler, typename... Args>
+class format_string_checker {
+ private:
+ using parse_context_type = compile_parse_context<Char, ErrorHandler>;
+ enum { num_args = sizeof...(Args) };
+
+ // Format specifier parsing function.
+ using parse_func = const Char* (*)(parse_context_type&);
+
+ parse_context_type context_;
+ parse_func parse_funcs_[num_args > 0 ? num_args : 1];
+
+ public:
+ explicit FMT_CONSTEXPR format_string_checker(
+ basic_string_view<Char> format_str, ErrorHandler eh)
+ : context_(format_str, num_args, eh),
+ parse_funcs_{&parse_format_specs<Args, parse_context_type>...} {}
+
+ FMT_CONSTEXPR void on_text(const Char*, const Char*) {}
+
+ FMT_CONSTEXPR auto on_arg_id() -> int { return context_.next_arg_id(); }
+ FMT_CONSTEXPR auto on_arg_id(int id) -> int {
+ return context_.check_arg_id(id), id;
+ }
+ FMT_CONSTEXPR auto on_arg_id(basic_string_view<Char> id) -> int {
+#if FMT_USE_NONTYPE_TEMPLATE_PARAMETERS
+ auto index = get_arg_index_by_name<Args...>(id);
+ if (index == invalid_arg_index) on_error("named argument is not found");
+ return context_.check_arg_id(index), index;
+#else
+ (void)id;
+ on_error("compile-time checks for named arguments require C++20 support");
+ return 0;
+#endif
+ }
+
+ FMT_CONSTEXPR void on_replacement_field(int, const Char*) {}
+
+ FMT_CONSTEXPR auto on_format_specs(int id, const Char* begin, const Char*)
+ -> const Char* {
+ context_.advance_to(context_.begin() + (begin - &*context_.begin()));
+ // id >= 0 check is a workaround for gcc 10 bug (#2065).
+ return id >= 0 && id < num_args ? parse_funcs_[id](context_) : begin;
+ }
+
+ FMT_CONSTEXPR void on_error(const char* message) {
+ context_.on_error(message);
+ }
+};
+
+template <typename... Args, typename S,
+ enable_if_t<(is_compile_string<S>::value), int>>
+void check_format_string(S format_str) {
+ FMT_CONSTEXPR auto s = to_string_view(format_str);
+ using checker = format_string_checker<typename S::char_type, error_handler,
+ remove_cvref_t<Args>...>;
+ FMT_CONSTEXPR bool invalid_format =
+ (parse_format_string<true>(s, checker(s, {})), true);
+ ignore_unused(invalid_format);
+}
+
+template <typename Char>
+void vformat_to(
+ buffer<Char>& buf, basic_string_view<Char> fmt,
+ basic_format_args<FMT_BUFFER_CONTEXT(type_identity_t<Char>)> args,
+ locale_ref loc = {});
+
+FMT_API void vprint_mojibake(std::FILE*, string_view, format_args);
+#ifndef _WIN32
+inline void vprint_mojibake(std::FILE*, string_view, format_args) {}
+#endif
+FMT_END_DETAIL_NAMESPACE
+
+// A formatter specialization for the core types corresponding to detail::type
+// constants.
+template <typename T, typename Char>
+struct formatter<T, Char,
+ enable_if_t<detail::type_constant<T, Char>::value !=
+ detail::type::custom_type>> {
+ private:
+ detail::dynamic_format_specs<Char> specs_;
+
+ public:
+ // Parses format specifiers stopping either at the end of the range or at the
+ // terminating '}'.
+ template <typename ParseContext>
+ FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
+ auto begin = ctx.begin(), end = ctx.end();
+ if (begin == end) return begin;
+ using handler_type = detail::dynamic_specs_handler<ParseContext>;
+ auto type = detail::type_constant<T, Char>::value;
+ auto checker =
+ detail::specs_checker<handler_type>(handler_type(specs_, ctx), type);
+ auto it = detail::parse_format_specs(begin, end, checker);
+ auto eh = ctx.error_handler();
+ switch (type) {
+ case detail::type::none_type:
+ FMT_ASSERT(false, "invalid argument type");
+ break;
+ case detail::type::bool_type:
+ if (specs_.type == presentation_type::none ||
+ specs_.type == presentation_type::string) {
+ break;
+ }
+ FMT_FALLTHROUGH;
+ case detail::type::int_type:
+ case detail::type::uint_type:
+ case detail::type::long_long_type:
+ case detail::type::ulong_long_type:
+ case detail::type::int128_type:
+ case detail::type::uint128_type:
+ detail::check_int_type_spec(specs_.type, eh);
+ break;
+ case detail::type::char_type:
+ detail::check_char_specs(specs_, eh);
+ break;
+ case detail::type::float_type:
+ if (detail::const_check(FMT_USE_FLOAT))
+ detail::parse_float_type_spec(specs_, eh);
+ else
+ FMT_ASSERT(false, "float support disabled");
+ break;
+ case detail::type::double_type:
+ if (detail::const_check(FMT_USE_DOUBLE))
+ detail::parse_float_type_spec(specs_, eh);
+ else
+ FMT_ASSERT(false, "double support disabled");
+ break;
+ case detail::type::long_double_type:
+ if (detail::const_check(FMT_USE_LONG_DOUBLE))
+ detail::parse_float_type_spec(specs_, eh);
+ else
+ FMT_ASSERT(false, "long double support disabled");
+ break;
+ case detail::type::cstring_type:
+ detail::check_cstring_type_spec(specs_.type, eh);
+ break;
+ case detail::type::string_type:
+ detail::check_string_type_spec(specs_.type, eh);
+ break;
+ case detail::type::pointer_type:
+ detail::check_pointer_type_spec(specs_.type, eh);
+ break;
+ case detail::type::custom_type:
+ // Custom format specifiers are checked in parse functions of
+ // formatter specializations.
+ break;
+ }
+ return it;
+ }
+
+ template <typename FormatContext>
+ FMT_CONSTEXPR auto format(const T& val, FormatContext& ctx) const
+ -> decltype(ctx.out());
+};
+
+template <typename Char> struct basic_runtime { basic_string_view<Char> str; };
+
+/** A compile-time format string. */
+template <typename Char, typename... Args> class basic_format_string {
+ private:
+ basic_string_view<Char> str_;
+
+ public:
+ template <typename S,
+ FMT_ENABLE_IF(
+ std::is_convertible<const S&, basic_string_view<Char>>::value)>
+ FMT_CONSTEVAL FMT_INLINE basic_format_string(const S& s) : str_(s) {
+ static_assert(
+ detail::count<
+ (std::is_base_of<detail::view, remove_reference_t<Args>>::value &&
+ std::is_reference<Args>::value)...>() == 0,
+ "passing views as lvalues is disallowed");
+#ifdef FMT_HAS_CONSTEVAL
+ if constexpr (detail::count_named_args<Args...>() ==
+ detail::count_statically_named_args<Args...>()) {
+ using checker = detail::format_string_checker<Char, detail::error_handler,
+ remove_cvref_t<Args>...>;
+ detail::parse_format_string<true>(str_, checker(s, {}));
+ }
+#else
+ detail::check_format_string<Args...>(s);
+#endif
+ }
+ basic_format_string(basic_runtime<Char> r) : str_(r.str) {}
+
+ FMT_INLINE operator basic_string_view<Char>() const { return str_; }
+};
+
+#if FMT_GCC_VERSION && FMT_GCC_VERSION < 409
+// Workaround broken conversion on older gcc.
+template <typename... Args> using format_string = string_view;
+template <typename S> auto runtime(const S& s) -> basic_string_view<char_t<S>> {
+ return s;
+}
+#else
+template <typename... Args>
+using format_string = basic_format_string<char, type_identity_t<Args>...>;
+/**
+ \rst
+ Creates a runtime format string.
+
+ **Example**::
+
+ // Check format string at runtime instead of compile-time.
+ fmt::print(fmt::runtime("{:d}"), "I am not a number");
+ \endrst
+ */
+template <typename S> auto runtime(const S& s) -> basic_runtime<char_t<S>> {
+ return {{s}};
+}
+#endif
+
+FMT_API auto vformat(string_view fmt, format_args args) -> std::string;
+
+/**
+ \rst
+ Formats ``args`` according to specifications in ``fmt`` and returns the result
+ as a string.
+
+ **Example**::
+
+ #include <fmt/core.h>
+ std::string message = fmt::format("The answer is {}.", 42);
+ \endrst
+*/
+template <typename... T>
+FMT_NODISCARD FMT_INLINE auto format(format_string<T...> fmt, T&&... args)
+ -> std::string {
+ return vformat(fmt, fmt::make_format_args(args...));
+}
+
+/** Formats a string and writes the output to ``out``. */
+template <typename OutputIt,
+ FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, char>::value)>
+auto vformat_to(OutputIt out, string_view fmt, format_args args) -> OutputIt {
+ using detail::get_buffer;
+ auto&& buf = get_buffer<char>(out);
+ detail::vformat_to(buf, fmt, args, {});
+ return detail::get_iterator(buf);
+}
+
+/**
+ \rst
+ Formats ``args`` according to specifications in ``fmt``, writes the result to
+ the output iterator ``out`` and returns the iterator past the end of the output
+ range. `format_to` does not append a terminating null character.
+
+ **Example**::
+
+ auto out = std::vector<char>();
+ fmt::format_to(std::back_inserter(out), "{}", 42);
+ \endrst
+ */
+template <typename OutputIt, typename... T,
+ FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, char>::value)>
+FMT_INLINE auto format_to(OutputIt out, format_string<T...> fmt, T&&... args)
+ -> OutputIt {
+ return vformat_to(out, fmt, fmt::make_format_args(args...));
+}
+
+template <typename OutputIt> struct format_to_n_result {
+ /** Iterator past the end of the output range. */
+ OutputIt out;
+ /** Total (not truncated) output size. */
+ size_t size;
+};
+
+template <typename OutputIt, typename... T,
+ FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, char>::value)>
+auto vformat_to_n(OutputIt out, size_t n, string_view fmt, format_args args)
+ -> format_to_n_result<OutputIt> {
+ using traits = detail::fixed_buffer_traits;
+ auto buf = detail::iterator_buffer<OutputIt, char, traits>(out, n);
+ detail::vformat_to(buf, fmt, args, {});
+ return {buf.out(), buf.count()};
+}
+
+/**
+ \rst
+ Formats ``args`` according to specifications in ``fmt``, writes up to ``n``
+ characters of the result to the output iterator ``out`` and returns the total
+ (not truncated) output size and the iterator past the end of the output range.
+ `format_to_n` does not append a terminating null character.
+ \endrst
+ */
+template <typename OutputIt, typename... T,
+ FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, char>::value)>
+FMT_INLINE auto format_to_n(OutputIt out, size_t n, format_string<T...> fmt,
+ T&&... args) -> format_to_n_result<OutputIt> {
+ return vformat_to_n(out, n, fmt, fmt::make_format_args(args...));
+}
+
+/** Returns the number of chars in the output of ``format(fmt, args...)``. */
+template <typename... T>
+FMT_NODISCARD FMT_INLINE auto formatted_size(format_string<T...> fmt,
+ T&&... args) -> size_t {
+ auto buf = detail::counting_buffer<>();
+ detail::vformat_to(buf, string_view(fmt), fmt::make_format_args(args...), {});
+ return buf.count();
+}
+
+FMT_API void vprint(string_view fmt, format_args args);
+FMT_API void vprint(std::FILE* f, string_view fmt, format_args args);
+
+/**
+ \rst
+ Formats ``args`` according to specifications in ``fmt`` and writes the output
+ to ``stdout``.
+
+ **Example**::
+
+ fmt::print("Elapsed time: {0:.2f} seconds", 1.23);
+ \endrst
+ */
+template <typename... T>
+FMT_INLINE void print(format_string<T...> fmt, T&&... args) {
+ const auto& vargs = fmt::make_format_args(args...);
+ return detail::is_utf8() ? vprint(fmt, vargs)
+ : detail::vprint_mojibake(stdout, fmt, vargs);
+}
+
+/**
+ \rst
+ Formats ``args`` according to specifications in ``fmt`` and writes the
+ output to the file ``f``.
+
+ **Example**::
+
+ fmt::print(stderr, "Don't {}!", "panic");
+ \endrst
+ */
+template <typename... T>
+FMT_INLINE void print(std::FILE* f, format_string<T...> fmt, T&&... args) {
+ const auto& vargs = fmt::make_format_args(args...);
+ return detail::is_utf8() ? vprint(f, fmt, vargs)
+ : detail::vprint_mojibake(f, fmt, vargs);
+}
+
+FMT_MODULE_EXPORT_END
+FMT_GCC_PRAGMA("GCC pop_options")
+FMT_END_NAMESPACE
+
+#ifdef FMT_HEADER_ONLY
+# include "format.h"
+#endif
+#endif // FMT_CORE_H_
diff --git a/extern/fmtlib/include/fmt/format-inl.h b/extern/fmtlib/include/fmt/format-inl.h
new file mode 100644
index 00000000000..2c51c50aeb2
--- /dev/null
+++ b/extern/fmtlib/include/fmt/format-inl.h
@@ -0,0 +1,2643 @@
+// Formatting library for C++ - implementation
+//
+// Copyright (c) 2012 - 2016, Victor Zverovich
+// All rights reserved.
+//
+// For the license information refer to format.h.
+
+#ifndef FMT_FORMAT_INL_H_
+#define FMT_FORMAT_INL_H_
+
+#include <algorithm>
+#include <cctype>
+#include <cerrno> // errno
+#include <climits>
+#include <cmath>
+#include <cstdarg>
+#include <cstring> // std::memmove
+#include <cwchar>
+#include <exception>
+
+#ifndef FMT_STATIC_THOUSANDS_SEPARATOR
+# include <locale>
+#endif
+
+#ifdef _WIN32
+# include <io.h> // _isatty
+#endif
+
+#include "format.h"
+
+FMT_BEGIN_NAMESPACE
+namespace detail {
+
+FMT_FUNC void assert_fail(const char* file, int line, const char* message) {
+ // Use unchecked std::fprintf to avoid triggering another assertion when
+ // writing to stderr fails
+ std::fprintf(stderr, "%s:%d: assertion failed: %s", file, line, message);
+ // Chosen instead of std::abort to satisfy Clang in CUDA mode during device
+ // code pass.
+ std::terminate();
+}
+
+FMT_FUNC void throw_format_error(const char* message) {
+ FMT_THROW(format_error(message));
+}
+
+#ifndef _MSC_VER
+# define FMT_SNPRINTF snprintf
+#else // _MSC_VER
+inline int fmt_snprintf(char* buffer, size_t size, const char* format, ...) {
+ va_list args;
+ va_start(args, format);
+ int result = vsnprintf_s(buffer, size, _TRUNCATE, format, args);
+ va_end(args);
+ return result;
+}
+# define FMT_SNPRINTF fmt_snprintf
+#endif // _MSC_VER
+
+FMT_FUNC void format_error_code(detail::buffer<char>& out, int error_code,
+ string_view message) FMT_NOEXCEPT {
+ // Report error code making sure that the output fits into
+ // inline_buffer_size to avoid dynamic memory allocation and potential
+ // bad_alloc.
+ out.try_resize(0);
+ static const char SEP[] = ": ";
+ static const char ERROR_STR[] = "error ";
+ // Subtract 2 to account for terminating null characters in SEP and ERROR_STR.
+ size_t error_code_size = sizeof(SEP) + sizeof(ERROR_STR) - 2;
+ auto abs_value = static_cast<uint32_or_64_or_128_t<int>>(error_code);
+ if (detail::is_negative(error_code)) {
+ abs_value = 0 - abs_value;
+ ++error_code_size;
+ }
+ error_code_size += detail::to_unsigned(detail::count_digits(abs_value));
+ auto it = buffer_appender<char>(out);
+ if (message.size() <= inline_buffer_size - error_code_size)
+ format_to(it, FMT_STRING("{}{}"), message, SEP);
+ format_to(it, FMT_STRING("{}{}"), ERROR_STR, error_code);
+ FMT_ASSERT(out.size() <= inline_buffer_size, "");
+}
+
+FMT_FUNC void report_error(format_func func, int error_code,
+ const char* message) FMT_NOEXCEPT {
+ memory_buffer full_message;
+ func(full_message, error_code, message);
+ // Don't use fwrite_fully because the latter may throw.
+ if (std::fwrite(full_message.data(), full_message.size(), 1, stderr) > 0)
+ std::fputc('\n', stderr);
+}
+
+// A wrapper around fwrite that throws on error.
+inline void fwrite_fully(const void* ptr, size_t size, size_t count,
+ FILE* stream) {
+ size_t written = std::fwrite(ptr, size, count, stream);
+ if (written < count) FMT_THROW(system_error(errno, "cannot write to file"));
+}
+
+#ifndef FMT_STATIC_THOUSANDS_SEPARATOR
+template <typename Locale>
+locale_ref::locale_ref(const Locale& loc) : locale_(&loc) {
+ static_assert(std::is_same<Locale, std::locale>::value, "");
+}
+
+template <typename Locale> Locale locale_ref::get() const {
+ static_assert(std::is_same<Locale, std::locale>::value, "");
+ return locale_ ? *static_cast<const std::locale*>(locale_) : std::locale();
+}
+
+template <typename Char>
+FMT_FUNC auto thousands_sep_impl(locale_ref loc) -> thousands_sep_result<Char> {
+ auto& facet = std::use_facet<std::numpunct<Char>>(loc.get<std::locale>());
+ auto grouping = facet.grouping();
+ auto thousands_sep = grouping.empty() ? Char() : facet.thousands_sep();
+ return {std::move(grouping), thousands_sep};
+}
+template <typename Char> FMT_FUNC Char decimal_point_impl(locale_ref loc) {
+ return std::use_facet<std::numpunct<Char>>(loc.get<std::locale>())
+ .decimal_point();
+}
+#else
+template <typename Char>
+FMT_FUNC auto thousands_sep_impl(locale_ref) -> thousands_sep_result<Char> {
+ return {"\03", FMT_STATIC_THOUSANDS_SEPARATOR};
+}
+template <typename Char> FMT_FUNC Char decimal_point_impl(locale_ref) {
+ return '.';
+}
+#endif
+} // namespace detail
+
+#if !FMT_MSC_VER
+FMT_API FMT_FUNC format_error::~format_error() FMT_NOEXCEPT = default;
+#endif
+
+FMT_FUNC std::system_error vsystem_error(int error_code, string_view format_str,
+ format_args args) {
+ auto ec = std::error_code(error_code, std::generic_category());
+ return std::system_error(ec, vformat(format_str, args));
+}
+
+namespace detail {
+
+template <> FMT_FUNC int count_digits<4>(detail::fallback_uintptr n) {
+ // fallback_uintptr is always stored in little endian.
+ int i = static_cast<int>(sizeof(void*)) - 1;
+ while (i > 0 && n.value[i] == 0) --i;
+ auto char_digits = std::numeric_limits<unsigned char>::digits / 4;
+ return i >= 0 ? i * char_digits + count_digits<4, unsigned>(n.value[i]) : 1;
+}
+
+// log10(2) = 0x0.4d104d427de7fbcc...
+static constexpr uint64_t log10_2_significand = 0x4d104d427de7fbcc;
+
+template <typename T = void> struct basic_impl_data {
+ // Normalized 64-bit significands of pow(10, k), for k = -348, -340, ..., 340.
+ // These are generated by support/compute-powers.py.
+ static constexpr uint64_t pow10_significands[87] = {
+ 0xfa8fd5a0081c0288, 0xbaaee17fa23ebf76, 0x8b16fb203055ac76,
+ 0xcf42894a5dce35ea, 0x9a6bb0aa55653b2d, 0xe61acf033d1a45df,
+ 0xab70fe17c79ac6ca, 0xff77b1fcbebcdc4f, 0xbe5691ef416bd60c,
+ 0x8dd01fad907ffc3c, 0xd3515c2831559a83, 0x9d71ac8fada6c9b5,
+ 0xea9c227723ee8bcb, 0xaecc49914078536d, 0x823c12795db6ce57,
+ 0xc21094364dfb5637, 0x9096ea6f3848984f, 0xd77485cb25823ac7,
+ 0xa086cfcd97bf97f4, 0xef340a98172aace5, 0xb23867fb2a35b28e,
+ 0x84c8d4dfd2c63f3b, 0xc5dd44271ad3cdba, 0x936b9fcebb25c996,
+ 0xdbac6c247d62a584, 0xa3ab66580d5fdaf6, 0xf3e2f893dec3f126,
+ 0xb5b5ada8aaff80b8, 0x87625f056c7c4a8b, 0xc9bcff6034c13053,
+ 0x964e858c91ba2655, 0xdff9772470297ebd, 0xa6dfbd9fb8e5b88f,
+ 0xf8a95fcf88747d94, 0xb94470938fa89bcf, 0x8a08f0f8bf0f156b,
+ 0xcdb02555653131b6, 0x993fe2c6d07b7fac, 0xe45c10c42a2b3b06,
+ 0xaa242499697392d3, 0xfd87b5f28300ca0e, 0xbce5086492111aeb,
+ 0x8cbccc096f5088cc, 0xd1b71758e219652c, 0x9c40000000000000,
+ 0xe8d4a51000000000, 0xad78ebc5ac620000, 0x813f3978f8940984,
+ 0xc097ce7bc90715b3, 0x8f7e32ce7bea5c70, 0xd5d238a4abe98068,
+ 0x9f4f2726179a2245, 0xed63a231d4c4fb27, 0xb0de65388cc8ada8,
+ 0x83c7088e1aab65db, 0xc45d1df942711d9a, 0x924d692ca61be758,
+ 0xda01ee641a708dea, 0xa26da3999aef774a, 0xf209787bb47d6b85,
+ 0xb454e4a179dd1877, 0x865b86925b9bc5c2, 0xc83553c5c8965d3d,
+ 0x952ab45cfa97a0b3, 0xde469fbd99a05fe3, 0xa59bc234db398c25,
+ 0xf6c69a72a3989f5c, 0xb7dcbf5354e9bece, 0x88fcf317f22241e2,
+ 0xcc20ce9bd35c78a5, 0x98165af37b2153df, 0xe2a0b5dc971f303a,
+ 0xa8d9d1535ce3b396, 0xfb9b7cd9a4a7443c, 0xbb764c4ca7a44410,
+ 0x8bab8eefb6409c1a, 0xd01fef10a657842c, 0x9b10a4e5e9913129,
+ 0xe7109bfba19c0c9d, 0xac2820d9623bf429, 0x80444b5e7aa7cf85,
+ 0xbf21e44003acdd2d, 0x8e679c2f5e44ff8f, 0xd433179d9c8cb841,
+ 0x9e19db92b4e31ba9, 0xeb96bf6ebadf77d9, 0xaf87023b9bf0ee6b,
+ };
+
+#if FMT_GCC_VERSION && FMT_GCC_VERSION < 409
+# pragma GCC diagnostic push
+# pragma GCC diagnostic ignored "-Wnarrowing"
+#endif
+ // Binary exponents of pow(10, k), for k = -348, -340, ..., 340, corresponding
+ // to significands above.
+ static constexpr int16_t pow10_exponents[87] = {
+ -1220, -1193, -1166, -1140, -1113, -1087, -1060, -1034, -1007, -980, -954,
+ -927, -901, -874, -847, -821, -794, -768, -741, -715, -688, -661,
+ -635, -608, -582, -555, -529, -502, -475, -449, -422, -396, -369,
+ -343, -316, -289, -263, -236, -210, -183, -157, -130, -103, -77,
+ -50, -24, 3, 30, 56, 83, 109, 136, 162, 189, 216,
+ 242, 269, 295, 322, 348, 375, 402, 428, 455, 481, 508,
+ 534, 561, 588, 614, 641, 667, 694, 720, 747, 774, 800,
+ 827, 853, 880, 907, 933, 960, 986, 1013, 1039, 1066};
+#if FMT_GCC_VERSION && FMT_GCC_VERSION < 409
+# pragma GCC diagnostic pop
+#endif
+
+ static constexpr uint64_t power_of_10_64[20] = {
+ 1, FMT_POWERS_OF_10(1ULL), FMT_POWERS_OF_10(1000000000ULL),
+ 10000000000000000000ULL};
+};
+
+// This is a struct rather than an alias to avoid shadowing warnings in gcc.
+struct impl_data : basic_impl_data<> {};
+
+#if __cplusplus < 201703L
+template <typename T>
+constexpr uint64_t basic_impl_data<T>::pow10_significands[];
+template <typename T> constexpr int16_t basic_impl_data<T>::pow10_exponents[];
+template <typename T> constexpr uint64_t basic_impl_data<T>::power_of_10_64[];
+#endif
+
+template <typename T> struct bits {
+ static FMT_CONSTEXPR_DECL const int value =
+ static_cast<int>(sizeof(T) * std::numeric_limits<unsigned char>::digits);
+};
+
+// Returns the number of significand bits in Float excluding the implicit bit.
+template <typename Float> constexpr int num_significand_bits() {
+ // Subtract 1 to account for an implicit most significant bit in the
+ // normalized form.
+ return std::numeric_limits<Float>::digits - 1;
+}
+
+// A floating-point number f * pow(2, e).
+struct fp {
+ uint64_t f;
+ int e;
+
+ static constexpr const int num_significand_bits = bits<decltype(f)>::value;
+
+ constexpr fp() : f(0), e(0) {}
+ constexpr fp(uint64_t f_val, int e_val) : f(f_val), e(e_val) {}
+
+ // Constructs fp from an IEEE754 floating-point number. It is a template to
+ // prevent compile errors on systems where n is not IEEE754.
+ template <typename Float> explicit FMT_CONSTEXPR fp(Float n) { assign(n); }
+
+ template <typename Float>
+ using is_supported = bool_constant<sizeof(Float) == sizeof(uint64_t) ||
+ sizeof(Float) == sizeof(uint32_t)>;
+
+ // Assigns d to this and return true iff predecessor is closer than successor.
+ template <typename Float, FMT_ENABLE_IF(is_supported<Float>::value)>
+ FMT_CONSTEXPR bool assign(Float n) {
+ // Assume float is in the format [sign][exponent][significand].
+ const int num_float_significand_bits =
+ detail::num_significand_bits<Float>();
+ const uint64_t implicit_bit = 1ULL << num_float_significand_bits;
+ const uint64_t significand_mask = implicit_bit - 1;
+ constexpr bool is_double = sizeof(Float) == sizeof(uint64_t);
+ auto u = bit_cast<conditional_t<is_double, uint64_t, uint32_t>>(n);
+ f = u & significand_mask;
+ const uint64_t exponent_mask = (~0ULL >> 1) & ~significand_mask;
+ int biased_e =
+ static_cast<int>((u & exponent_mask) >> num_float_significand_bits);
+ // The predecessor is closer if n is a normalized power of 2 (f == 0) other
+ // than the smallest normalized number (biased_e > 1).
+ bool is_predecessor_closer = f == 0 && biased_e > 1;
+ if (biased_e != 0)
+ f += implicit_bit;
+ else
+ biased_e = 1; // Subnormals use biased exponent 1 (min exponent).
+ const int exponent_bias = std::numeric_limits<Float>::max_exponent - 1;
+ e = biased_e - exponent_bias - num_float_significand_bits;
+ return is_predecessor_closer;
+ }
+
+ template <typename Float, FMT_ENABLE_IF(!is_supported<Float>::value)>
+ bool assign(Float) {
+ FMT_ASSERT(false, "");
+ return false;
+ }
+};
+
+// Normalizes the value converted from double and multiplied by (1 << SHIFT).
+template <int SHIFT = 0> FMT_CONSTEXPR fp normalize(fp value) {
+ // Handle subnormals.
+ const uint64_t implicit_bit = 1ULL << num_significand_bits<double>();
+ const auto shifted_implicit_bit = implicit_bit << SHIFT;
+ while ((value.f & shifted_implicit_bit) == 0) {
+ value.f <<= 1;
+ --value.e;
+ }
+ // Subtract 1 to account for hidden bit.
+ const auto offset =
+ fp::num_significand_bits - num_significand_bits<double>() - SHIFT - 1;
+ value.f <<= offset;
+ value.e -= offset;
+ return value;
+}
+
+inline bool operator==(fp x, fp y) { return x.f == y.f && x.e == y.e; }
+
+// Computes lhs * rhs / pow(2, 64) rounded to nearest with half-up tie breaking.
+FMT_CONSTEXPR inline uint64_t multiply(uint64_t lhs, uint64_t rhs) {
+#if FMT_USE_INT128
+ auto product = static_cast<__uint128_t>(lhs) * rhs;
+ auto f = static_cast<uint64_t>(product >> 64);
+ return (static_cast<uint64_t>(product) & (1ULL << 63)) != 0 ? f + 1 : f;
+#else
+ // Multiply 32-bit parts of significands.
+ uint64_t mask = (1ULL << 32) - 1;
+ uint64_t a = lhs >> 32, b = lhs & mask;
+ uint64_t c = rhs >> 32, d = rhs & mask;
+ uint64_t ac = a * c, bc = b * c, ad = a * d, bd = b * d;
+ // Compute mid 64-bit of result and round.
+ uint64_t mid = (bd >> 32) + (ad & mask) + (bc & mask) + (1U << 31);
+ return ac + (ad >> 32) + (bc >> 32) + (mid >> 32);
+#endif
+}
+
+FMT_CONSTEXPR inline fp operator*(fp x, fp y) {
+ return {multiply(x.f, y.f), x.e + y.e + 64};
+}
+
+// Returns a cached power of 10 `c_k = c_k.f * pow(2, c_k.e)` such that its
+// (binary) exponent satisfies `min_exponent <= c_k.e <= min_exponent + 28`.
+FMT_CONSTEXPR inline fp get_cached_power(int min_exponent,
+ int& pow10_exponent) {
+ const int shift = 32;
+ const auto significand = static_cast<int64_t>(log10_2_significand);
+ int index = static_cast<int>(
+ ((min_exponent + fp::num_significand_bits - 1) * (significand >> shift) +
+ ((int64_t(1) << shift) - 1)) // ceil
+ >> 32 // arithmetic shift
+ );
+ // Decimal exponent of the first (smallest) cached power of 10.
+ const int first_dec_exp = -348;
+ // Difference between 2 consecutive decimal exponents in cached powers of 10.
+ const int dec_exp_step = 8;
+ index = (index - first_dec_exp - 1) / dec_exp_step + 1;
+ pow10_exponent = first_dec_exp + index * dec_exp_step;
+ return {impl_data::pow10_significands[index],
+ impl_data::pow10_exponents[index]};
+}
+
+// A simple accumulator to hold the sums of terms in bigint::square if uint128_t
+// is not available.
+struct accumulator {
+ uint64_t lower;
+ uint64_t upper;
+
+ constexpr accumulator() : lower(0), upper(0) {}
+ constexpr explicit operator uint32_t() const {
+ return static_cast<uint32_t>(lower);
+ }
+
+ FMT_CONSTEXPR void operator+=(uint64_t n) {
+ lower += n;
+ if (lower < n) ++upper;
+ }
+ FMT_CONSTEXPR void operator>>=(int shift) {
+ FMT_ASSERT(shift == 32, "");
+ (void)shift;
+ lower = (upper << 32) | (lower >> 32);
+ upper >>= 32;
+ }
+};
+
+class bigint {
+ private:
+ // A bigint is stored as an array of bigits (big digits), with bigit at index
+ // 0 being the least significant one.
+ using bigit = uint32_t;
+ using double_bigit = uint64_t;
+ enum { bigits_capacity = 32 };
+ basic_memory_buffer<bigit, bigits_capacity> bigits_;
+ int exp_;
+
+ FMT_CONSTEXPR20 bigit operator[](int index) const {
+ return bigits_[to_unsigned(index)];
+ }
+ FMT_CONSTEXPR20 bigit& operator[](int index) {
+ return bigits_[to_unsigned(index)];
+ }
+
+ static FMT_CONSTEXPR_DECL const int bigit_bits = bits<bigit>::value;
+
+ friend struct formatter<bigint>;
+
+ FMT_CONSTEXPR20 void subtract_bigits(int index, bigit other, bigit& borrow) {
+ auto result = static_cast<double_bigit>((*this)[index]) - other - borrow;
+ (*this)[index] = static_cast<bigit>(result);
+ borrow = static_cast<bigit>(result >> (bigit_bits * 2 - 1));
+ }
+
+ FMT_CONSTEXPR20 void remove_leading_zeros() {
+ int num_bigits = static_cast<int>(bigits_.size()) - 1;
+ while (num_bigits > 0 && (*this)[num_bigits] == 0) --num_bigits;
+ bigits_.resize(to_unsigned(num_bigits + 1));
+ }
+
+ // Computes *this -= other assuming aligned bigints and *this >= other.
+ FMT_CONSTEXPR20 void subtract_aligned(const bigint& other) {
+ FMT_ASSERT(other.exp_ >= exp_, "unaligned bigints");
+ FMT_ASSERT(compare(*this, other) >= 0, "");
+ bigit borrow = 0;
+ int i = other.exp_ - exp_;
+ for (size_t j = 0, n = other.bigits_.size(); j != n; ++i, ++j)
+ subtract_bigits(i, other.bigits_[j], borrow);
+ while (borrow > 0) subtract_bigits(i, 0, borrow);
+ remove_leading_zeros();
+ }
+
+ FMT_CONSTEXPR20 void multiply(uint32_t value) {
+ const double_bigit wide_value = value;
+ bigit carry = 0;
+ for (size_t i = 0, n = bigits_.size(); i < n; ++i) {
+ double_bigit result = bigits_[i] * wide_value + carry;
+ bigits_[i] = static_cast<bigit>(result);
+ carry = static_cast<bigit>(result >> bigit_bits);
+ }
+ if (carry != 0) bigits_.push_back(carry);
+ }
+
+ FMT_CONSTEXPR20 void multiply(uint64_t value) {
+ const bigit mask = ~bigit(0);
+ const double_bigit lower = value & mask;
+ const double_bigit upper = value >> bigit_bits;
+ double_bigit carry = 0;
+ for (size_t i = 0, n = bigits_.size(); i < n; ++i) {
+ double_bigit result = bigits_[i] * lower + (carry & mask);
+ carry =
+ bigits_[i] * upper + (result >> bigit_bits) + (carry >> bigit_bits);
+ bigits_[i] = static_cast<bigit>(result);
+ }
+ while (carry != 0) {
+ bigits_.push_back(carry & mask);
+ carry >>= bigit_bits;
+ }
+ }
+
+ public:
+ FMT_CONSTEXPR20 bigint() : exp_(0) {}
+ explicit bigint(uint64_t n) { assign(n); }
+ FMT_CONSTEXPR20 ~bigint() {
+ FMT_ASSERT(bigits_.capacity() <= bigits_capacity, "");
+ }
+
+ bigint(const bigint&) = delete;
+ void operator=(const bigint&) = delete;
+
+ FMT_CONSTEXPR20 void assign(const bigint& other) {
+ auto size = other.bigits_.size();
+ bigits_.resize(size);
+ auto data = other.bigits_.data();
+ std::copy(data, data + size, make_checked(bigits_.data(), size));
+ exp_ = other.exp_;
+ }
+
+ FMT_CONSTEXPR20 void assign(uint64_t n) {
+ size_t num_bigits = 0;
+ do {
+ bigits_[num_bigits++] = n & ~bigit(0);
+ n >>= bigit_bits;
+ } while (n != 0);
+ bigits_.resize(num_bigits);
+ exp_ = 0;
+ }
+
+ FMT_CONSTEXPR20 int num_bigits() const {
+ return static_cast<int>(bigits_.size()) + exp_;
+ }
+
+ FMT_NOINLINE FMT_CONSTEXPR20 bigint& operator<<=(int shift) {
+ FMT_ASSERT(shift >= 0, "");
+ exp_ += shift / bigit_bits;
+ shift %= bigit_bits;
+ if (shift == 0) return *this;
+ bigit carry = 0;
+ for (size_t i = 0, n = bigits_.size(); i < n; ++i) {
+ bigit c = bigits_[i] >> (bigit_bits - shift);
+ bigits_[i] = (bigits_[i] << shift) + carry;
+ carry = c;
+ }
+ if (carry != 0) bigits_.push_back(carry);
+ return *this;
+ }
+
+ template <typename Int> FMT_CONSTEXPR20 bigint& operator*=(Int value) {
+ FMT_ASSERT(value > 0, "");
+ multiply(uint32_or_64_or_128_t<Int>(value));
+ return *this;
+ }
+
+ friend FMT_CONSTEXPR20 int compare(const bigint& lhs, const bigint& rhs) {
+ int num_lhs_bigits = lhs.num_bigits(), num_rhs_bigits = rhs.num_bigits();
+ if (num_lhs_bigits != num_rhs_bigits)
+ return num_lhs_bigits > num_rhs_bigits ? 1 : -1;
+ int i = static_cast<int>(lhs.bigits_.size()) - 1;
+ int j = static_cast<int>(rhs.bigits_.size()) - 1;
+ int end = i - j;
+ if (end < 0) end = 0;
+ for (; i >= end; --i, --j) {
+ bigit lhs_bigit = lhs[i], rhs_bigit = rhs[j];
+ if (lhs_bigit != rhs_bigit) return lhs_bigit > rhs_bigit ? 1 : -1;
+ }
+ if (i != j) return i > j ? 1 : -1;
+ return 0;
+ }
+
+ // Returns compare(lhs1 + lhs2, rhs).
+ friend FMT_CONSTEXPR20 int add_compare(const bigint& lhs1, const bigint& lhs2,
+ const bigint& rhs) {
+ int max_lhs_bigits = (std::max)(lhs1.num_bigits(), lhs2.num_bigits());
+ int num_rhs_bigits = rhs.num_bigits();
+ if (max_lhs_bigits + 1 < num_rhs_bigits) return -1;
+ if (max_lhs_bigits > num_rhs_bigits) return 1;
+ auto get_bigit = [](const bigint& n, int i) -> bigit {
+ return i >= n.exp_ && i < n.num_bigits() ? n[i - n.exp_] : 0;
+ };
+ double_bigit borrow = 0;
+ int min_exp = (std::min)((std::min)(lhs1.exp_, lhs2.exp_), rhs.exp_);
+ for (int i = num_rhs_bigits - 1; i >= min_exp; --i) {
+ double_bigit sum =
+ static_cast<double_bigit>(get_bigit(lhs1, i)) + get_bigit(lhs2, i);
+ bigit rhs_bigit = get_bigit(rhs, i);
+ if (sum > rhs_bigit + borrow) return 1;
+ borrow = rhs_bigit + borrow - sum;
+ if (borrow > 1) return -1;
+ borrow <<= bigit_bits;
+ }
+ return borrow != 0 ? -1 : 0;
+ }
+
+ // Assigns pow(10, exp) to this bigint.
+ FMT_CONSTEXPR20 void assign_pow10(int exp) {
+ FMT_ASSERT(exp >= 0, "");
+ if (exp == 0) return assign(1);
+ // Find the top bit.
+ int bitmask = 1;
+ while (exp >= bitmask) bitmask <<= 1;
+ bitmask >>= 1;
+ // pow(10, exp) = pow(5, exp) * pow(2, exp). First compute pow(5, exp) by
+ // repeated squaring and multiplication.
+ assign(5);
+ bitmask >>= 1;
+ while (bitmask != 0) {
+ square();
+ if ((exp & bitmask) != 0) *this *= 5;
+ bitmask >>= 1;
+ }
+ *this <<= exp; // Multiply by pow(2, exp) by shifting.
+ }
+
+ FMT_CONSTEXPR20 void square() {
+ int num_bigits = static_cast<int>(bigits_.size());
+ int num_result_bigits = 2 * num_bigits;
+ basic_memory_buffer<bigit, bigits_capacity> n(std::move(bigits_));
+ bigits_.resize(to_unsigned(num_result_bigits));
+ using accumulator_t = conditional_t<FMT_USE_INT128, uint128_t, accumulator>;
+ auto sum = accumulator_t();
+ for (int bigit_index = 0; bigit_index < num_bigits; ++bigit_index) {
+ // Compute bigit at position bigit_index of the result by adding
+ // cross-product terms n[i] * n[j] such that i + j == bigit_index.
+ for (int i = 0, j = bigit_index; j >= 0; ++i, --j) {
+ // Most terms are multiplied twice which can be optimized in the future.
+ sum += static_cast<double_bigit>(n[i]) * n[j];
+ }
+ (*this)[bigit_index] = static_cast<bigit>(sum);
+ sum >>= bits<bigit>::value; // Compute the carry.
+ }
+ // Do the same for the top half.
+ for (int bigit_index = num_bigits; bigit_index < num_result_bigits;
+ ++bigit_index) {
+ for (int j = num_bigits - 1, i = bigit_index - j; i < num_bigits;)
+ sum += static_cast<double_bigit>(n[i++]) * n[j--];
+ (*this)[bigit_index] = static_cast<bigit>(sum);
+ sum >>= bits<bigit>::value;
+ }
+ remove_leading_zeros();
+ exp_ *= 2;
+ }
+
+ // If this bigint has a bigger exponent than other, adds trailing zero to make
+ // exponents equal. This simplifies some operations such as subtraction.
+ FMT_CONSTEXPR20 void align(const bigint& other) {
+ int exp_difference = exp_ - other.exp_;
+ if (exp_difference <= 0) return;
+ int num_bigits = static_cast<int>(bigits_.size());
+ bigits_.resize(to_unsigned(num_bigits + exp_difference));
+ for (int i = num_bigits - 1, j = i + exp_difference; i >= 0; --i, --j)
+ bigits_[j] = bigits_[i];
+ std::uninitialized_fill_n(bigits_.data(), exp_difference, 0);
+ exp_ -= exp_difference;
+ }
+
+ // Divides this bignum by divisor, assigning the remainder to this and
+ // returning the quotient.
+ FMT_CONSTEXPR20 int divmod_assign(const bigint& divisor) {
+ FMT_ASSERT(this != &divisor, "");
+ if (compare(*this, divisor) < 0) return 0;
+ FMT_ASSERT(divisor.bigits_[divisor.bigits_.size() - 1u] != 0, "");
+ align(divisor);
+ int quotient = 0;
+ do {
+ subtract_aligned(divisor);
+ ++quotient;
+ } while (compare(*this, divisor) >= 0);
+ return quotient;
+ }
+};
+
+enum class round_direction { unknown, up, down };
+
+// Given the divisor (normally a power of 10), the remainder = v % divisor for
+// some number v and the error, returns whether v should be rounded up, down, or
+// whether the rounding direction can't be determined due to error.
+// error should be less than divisor / 2.
+FMT_CONSTEXPR inline round_direction get_round_direction(uint64_t divisor,
+ uint64_t remainder,
+ uint64_t error) {
+ FMT_ASSERT(remainder < divisor, ""); // divisor - remainder won't overflow.
+ FMT_ASSERT(error < divisor, ""); // divisor - error won't overflow.
+ FMT_ASSERT(error < divisor - error, ""); // error * 2 won't overflow.
+ // Round down if (remainder + error) * 2 <= divisor.
+ if (remainder <= divisor - remainder && error * 2 <= divisor - remainder * 2)
+ return round_direction::down;
+ // Round up if (remainder - error) * 2 >= divisor.
+ if (remainder >= error &&
+ remainder - error >= divisor - (remainder - error)) {
+ return round_direction::up;
+ }
+ return round_direction::unknown;
+}
+
+namespace digits {
+enum result {
+ more, // Generate more digits.
+ done, // Done generating digits.
+ error // Digit generation cancelled due to an error.
+};
+}
+
+struct gen_digits_handler {
+ char* buf;
+ int size;
+ int precision;
+ int exp10;
+ bool fixed;
+
+ FMT_CONSTEXPR digits::result on_digit(char digit, uint64_t divisor,
+ uint64_t remainder, uint64_t error,
+ bool integral) {
+ FMT_ASSERT(remainder < divisor, "");
+ buf[size++] = digit;
+ if (!integral && error >= remainder) return digits::error;
+ if (size < precision) return digits::more;
+ if (!integral) {
+ // Check if error * 2 < divisor with overflow prevention.
+ // The check is not needed for the integral part because error = 1
+ // and divisor > (1 << 32) there.
+ if (error >= divisor || error >= divisor - error) return digits::error;
+ } else {
+ FMT_ASSERT(error == 1 && divisor > 2, "");
+ }
+ auto dir = get_round_direction(divisor, remainder, error);
+ if (dir != round_direction::up)
+ return dir == round_direction::down ? digits::done : digits::error;
+ ++buf[size - 1];
+ for (int i = size - 1; i > 0 && buf[i] > '9'; --i) {
+ buf[i] = '0';
+ ++buf[i - 1];
+ }
+ if (buf[0] > '9') {
+ buf[0] = '1';
+ if (fixed)
+ buf[size++] = '0';
+ else
+ ++exp10;
+ }
+ return digits::done;
+ }
+};
+
+// Generates output using the Grisu digit-gen algorithm.
+// error: the size of the region (lower, upper) outside of which numbers
+// definitely do not round to value (Delta in Grisu3).
+FMT_INLINE FMT_CONSTEXPR20 digits::result grisu_gen_digits(
+ fp value, uint64_t error, int& exp, gen_digits_handler& handler) {
+ const fp one(1ULL << -value.e, value.e);
+ // The integral part of scaled value (p1 in Grisu) = value / one. It cannot be
+ // zero because it contains a product of two 64-bit numbers with MSB set (due
+ // to normalization) - 1, shifted right by at most 60 bits.
+ auto integral = static_cast<uint32_t>(value.f >> -one.e);
+ FMT_ASSERT(integral != 0, "");
+ FMT_ASSERT(integral == value.f >> -one.e, "");
+ // The fractional part of scaled value (p2 in Grisu) c = value % one.
+ uint64_t fractional = value.f & (one.f - 1);
+ exp = count_digits(integral); // kappa in Grisu.
+ // Non-fixed formats require at least one digit and no precision adjustment.
+ if (handler.fixed) {
+ // Adjust fixed precision by exponent because it is relative to decimal
+ // point.
+ int precision_offset = exp + handler.exp10;
+ if (precision_offset > 0 &&
+ handler.precision > max_value<int>() - precision_offset) {
+ FMT_THROW(format_error("number is too big"));
+ }
+ handler.precision += precision_offset;
+ // Check if precision is satisfied just by leading zeros, e.g.
+ // format("{:.2f}", 0.001) gives "0.00" without generating any digits.
+ if (handler.precision <= 0) {
+ if (handler.precision < 0) return digits::done;
+ // Divide by 10 to prevent overflow.
+ uint64_t divisor = impl_data::power_of_10_64[exp - 1] << -one.e;
+ auto dir = get_round_direction(divisor, value.f / 10, error * 10);
+ if (dir == round_direction::unknown) return digits::error;
+ handler.buf[handler.size++] = dir == round_direction::up ? '1' : '0';
+ return digits::done;
+ }
+ }
+ // Generate digits for the integral part. This can produce up to 10 digits.
+ do {
+ uint32_t digit = 0;
+ auto divmod_integral = [&](uint32_t divisor) {
+ digit = integral / divisor;
+ integral %= divisor;
+ };
+ // This optimization by Milo Yip reduces the number of integer divisions by
+ // one per iteration.
+ switch (exp) {
+ case 10:
+ divmod_integral(1000000000);
+ break;
+ case 9:
+ divmod_integral(100000000);
+ break;
+ case 8:
+ divmod_integral(10000000);
+ break;
+ case 7:
+ divmod_integral(1000000);
+ break;
+ case 6:
+ divmod_integral(100000);
+ break;
+ case 5:
+ divmod_integral(10000);
+ break;
+ case 4:
+ divmod_integral(1000);
+ break;
+ case 3:
+ divmod_integral(100);
+ break;
+ case 2:
+ divmod_integral(10);
+ break;
+ case 1:
+ digit = integral;
+ integral = 0;
+ break;
+ default:
+ FMT_ASSERT(false, "invalid number of digits");
+ }
+ --exp;
+ auto remainder = (static_cast<uint64_t>(integral) << -one.e) + fractional;
+ auto result = handler.on_digit(static_cast<char>('0' + digit),
+ impl_data::power_of_10_64[exp] << -one.e,
+ remainder, error, true);
+ if (result != digits::more) return result;
+ } while (exp > 0);
+ // Generate digits for the fractional part.
+ for (;;) {
+ fractional *= 10;
+ error *= 10;
+ char digit = static_cast<char>('0' + (fractional >> -one.e));
+ fractional &= one.f - 1;
+ --exp;
+ auto result = handler.on_digit(digit, one.f, fractional, error, false);
+ if (result != digits::more) return result;
+ }
+}
+
+// A 128-bit integer type used internally,
+struct uint128_wrapper {
+ uint128_wrapper() = default;
+
+#if FMT_USE_INT128
+ uint128_t internal_;
+
+ constexpr uint128_wrapper(uint64_t high, uint64_t low) FMT_NOEXCEPT
+ : internal_{static_cast<uint128_t>(low) |
+ (static_cast<uint128_t>(high) << 64)} {}
+
+ constexpr uint128_wrapper(uint128_t u) : internal_{u} {}
+
+ constexpr uint64_t high() const FMT_NOEXCEPT {
+ return uint64_t(internal_ >> 64);
+ }
+ constexpr uint64_t low() const FMT_NOEXCEPT { return uint64_t(internal_); }
+
+ uint128_wrapper& operator+=(uint64_t n) FMT_NOEXCEPT {
+ internal_ += n;
+ return *this;
+ }
+#else
+ uint64_t high_;
+ uint64_t low_;
+
+ constexpr uint128_wrapper(uint64_t high, uint64_t low) FMT_NOEXCEPT
+ : high_{high},
+ low_{low} {}
+
+ constexpr uint64_t high() const FMT_NOEXCEPT { return high_; }
+ constexpr uint64_t low() const FMT_NOEXCEPT { return low_; }
+
+ uint128_wrapper& operator+=(uint64_t n) FMT_NOEXCEPT {
+# if defined(_MSC_VER) && defined(_M_X64)
+ unsigned char carry = _addcarry_u64(0, low_, n, &low_);
+ _addcarry_u64(carry, high_, 0, &high_);
+ return *this;
+# else
+ uint64_t sum = low_ + n;
+ high_ += (sum < low_ ? 1 : 0);
+ low_ = sum;
+ return *this;
+# endif
+ }
+#endif
+};
+
+// Implementation of Dragonbox algorithm: https://github.com/jk-jeon/dragonbox.
+namespace dragonbox {
+// Computes 128-bit result of multiplication of two 64-bit unsigned integers.
+inline uint128_wrapper umul128(uint64_t x, uint64_t y) FMT_NOEXCEPT {
+#if FMT_USE_INT128
+ return static_cast<uint128_t>(x) * static_cast<uint128_t>(y);
+#elif defined(_MSC_VER) && defined(_M_X64)
+ uint128_wrapper result;
+ result.low_ = _umul128(x, y, &result.high_);
+ return result;
+#else
+ const uint64_t mask = (uint64_t(1) << 32) - uint64_t(1);
+
+ uint64_t a = x >> 32;
+ uint64_t b = x & mask;
+ uint64_t c = y >> 32;
+ uint64_t d = y & mask;
+
+ uint64_t ac = a * c;
+ uint64_t bc = b * c;
+ uint64_t ad = a * d;
+ uint64_t bd = b * d;
+
+ uint64_t intermediate = (bd >> 32) + (ad & mask) + (bc & mask);
+
+ return {ac + (intermediate >> 32) + (ad >> 32) + (bc >> 32),
+ (intermediate << 32) + (bd & mask)};
+#endif
+}
+
+// Computes upper 64 bits of multiplication of two 64-bit unsigned integers.
+inline uint64_t umul128_upper64(uint64_t x, uint64_t y) FMT_NOEXCEPT {
+#if FMT_USE_INT128
+ auto p = static_cast<uint128_t>(x) * static_cast<uint128_t>(y);
+ return static_cast<uint64_t>(p >> 64);
+#elif defined(_MSC_VER) && defined(_M_X64)
+ return __umulh(x, y);
+#else
+ return umul128(x, y).high();
+#endif
+}
+
+// Computes upper 64 bits of multiplication of a 64-bit unsigned integer and a
+// 128-bit unsigned integer.
+inline uint64_t umul192_upper64(uint64_t x, uint128_wrapper y) FMT_NOEXCEPT {
+ uint128_wrapper g0 = umul128(x, y.high());
+ g0 += umul128_upper64(x, y.low());
+ return g0.high();
+}
+
+// Computes upper 32 bits of multiplication of a 32-bit unsigned integer and a
+// 64-bit unsigned integer.
+inline uint32_t umul96_upper32(uint32_t x, uint64_t y) FMT_NOEXCEPT {
+ return static_cast<uint32_t>(umul128_upper64(x, y));
+}
+
+// Computes middle 64 bits of multiplication of a 64-bit unsigned integer and a
+// 128-bit unsigned integer.
+inline uint64_t umul192_middle64(uint64_t x, uint128_wrapper y) FMT_NOEXCEPT {
+ uint64_t g01 = x * y.high();
+ uint64_t g10 = umul128_upper64(x, y.low());
+ return g01 + g10;
+}
+
+// Computes lower 64 bits of multiplication of a 32-bit unsigned integer and a
+// 64-bit unsigned integer.
+inline uint64_t umul96_lower64(uint32_t x, uint64_t y) FMT_NOEXCEPT {
+ return x * y;
+}
+
+// Computes floor(log10(pow(2, e))) for e in [-1700, 1700] using the method from
+// https://fmt.dev/papers/Grisu-Exact.pdf#page=5, section 3.4.
+inline int floor_log10_pow2(int e) FMT_NOEXCEPT {
+ FMT_ASSERT(e <= 1700 && e >= -1700, "too large exponent");
+ const int shift = 22;
+ return (e * static_cast<int>(log10_2_significand >> (64 - shift))) >> shift;
+}
+
+// Various fast log computations.
+inline int floor_log2_pow10(int e) FMT_NOEXCEPT {
+ FMT_ASSERT(e <= 1233 && e >= -1233, "too large exponent");
+ const uint64_t log2_10_integer_part = 3;
+ const uint64_t log2_10_fractional_digits = 0x5269e12f346e2bf9;
+ const int shift_amount = 19;
+ return (e * static_cast<int>(
+ (log2_10_integer_part << shift_amount) |
+ (log2_10_fractional_digits >> (64 - shift_amount)))) >>
+ shift_amount;
+}
+inline int floor_log10_pow2_minus_log10_4_over_3(int e) FMT_NOEXCEPT {
+ FMT_ASSERT(e <= 1700 && e >= -1700, "too large exponent");
+ const uint64_t log10_4_over_3_fractional_digits = 0x1ffbfc2bbc780375;
+ const int shift_amount = 22;
+ return (e * static_cast<int>(log10_2_significand >> (64 - shift_amount)) -
+ static_cast<int>(log10_4_over_3_fractional_digits >>
+ (64 - shift_amount))) >>
+ shift_amount;
+}
+
+// Returns true iff x is divisible by pow(2, exp).
+inline bool divisible_by_power_of_2(uint32_t x, int exp) FMT_NOEXCEPT {
+ FMT_ASSERT(exp >= 1, "");
+ FMT_ASSERT(x != 0, "");
+#ifdef FMT_BUILTIN_CTZ
+ return FMT_BUILTIN_CTZ(x) >= exp;
+#else
+ return exp < num_bits<uint32_t>() && x == ((x >> exp) << exp);
+#endif
+}
+inline bool divisible_by_power_of_2(uint64_t x, int exp) FMT_NOEXCEPT {
+ FMT_ASSERT(exp >= 1, "");
+ FMT_ASSERT(x != 0, "");
+#ifdef FMT_BUILTIN_CTZLL
+ return FMT_BUILTIN_CTZLL(x) >= exp;
+#else
+ return exp < num_bits<uint64_t>() && x == ((x >> exp) << exp);
+#endif
+}
+
+// Table entry type for divisibility test.
+template <typename T> struct divtest_table_entry {
+ T mod_inv;
+ T max_quotient;
+};
+
+// Returns true iff x is divisible by pow(5, exp).
+inline bool divisible_by_power_of_5(uint32_t x, int exp) FMT_NOEXCEPT {
+ FMT_ASSERT(exp <= 10, "too large exponent");
+ static constexpr const divtest_table_entry<uint32_t> divtest_table[] = {
+ {0x00000001, 0xffffffff}, {0xcccccccd, 0x33333333},
+ {0xc28f5c29, 0x0a3d70a3}, {0x26e978d5, 0x020c49ba},
+ {0x3afb7e91, 0x0068db8b}, {0x0bcbe61d, 0x0014f8b5},
+ {0x68c26139, 0x000431bd}, {0xae8d46a5, 0x0000d6bf},
+ {0x22e90e21, 0x00002af3}, {0x3a2e9c6d, 0x00000897},
+ {0x3ed61f49, 0x000001b7}};
+ return x * divtest_table[exp].mod_inv <= divtest_table[exp].max_quotient;
+}
+inline bool divisible_by_power_of_5(uint64_t x, int exp) FMT_NOEXCEPT {
+ FMT_ASSERT(exp <= 23, "too large exponent");
+ static constexpr const divtest_table_entry<uint64_t> divtest_table[] = {
+ {0x0000000000000001, 0xffffffffffffffff},
+ {0xcccccccccccccccd, 0x3333333333333333},
+ {0x8f5c28f5c28f5c29, 0x0a3d70a3d70a3d70},
+ {0x1cac083126e978d5, 0x020c49ba5e353f7c},
+ {0xd288ce703afb7e91, 0x0068db8bac710cb2},
+ {0x5d4e8fb00bcbe61d, 0x0014f8b588e368f0},
+ {0x790fb65668c26139, 0x000431bde82d7b63},
+ {0xe5032477ae8d46a5, 0x0000d6bf94d5e57a},
+ {0xc767074b22e90e21, 0x00002af31dc46118},
+ {0x8e47ce423a2e9c6d, 0x0000089705f4136b},
+ {0x4fa7f60d3ed61f49, 0x000001b7cdfd9d7b},
+ {0x0fee64690c913975, 0x00000057f5ff85e5},
+ {0x3662e0e1cf503eb1, 0x000000119799812d},
+ {0xa47a2cf9f6433fbd, 0x0000000384b84d09},
+ {0x54186f653140a659, 0x00000000b424dc35},
+ {0x7738164770402145, 0x0000000024075f3d},
+ {0xe4a4d1417cd9a041, 0x000000000734aca5},
+ {0xc75429d9e5c5200d, 0x000000000170ef54},
+ {0xc1773b91fac10669, 0x000000000049c977},
+ {0x26b172506559ce15, 0x00000000000ec1e4},
+ {0xd489e3a9addec2d1, 0x000000000002f394},
+ {0x90e860bb892c8d5d, 0x000000000000971d},
+ {0x502e79bf1b6f4f79, 0x0000000000001e39},
+ {0xdcd618596be30fe5, 0x000000000000060b}};
+ return x * divtest_table[exp].mod_inv <= divtest_table[exp].max_quotient;
+}
+
+// Replaces n by floor(n / pow(5, N)) returning true if and only if n is
+// divisible by pow(5, N).
+// Precondition: n <= 2 * pow(5, N + 1).
+template <int N>
+bool check_divisibility_and_divide_by_pow5(uint32_t& n) FMT_NOEXCEPT {
+ static constexpr struct {
+ uint32_t magic_number;
+ int bits_for_comparison;
+ uint32_t threshold;
+ int shift_amount;
+ } infos[] = {{0xcccd, 16, 0x3333, 18}, {0xa429, 8, 0x0a, 20}};
+ constexpr auto info = infos[N - 1];
+ n *= info.magic_number;
+ const uint32_t comparison_mask = (1u << info.bits_for_comparison) - 1;
+ bool result = (n & comparison_mask) <= info.threshold;
+ n >>= info.shift_amount;
+ return result;
+}
+
+// Computes floor(n / pow(10, N)) for small n and N.
+// Precondition: n <= pow(10, N + 1).
+template <int N> uint32_t small_division_by_pow10(uint32_t n) FMT_NOEXCEPT {
+ static constexpr struct {
+ uint32_t magic_number;
+ int shift_amount;
+ uint32_t divisor_times_10;
+ } infos[] = {{0xcccd, 19, 100}, {0xa3d8, 22, 1000}};
+ constexpr auto info = infos[N - 1];
+ FMT_ASSERT(n <= info.divisor_times_10, "n is too large");
+ return n * info.magic_number >> info.shift_amount;
+}
+
+// Computes floor(n / 10^(kappa + 1)) (float)
+inline uint32_t divide_by_10_to_kappa_plus_1(uint32_t n) FMT_NOEXCEPT {
+ return n / float_info<float>::big_divisor;
+}
+// Computes floor(n / 10^(kappa + 1)) (double)
+inline uint64_t divide_by_10_to_kappa_plus_1(uint64_t n) FMT_NOEXCEPT {
+ return umul128_upper64(n, 0x83126e978d4fdf3c) >> 9;
+}
+
+// Various subroutines using pow10 cache
+template <class T> struct cache_accessor;
+
+template <> struct cache_accessor<float> {
+ using carrier_uint = float_info<float>::carrier_uint;
+ using cache_entry_type = uint64_t;
+
+ static uint64_t get_cached_power(int k) FMT_NOEXCEPT {
+ FMT_ASSERT(k >= float_info<float>::min_k && k <= float_info<float>::max_k,
+ "k is out of range");
+ static constexpr const uint64_t pow10_significands[] = {
+ 0x81ceb32c4b43fcf5, 0xa2425ff75e14fc32, 0xcad2f7f5359a3b3f,
+ 0xfd87b5f28300ca0e, 0x9e74d1b791e07e49, 0xc612062576589ddb,
+ 0xf79687aed3eec552, 0x9abe14cd44753b53, 0xc16d9a0095928a28,
+ 0xf1c90080baf72cb2, 0x971da05074da7bef, 0xbce5086492111aeb,
+ 0xec1e4a7db69561a6, 0x9392ee8e921d5d08, 0xb877aa3236a4b44a,
+ 0xe69594bec44de15c, 0x901d7cf73ab0acda, 0xb424dc35095cd810,
+ 0xe12e13424bb40e14, 0x8cbccc096f5088cc, 0xafebff0bcb24aaff,
+ 0xdbe6fecebdedd5bf, 0x89705f4136b4a598, 0xabcc77118461cefd,
+ 0xd6bf94d5e57a42bd, 0x8637bd05af6c69b6, 0xa7c5ac471b478424,
+ 0xd1b71758e219652c, 0x83126e978d4fdf3c, 0xa3d70a3d70a3d70b,
+ 0xcccccccccccccccd, 0x8000000000000000, 0xa000000000000000,
+ 0xc800000000000000, 0xfa00000000000000, 0x9c40000000000000,
+ 0xc350000000000000, 0xf424000000000000, 0x9896800000000000,
+ 0xbebc200000000000, 0xee6b280000000000, 0x9502f90000000000,
+ 0xba43b74000000000, 0xe8d4a51000000000, 0x9184e72a00000000,
+ 0xb5e620f480000000, 0xe35fa931a0000000, 0x8e1bc9bf04000000,
+ 0xb1a2bc2ec5000000, 0xde0b6b3a76400000, 0x8ac7230489e80000,
+ 0xad78ebc5ac620000, 0xd8d726b7177a8000, 0x878678326eac9000,
+ 0xa968163f0a57b400, 0xd3c21bcecceda100, 0x84595161401484a0,
+ 0xa56fa5b99019a5c8, 0xcecb8f27f4200f3a, 0x813f3978f8940984,
+ 0xa18f07d736b90be5, 0xc9f2c9cd04674ede, 0xfc6f7c4045812296,
+ 0x9dc5ada82b70b59d, 0xc5371912364ce305, 0xf684df56c3e01bc6,
+ 0x9a130b963a6c115c, 0xc097ce7bc90715b3, 0xf0bdc21abb48db20,
+ 0x96769950b50d88f4, 0xbc143fa4e250eb31, 0xeb194f8e1ae525fd,
+ 0x92efd1b8d0cf37be, 0xb7abc627050305ad, 0xe596b7b0c643c719,
+ 0x8f7e32ce7bea5c6f, 0xb35dbf821ae4f38b, 0xe0352f62a19e306e};
+ return pow10_significands[k - float_info<float>::min_k];
+ }
+
+ static carrier_uint compute_mul(carrier_uint u,
+ const cache_entry_type& cache) FMT_NOEXCEPT {
+ return umul96_upper32(u, cache);
+ }
+
+ static uint32_t compute_delta(const cache_entry_type& cache,
+ int beta_minus_1) FMT_NOEXCEPT {
+ return static_cast<uint32_t>(cache >> (64 - 1 - beta_minus_1));
+ }
+
+ static bool compute_mul_parity(carrier_uint two_f,
+ const cache_entry_type& cache,
+ int beta_minus_1) FMT_NOEXCEPT {
+ FMT_ASSERT(beta_minus_1 >= 1, "");
+ FMT_ASSERT(beta_minus_1 < 64, "");
+
+ return ((umul96_lower64(two_f, cache) >> (64 - beta_minus_1)) & 1) != 0;
+ }
+
+ static carrier_uint compute_left_endpoint_for_shorter_interval_case(
+ const cache_entry_type& cache, int beta_minus_1) FMT_NOEXCEPT {
+ return static_cast<carrier_uint>(
+ (cache - (cache >> (float_info<float>::significand_bits + 2))) >>
+ (64 - float_info<float>::significand_bits - 1 - beta_minus_1));
+ }
+
+ static carrier_uint compute_right_endpoint_for_shorter_interval_case(
+ const cache_entry_type& cache, int beta_minus_1) FMT_NOEXCEPT {
+ return static_cast<carrier_uint>(
+ (cache + (cache >> (float_info<float>::significand_bits + 1))) >>
+ (64 - float_info<float>::significand_bits - 1 - beta_minus_1));
+ }
+
+ static carrier_uint compute_round_up_for_shorter_interval_case(
+ const cache_entry_type& cache, int beta_minus_1) FMT_NOEXCEPT {
+ return (static_cast<carrier_uint>(
+ cache >>
+ (64 - float_info<float>::significand_bits - 2 - beta_minus_1)) +
+ 1) /
+ 2;
+ }
+};
+
+template <> struct cache_accessor<double> {
+ using carrier_uint = float_info<double>::carrier_uint;
+ using cache_entry_type = uint128_wrapper;
+
+ static uint128_wrapper get_cached_power(int k) FMT_NOEXCEPT {
+ FMT_ASSERT(k >= float_info<double>::min_k && k <= float_info<double>::max_k,
+ "k is out of range");
+
+ static constexpr const uint128_wrapper pow10_significands[] = {
+#if FMT_USE_FULL_CACHE_DRAGONBOX
+ {0xff77b1fcbebcdc4f, 0x25e8e89c13bb0f7b},
+ {0x9faacf3df73609b1, 0x77b191618c54e9ad},
+ {0xc795830d75038c1d, 0xd59df5b9ef6a2418},
+ {0xf97ae3d0d2446f25, 0x4b0573286b44ad1e},
+ {0x9becce62836ac577, 0x4ee367f9430aec33},
+ {0xc2e801fb244576d5, 0x229c41f793cda740},
+ {0xf3a20279ed56d48a, 0x6b43527578c11110},
+ {0x9845418c345644d6, 0x830a13896b78aaaa},
+ {0xbe5691ef416bd60c, 0x23cc986bc656d554},
+ {0xedec366b11c6cb8f, 0x2cbfbe86b7ec8aa9},
+ {0x94b3a202eb1c3f39, 0x7bf7d71432f3d6aa},
+ {0xb9e08a83a5e34f07, 0xdaf5ccd93fb0cc54},
+ {0xe858ad248f5c22c9, 0xd1b3400f8f9cff69},
+ {0x91376c36d99995be, 0x23100809b9c21fa2},
+ {0xb58547448ffffb2d, 0xabd40a0c2832a78b},
+ {0xe2e69915b3fff9f9, 0x16c90c8f323f516d},
+ {0x8dd01fad907ffc3b, 0xae3da7d97f6792e4},
+ {0xb1442798f49ffb4a, 0x99cd11cfdf41779d},
+ {0xdd95317f31c7fa1d, 0x40405643d711d584},
+ {0x8a7d3eef7f1cfc52, 0x482835ea666b2573},
+ {0xad1c8eab5ee43b66, 0xda3243650005eed0},
+ {0xd863b256369d4a40, 0x90bed43e40076a83},
+ {0x873e4f75e2224e68, 0x5a7744a6e804a292},
+ {0xa90de3535aaae202, 0x711515d0a205cb37},
+ {0xd3515c2831559a83, 0x0d5a5b44ca873e04},
+ {0x8412d9991ed58091, 0xe858790afe9486c3},
+ {0xa5178fff668ae0b6, 0x626e974dbe39a873},
+ {0xce5d73ff402d98e3, 0xfb0a3d212dc81290},
+ {0x80fa687f881c7f8e, 0x7ce66634bc9d0b9a},
+ {0xa139029f6a239f72, 0x1c1fffc1ebc44e81},
+ {0xc987434744ac874e, 0xa327ffb266b56221},
+ {0xfbe9141915d7a922, 0x4bf1ff9f0062baa9},
+ {0x9d71ac8fada6c9b5, 0x6f773fc3603db4aa},
+ {0xc4ce17b399107c22, 0xcb550fb4384d21d4},
+ {0xf6019da07f549b2b, 0x7e2a53a146606a49},
+ {0x99c102844f94e0fb, 0x2eda7444cbfc426e},
+ {0xc0314325637a1939, 0xfa911155fefb5309},
+ {0xf03d93eebc589f88, 0x793555ab7eba27cb},
+ {0x96267c7535b763b5, 0x4bc1558b2f3458df},
+ {0xbbb01b9283253ca2, 0x9eb1aaedfb016f17},
+ {0xea9c227723ee8bcb, 0x465e15a979c1cadd},
+ {0x92a1958a7675175f, 0x0bfacd89ec191eca},
+ {0xb749faed14125d36, 0xcef980ec671f667c},
+ {0xe51c79a85916f484, 0x82b7e12780e7401b},
+ {0x8f31cc0937ae58d2, 0xd1b2ecb8b0908811},
+ {0xb2fe3f0b8599ef07, 0x861fa7e6dcb4aa16},
+ {0xdfbdcece67006ac9, 0x67a791e093e1d49b},
+ {0x8bd6a141006042bd, 0xe0c8bb2c5c6d24e1},
+ {0xaecc49914078536d, 0x58fae9f773886e19},
+ {0xda7f5bf590966848, 0xaf39a475506a899f},
+ {0x888f99797a5e012d, 0x6d8406c952429604},
+ {0xaab37fd7d8f58178, 0xc8e5087ba6d33b84},
+ {0xd5605fcdcf32e1d6, 0xfb1e4a9a90880a65},
+ {0x855c3be0a17fcd26, 0x5cf2eea09a550680},
+ {0xa6b34ad8c9dfc06f, 0xf42faa48c0ea481f},
+ {0xd0601d8efc57b08b, 0xf13b94daf124da27},
+ {0x823c12795db6ce57, 0x76c53d08d6b70859},
+ {0xa2cb1717b52481ed, 0x54768c4b0c64ca6f},
+ {0xcb7ddcdda26da268, 0xa9942f5dcf7dfd0a},
+ {0xfe5d54150b090b02, 0xd3f93b35435d7c4d},
+ {0x9efa548d26e5a6e1, 0xc47bc5014a1a6db0},
+ {0xc6b8e9b0709f109a, 0x359ab6419ca1091c},
+ {0xf867241c8cc6d4c0, 0xc30163d203c94b63},
+ {0x9b407691d7fc44f8, 0x79e0de63425dcf1e},
+ {0xc21094364dfb5636, 0x985915fc12f542e5},
+ {0xf294b943e17a2bc4, 0x3e6f5b7b17b2939e},
+ {0x979cf3ca6cec5b5a, 0xa705992ceecf9c43},
+ {0xbd8430bd08277231, 0x50c6ff782a838354},
+ {0xece53cec4a314ebd, 0xa4f8bf5635246429},
+ {0x940f4613ae5ed136, 0x871b7795e136be9a},
+ {0xb913179899f68584, 0x28e2557b59846e40},
+ {0xe757dd7ec07426e5, 0x331aeada2fe589d0},
+ {0x9096ea6f3848984f, 0x3ff0d2c85def7622},
+ {0xb4bca50b065abe63, 0x0fed077a756b53aa},
+ {0xe1ebce4dc7f16dfb, 0xd3e8495912c62895},
+ {0x8d3360f09cf6e4bd, 0x64712dd7abbbd95d},
+ {0xb080392cc4349dec, 0xbd8d794d96aacfb4},
+ {0xdca04777f541c567, 0xecf0d7a0fc5583a1},
+ {0x89e42caaf9491b60, 0xf41686c49db57245},
+ {0xac5d37d5b79b6239, 0x311c2875c522ced6},
+ {0xd77485cb25823ac7, 0x7d633293366b828c},
+ {0x86a8d39ef77164bc, 0xae5dff9c02033198},
+ {0xa8530886b54dbdeb, 0xd9f57f830283fdfd},
+ {0xd267caa862a12d66, 0xd072df63c324fd7c},
+ {0x8380dea93da4bc60, 0x4247cb9e59f71e6e},
+ {0xa46116538d0deb78, 0x52d9be85f074e609},
+ {0xcd795be870516656, 0x67902e276c921f8c},
+ {0x806bd9714632dff6, 0x00ba1cd8a3db53b7},
+ {0xa086cfcd97bf97f3, 0x80e8a40eccd228a5},
+ {0xc8a883c0fdaf7df0, 0x6122cd128006b2ce},
+ {0xfad2a4b13d1b5d6c, 0x796b805720085f82},
+ {0x9cc3a6eec6311a63, 0xcbe3303674053bb1},
+ {0xc3f490aa77bd60fc, 0xbedbfc4411068a9d},
+ {0xf4f1b4d515acb93b, 0xee92fb5515482d45},
+ {0x991711052d8bf3c5, 0x751bdd152d4d1c4b},
+ {0xbf5cd54678eef0b6, 0xd262d45a78a0635e},
+ {0xef340a98172aace4, 0x86fb897116c87c35},
+ {0x9580869f0e7aac0e, 0xd45d35e6ae3d4da1},
+ {0xbae0a846d2195712, 0x8974836059cca10a},
+ {0xe998d258869facd7, 0x2bd1a438703fc94c},
+ {0x91ff83775423cc06, 0x7b6306a34627ddd0},
+ {0xb67f6455292cbf08, 0x1a3bc84c17b1d543},
+ {0xe41f3d6a7377eeca, 0x20caba5f1d9e4a94},
+ {0x8e938662882af53e, 0x547eb47b7282ee9d},
+ {0xb23867fb2a35b28d, 0xe99e619a4f23aa44},
+ {0xdec681f9f4c31f31, 0x6405fa00e2ec94d5},
+ {0x8b3c113c38f9f37e, 0xde83bc408dd3dd05},
+ {0xae0b158b4738705e, 0x9624ab50b148d446},
+ {0xd98ddaee19068c76, 0x3badd624dd9b0958},
+ {0x87f8a8d4cfa417c9, 0xe54ca5d70a80e5d7},
+ {0xa9f6d30a038d1dbc, 0x5e9fcf4ccd211f4d},
+ {0xd47487cc8470652b, 0x7647c32000696720},
+ {0x84c8d4dfd2c63f3b, 0x29ecd9f40041e074},
+ {0xa5fb0a17c777cf09, 0xf468107100525891},
+ {0xcf79cc9db955c2cc, 0x7182148d4066eeb5},
+ {0x81ac1fe293d599bf, 0xc6f14cd848405531},
+ {0xa21727db38cb002f, 0xb8ada00e5a506a7d},
+ {0xca9cf1d206fdc03b, 0xa6d90811f0e4851d},
+ {0xfd442e4688bd304a, 0x908f4a166d1da664},
+ {0x9e4a9cec15763e2e, 0x9a598e4e043287ff},
+ {0xc5dd44271ad3cdba, 0x40eff1e1853f29fe},
+ {0xf7549530e188c128, 0xd12bee59e68ef47d},
+ {0x9a94dd3e8cf578b9, 0x82bb74f8301958cf},
+ {0xc13a148e3032d6e7, 0xe36a52363c1faf02},
+ {0xf18899b1bc3f8ca1, 0xdc44e6c3cb279ac2},
+ {0x96f5600f15a7b7e5, 0x29ab103a5ef8c0ba},
+ {0xbcb2b812db11a5de, 0x7415d448f6b6f0e8},
+ {0xebdf661791d60f56, 0x111b495b3464ad22},
+ {0x936b9fcebb25c995, 0xcab10dd900beec35},
+ {0xb84687c269ef3bfb, 0x3d5d514f40eea743},
+ {0xe65829b3046b0afa, 0x0cb4a5a3112a5113},
+ {0x8ff71a0fe2c2e6dc, 0x47f0e785eaba72ac},
+ {0xb3f4e093db73a093, 0x59ed216765690f57},
+ {0xe0f218b8d25088b8, 0x306869c13ec3532d},
+ {0x8c974f7383725573, 0x1e414218c73a13fc},
+ {0xafbd2350644eeacf, 0xe5d1929ef90898fb},
+ {0xdbac6c247d62a583, 0xdf45f746b74abf3a},
+ {0x894bc396ce5da772, 0x6b8bba8c328eb784},
+ {0xab9eb47c81f5114f, 0x066ea92f3f326565},
+ {0xd686619ba27255a2, 0xc80a537b0efefebe},
+ {0x8613fd0145877585, 0xbd06742ce95f5f37},
+ {0xa798fc4196e952e7, 0x2c48113823b73705},
+ {0xd17f3b51fca3a7a0, 0xf75a15862ca504c6},
+ {0x82ef85133de648c4, 0x9a984d73dbe722fc},
+ {0xa3ab66580d5fdaf5, 0xc13e60d0d2e0ebbb},
+ {0xcc963fee10b7d1b3, 0x318df905079926a9},
+ {0xffbbcfe994e5c61f, 0xfdf17746497f7053},
+ {0x9fd561f1fd0f9bd3, 0xfeb6ea8bedefa634},
+ {0xc7caba6e7c5382c8, 0xfe64a52ee96b8fc1},
+ {0xf9bd690a1b68637b, 0x3dfdce7aa3c673b1},
+ {0x9c1661a651213e2d, 0x06bea10ca65c084f},
+ {0xc31bfa0fe5698db8, 0x486e494fcff30a63},
+ {0xf3e2f893dec3f126, 0x5a89dba3c3efccfb},
+ {0x986ddb5c6b3a76b7, 0xf89629465a75e01d},
+ {0xbe89523386091465, 0xf6bbb397f1135824},
+ {0xee2ba6c0678b597f, 0x746aa07ded582e2d},
+ {0x94db483840b717ef, 0xa8c2a44eb4571cdd},
+ {0xba121a4650e4ddeb, 0x92f34d62616ce414},
+ {0xe896a0d7e51e1566, 0x77b020baf9c81d18},
+ {0x915e2486ef32cd60, 0x0ace1474dc1d122f},
+ {0xb5b5ada8aaff80b8, 0x0d819992132456bb},
+ {0xe3231912d5bf60e6, 0x10e1fff697ed6c6a},
+ {0x8df5efabc5979c8f, 0xca8d3ffa1ef463c2},
+ {0xb1736b96b6fd83b3, 0xbd308ff8a6b17cb3},
+ {0xddd0467c64bce4a0, 0xac7cb3f6d05ddbdf},
+ {0x8aa22c0dbef60ee4, 0x6bcdf07a423aa96c},
+ {0xad4ab7112eb3929d, 0x86c16c98d2c953c7},
+ {0xd89d64d57a607744, 0xe871c7bf077ba8b8},
+ {0x87625f056c7c4a8b, 0x11471cd764ad4973},
+ {0xa93af6c6c79b5d2d, 0xd598e40d3dd89bd0},
+ {0xd389b47879823479, 0x4aff1d108d4ec2c4},
+ {0x843610cb4bf160cb, 0xcedf722a585139bb},
+ {0xa54394fe1eedb8fe, 0xc2974eb4ee658829},
+ {0xce947a3da6a9273e, 0x733d226229feea33},
+ {0x811ccc668829b887, 0x0806357d5a3f5260},
+ {0xa163ff802a3426a8, 0xca07c2dcb0cf26f8},
+ {0xc9bcff6034c13052, 0xfc89b393dd02f0b6},
+ {0xfc2c3f3841f17c67, 0xbbac2078d443ace3},
+ {0x9d9ba7832936edc0, 0xd54b944b84aa4c0e},
+ {0xc5029163f384a931, 0x0a9e795e65d4df12},
+ {0xf64335bcf065d37d, 0x4d4617b5ff4a16d6},
+ {0x99ea0196163fa42e, 0x504bced1bf8e4e46},
+ {0xc06481fb9bcf8d39, 0xe45ec2862f71e1d7},
+ {0xf07da27a82c37088, 0x5d767327bb4e5a4d},
+ {0x964e858c91ba2655, 0x3a6a07f8d510f870},
+ {0xbbe226efb628afea, 0x890489f70a55368c},
+ {0xeadab0aba3b2dbe5, 0x2b45ac74ccea842f},
+ {0x92c8ae6b464fc96f, 0x3b0b8bc90012929e},
+ {0xb77ada0617e3bbcb, 0x09ce6ebb40173745},
+ {0xe55990879ddcaabd, 0xcc420a6a101d0516},
+ {0x8f57fa54c2a9eab6, 0x9fa946824a12232e},
+ {0xb32df8e9f3546564, 0x47939822dc96abfa},
+ {0xdff9772470297ebd, 0x59787e2b93bc56f8},
+ {0x8bfbea76c619ef36, 0x57eb4edb3c55b65b},
+ {0xaefae51477a06b03, 0xede622920b6b23f2},
+ {0xdab99e59958885c4, 0xe95fab368e45ecee},
+ {0x88b402f7fd75539b, 0x11dbcb0218ebb415},
+ {0xaae103b5fcd2a881, 0xd652bdc29f26a11a},
+ {0xd59944a37c0752a2, 0x4be76d3346f04960},
+ {0x857fcae62d8493a5, 0x6f70a4400c562ddc},
+ {0xa6dfbd9fb8e5b88e, 0xcb4ccd500f6bb953},
+ {0xd097ad07a71f26b2, 0x7e2000a41346a7a8},
+ {0x825ecc24c873782f, 0x8ed400668c0c28c9},
+ {0xa2f67f2dfa90563b, 0x728900802f0f32fb},
+ {0xcbb41ef979346bca, 0x4f2b40a03ad2ffba},
+ {0xfea126b7d78186bc, 0xe2f610c84987bfa9},
+ {0x9f24b832e6b0f436, 0x0dd9ca7d2df4d7ca},
+ {0xc6ede63fa05d3143, 0x91503d1c79720dbc},
+ {0xf8a95fcf88747d94, 0x75a44c6397ce912b},
+ {0x9b69dbe1b548ce7c, 0xc986afbe3ee11abb},
+ {0xc24452da229b021b, 0xfbe85badce996169},
+ {0xf2d56790ab41c2a2, 0xfae27299423fb9c4},
+ {0x97c560ba6b0919a5, 0xdccd879fc967d41b},
+ {0xbdb6b8e905cb600f, 0x5400e987bbc1c921},
+ {0xed246723473e3813, 0x290123e9aab23b69},
+ {0x9436c0760c86e30b, 0xf9a0b6720aaf6522},
+ {0xb94470938fa89bce, 0xf808e40e8d5b3e6a},
+ {0xe7958cb87392c2c2, 0xb60b1d1230b20e05},
+ {0x90bd77f3483bb9b9, 0xb1c6f22b5e6f48c3},
+ {0xb4ecd5f01a4aa828, 0x1e38aeb6360b1af4},
+ {0xe2280b6c20dd5232, 0x25c6da63c38de1b1},
+ {0x8d590723948a535f, 0x579c487e5a38ad0f},
+ {0xb0af48ec79ace837, 0x2d835a9df0c6d852},
+ {0xdcdb1b2798182244, 0xf8e431456cf88e66},
+ {0x8a08f0f8bf0f156b, 0x1b8e9ecb641b5900},
+ {0xac8b2d36eed2dac5, 0xe272467e3d222f40},
+ {0xd7adf884aa879177, 0x5b0ed81dcc6abb10},
+ {0x86ccbb52ea94baea, 0x98e947129fc2b4ea},
+ {0xa87fea27a539e9a5, 0x3f2398d747b36225},
+ {0xd29fe4b18e88640e, 0x8eec7f0d19a03aae},
+ {0x83a3eeeef9153e89, 0x1953cf68300424ad},
+ {0xa48ceaaab75a8e2b, 0x5fa8c3423c052dd8},
+ {0xcdb02555653131b6, 0x3792f412cb06794e},
+ {0x808e17555f3ebf11, 0xe2bbd88bbee40bd1},
+ {0xa0b19d2ab70e6ed6, 0x5b6aceaeae9d0ec5},
+ {0xc8de047564d20a8b, 0xf245825a5a445276},
+ {0xfb158592be068d2e, 0xeed6e2f0f0d56713},
+ {0x9ced737bb6c4183d, 0x55464dd69685606c},
+ {0xc428d05aa4751e4c, 0xaa97e14c3c26b887},
+ {0xf53304714d9265df, 0xd53dd99f4b3066a9},
+ {0x993fe2c6d07b7fab, 0xe546a8038efe402a},
+ {0xbf8fdb78849a5f96, 0xde98520472bdd034},
+ {0xef73d256a5c0f77c, 0x963e66858f6d4441},
+ {0x95a8637627989aad, 0xdde7001379a44aa9},
+ {0xbb127c53b17ec159, 0x5560c018580d5d53},
+ {0xe9d71b689dde71af, 0xaab8f01e6e10b4a7},
+ {0x9226712162ab070d, 0xcab3961304ca70e9},
+ {0xb6b00d69bb55c8d1, 0x3d607b97c5fd0d23},
+ {0xe45c10c42a2b3b05, 0x8cb89a7db77c506b},
+ {0x8eb98a7a9a5b04e3, 0x77f3608e92adb243},
+ {0xb267ed1940f1c61c, 0x55f038b237591ed4},
+ {0xdf01e85f912e37a3, 0x6b6c46dec52f6689},
+ {0x8b61313bbabce2c6, 0x2323ac4b3b3da016},
+ {0xae397d8aa96c1b77, 0xabec975e0a0d081b},
+ {0xd9c7dced53c72255, 0x96e7bd358c904a22},
+ {0x881cea14545c7575, 0x7e50d64177da2e55},
+ {0xaa242499697392d2, 0xdde50bd1d5d0b9ea},
+ {0xd4ad2dbfc3d07787, 0x955e4ec64b44e865},
+ {0x84ec3c97da624ab4, 0xbd5af13bef0b113f},
+ {0xa6274bbdd0fadd61, 0xecb1ad8aeacdd58f},
+ {0xcfb11ead453994ba, 0x67de18eda5814af3},
+ {0x81ceb32c4b43fcf4, 0x80eacf948770ced8},
+ {0xa2425ff75e14fc31, 0xa1258379a94d028e},
+ {0xcad2f7f5359a3b3e, 0x096ee45813a04331},
+ {0xfd87b5f28300ca0d, 0x8bca9d6e188853fd},
+ {0x9e74d1b791e07e48, 0x775ea264cf55347e},
+ {0xc612062576589dda, 0x95364afe032a819e},
+ {0xf79687aed3eec551, 0x3a83ddbd83f52205},
+ {0x9abe14cd44753b52, 0xc4926a9672793543},
+ {0xc16d9a0095928a27, 0x75b7053c0f178294},
+ {0xf1c90080baf72cb1, 0x5324c68b12dd6339},
+ {0x971da05074da7bee, 0xd3f6fc16ebca5e04},
+ {0xbce5086492111aea, 0x88f4bb1ca6bcf585},
+ {0xec1e4a7db69561a5, 0x2b31e9e3d06c32e6},
+ {0x9392ee8e921d5d07, 0x3aff322e62439fd0},
+ {0xb877aa3236a4b449, 0x09befeb9fad487c3},
+ {0xe69594bec44de15b, 0x4c2ebe687989a9b4},
+ {0x901d7cf73ab0acd9, 0x0f9d37014bf60a11},
+ {0xb424dc35095cd80f, 0x538484c19ef38c95},
+ {0xe12e13424bb40e13, 0x2865a5f206b06fba},
+ {0x8cbccc096f5088cb, 0xf93f87b7442e45d4},
+ {0xafebff0bcb24aafe, 0xf78f69a51539d749},
+ {0xdbe6fecebdedd5be, 0xb573440e5a884d1c},
+ {0x89705f4136b4a597, 0x31680a88f8953031},
+ {0xabcc77118461cefc, 0xfdc20d2b36ba7c3e},
+ {0xd6bf94d5e57a42bc, 0x3d32907604691b4d},
+ {0x8637bd05af6c69b5, 0xa63f9a49c2c1b110},
+ {0xa7c5ac471b478423, 0x0fcf80dc33721d54},
+ {0xd1b71758e219652b, 0xd3c36113404ea4a9},
+ {0x83126e978d4fdf3b, 0x645a1cac083126ea},
+ {0xa3d70a3d70a3d70a, 0x3d70a3d70a3d70a4},
+ {0xcccccccccccccccc, 0xcccccccccccccccd},
+ {0x8000000000000000, 0x0000000000000000},
+ {0xa000000000000000, 0x0000000000000000},
+ {0xc800000000000000, 0x0000000000000000},
+ {0xfa00000000000000, 0x0000000000000000},
+ {0x9c40000000000000, 0x0000000000000000},
+ {0xc350000000000000, 0x0000000000000000},
+ {0xf424000000000000, 0x0000000000000000},
+ {0x9896800000000000, 0x0000000000000000},
+ {0xbebc200000000000, 0x0000000000000000},
+ {0xee6b280000000000, 0x0000000000000000},
+ {0x9502f90000000000, 0x0000000000000000},
+ {0xba43b74000000000, 0x0000000000000000},
+ {0xe8d4a51000000000, 0x0000000000000000},
+ {0x9184e72a00000000, 0x0000000000000000},
+ {0xb5e620f480000000, 0x0000000000000000},
+ {0xe35fa931a0000000, 0x0000000000000000},
+ {0x8e1bc9bf04000000, 0x0000000000000000},
+ {0xb1a2bc2ec5000000, 0x0000000000000000},
+ {0xde0b6b3a76400000, 0x0000000000000000},
+ {0x8ac7230489e80000, 0x0000000000000000},
+ {0xad78ebc5ac620000, 0x0000000000000000},
+ {0xd8d726b7177a8000, 0x0000000000000000},
+ {0x878678326eac9000, 0x0000000000000000},
+ {0xa968163f0a57b400, 0x0000000000000000},
+ {0xd3c21bcecceda100, 0x0000000000000000},
+ {0x84595161401484a0, 0x0000000000000000},
+ {0xa56fa5b99019a5c8, 0x0000000000000000},
+ {0xcecb8f27f4200f3a, 0x0000000000000000},
+ {0x813f3978f8940984, 0x4000000000000000},
+ {0xa18f07d736b90be5, 0x5000000000000000},
+ {0xc9f2c9cd04674ede, 0xa400000000000000},
+ {0xfc6f7c4045812296, 0x4d00000000000000},
+ {0x9dc5ada82b70b59d, 0xf020000000000000},
+ {0xc5371912364ce305, 0x6c28000000000000},
+ {0xf684df56c3e01bc6, 0xc732000000000000},
+ {0x9a130b963a6c115c, 0x3c7f400000000000},
+ {0xc097ce7bc90715b3, 0x4b9f100000000000},
+ {0xf0bdc21abb48db20, 0x1e86d40000000000},
+ {0x96769950b50d88f4, 0x1314448000000000},
+ {0xbc143fa4e250eb31, 0x17d955a000000000},
+ {0xeb194f8e1ae525fd, 0x5dcfab0800000000},
+ {0x92efd1b8d0cf37be, 0x5aa1cae500000000},
+ {0xb7abc627050305ad, 0xf14a3d9e40000000},
+ {0xe596b7b0c643c719, 0x6d9ccd05d0000000},
+ {0x8f7e32ce7bea5c6f, 0xe4820023a2000000},
+ {0xb35dbf821ae4f38b, 0xdda2802c8a800000},
+ {0xe0352f62a19e306e, 0xd50b2037ad200000},
+ {0x8c213d9da502de45, 0x4526f422cc340000},
+ {0xaf298d050e4395d6, 0x9670b12b7f410000},
+ {0xdaf3f04651d47b4c, 0x3c0cdd765f114000},
+ {0x88d8762bf324cd0f, 0xa5880a69fb6ac800},
+ {0xab0e93b6efee0053, 0x8eea0d047a457a00},
+ {0xd5d238a4abe98068, 0x72a4904598d6d880},
+ {0x85a36366eb71f041, 0x47a6da2b7f864750},
+ {0xa70c3c40a64e6c51, 0x999090b65f67d924},
+ {0xd0cf4b50cfe20765, 0xfff4b4e3f741cf6d},
+ {0x82818f1281ed449f, 0xbff8f10e7a8921a4},
+ {0xa321f2d7226895c7, 0xaff72d52192b6a0d},
+ {0xcbea6f8ceb02bb39, 0x9bf4f8a69f764490},
+ {0xfee50b7025c36a08, 0x02f236d04753d5b4},
+ {0x9f4f2726179a2245, 0x01d762422c946590},
+ {0xc722f0ef9d80aad6, 0x424d3ad2b7b97ef5},
+ {0xf8ebad2b84e0d58b, 0xd2e0898765a7deb2},
+ {0x9b934c3b330c8577, 0x63cc55f49f88eb2f},
+ {0xc2781f49ffcfa6d5, 0x3cbf6b71c76b25fb},
+ {0xf316271c7fc3908a, 0x8bef464e3945ef7a},
+ {0x97edd871cfda3a56, 0x97758bf0e3cbb5ac},
+ {0xbde94e8e43d0c8ec, 0x3d52eeed1cbea317},
+ {0xed63a231d4c4fb27, 0x4ca7aaa863ee4bdd},
+ {0x945e455f24fb1cf8, 0x8fe8caa93e74ef6a},
+ {0xb975d6b6ee39e436, 0xb3e2fd538e122b44},
+ {0xe7d34c64a9c85d44, 0x60dbbca87196b616},
+ {0x90e40fbeea1d3a4a, 0xbc8955e946fe31cd},
+ {0xb51d13aea4a488dd, 0x6babab6398bdbe41},
+ {0xe264589a4dcdab14, 0xc696963c7eed2dd1},
+ {0x8d7eb76070a08aec, 0xfc1e1de5cf543ca2},
+ {0xb0de65388cc8ada8, 0x3b25a55f43294bcb},
+ {0xdd15fe86affad912, 0x49ef0eb713f39ebe},
+ {0x8a2dbf142dfcc7ab, 0x6e3569326c784337},
+ {0xacb92ed9397bf996, 0x49c2c37f07965404},
+ {0xd7e77a8f87daf7fb, 0xdc33745ec97be906},
+ {0x86f0ac99b4e8dafd, 0x69a028bb3ded71a3},
+ {0xa8acd7c0222311bc, 0xc40832ea0d68ce0c},
+ {0xd2d80db02aabd62b, 0xf50a3fa490c30190},
+ {0x83c7088e1aab65db, 0x792667c6da79e0fa},
+ {0xa4b8cab1a1563f52, 0x577001b891185938},
+ {0xcde6fd5e09abcf26, 0xed4c0226b55e6f86},
+ {0x80b05e5ac60b6178, 0x544f8158315b05b4},
+ {0xa0dc75f1778e39d6, 0x696361ae3db1c721},
+ {0xc913936dd571c84c, 0x03bc3a19cd1e38e9},
+ {0xfb5878494ace3a5f, 0x04ab48a04065c723},
+ {0x9d174b2dcec0e47b, 0x62eb0d64283f9c76},
+ {0xc45d1df942711d9a, 0x3ba5d0bd324f8394},
+ {0xf5746577930d6500, 0xca8f44ec7ee36479},
+ {0x9968bf6abbe85f20, 0x7e998b13cf4e1ecb},
+ {0xbfc2ef456ae276e8, 0x9e3fedd8c321a67e},
+ {0xefb3ab16c59b14a2, 0xc5cfe94ef3ea101e},
+ {0x95d04aee3b80ece5, 0xbba1f1d158724a12},
+ {0xbb445da9ca61281f, 0x2a8a6e45ae8edc97},
+ {0xea1575143cf97226, 0xf52d09d71a3293bd},
+ {0x924d692ca61be758, 0x593c2626705f9c56},
+ {0xb6e0c377cfa2e12e, 0x6f8b2fb00c77836c},
+ {0xe498f455c38b997a, 0x0b6dfb9c0f956447},
+ {0x8edf98b59a373fec, 0x4724bd4189bd5eac},
+ {0xb2977ee300c50fe7, 0x58edec91ec2cb657},
+ {0xdf3d5e9bc0f653e1, 0x2f2967b66737e3ed},
+ {0x8b865b215899f46c, 0xbd79e0d20082ee74},
+ {0xae67f1e9aec07187, 0xecd8590680a3aa11},
+ {0xda01ee641a708de9, 0xe80e6f4820cc9495},
+ {0x884134fe908658b2, 0x3109058d147fdcdd},
+ {0xaa51823e34a7eede, 0xbd4b46f0599fd415},
+ {0xd4e5e2cdc1d1ea96, 0x6c9e18ac7007c91a},
+ {0x850fadc09923329e, 0x03e2cf6bc604ddb0},
+ {0xa6539930bf6bff45, 0x84db8346b786151c},
+ {0xcfe87f7cef46ff16, 0xe612641865679a63},
+ {0x81f14fae158c5f6e, 0x4fcb7e8f3f60c07e},
+ {0xa26da3999aef7749, 0xe3be5e330f38f09d},
+ {0xcb090c8001ab551c, 0x5cadf5bfd3072cc5},
+ {0xfdcb4fa002162a63, 0x73d9732fc7c8f7f6},
+ {0x9e9f11c4014dda7e, 0x2867e7fddcdd9afa},
+ {0xc646d63501a1511d, 0xb281e1fd541501b8},
+ {0xf7d88bc24209a565, 0x1f225a7ca91a4226},
+ {0x9ae757596946075f, 0x3375788de9b06958},
+ {0xc1a12d2fc3978937, 0x0052d6b1641c83ae},
+ {0xf209787bb47d6b84, 0xc0678c5dbd23a49a},
+ {0x9745eb4d50ce6332, 0xf840b7ba963646e0},
+ {0xbd176620a501fbff, 0xb650e5a93bc3d898},
+ {0xec5d3fa8ce427aff, 0xa3e51f138ab4cebe},
+ {0x93ba47c980e98cdf, 0xc66f336c36b10137},
+ {0xb8a8d9bbe123f017, 0xb80b0047445d4184},
+ {0xe6d3102ad96cec1d, 0xa60dc059157491e5},
+ {0x9043ea1ac7e41392, 0x87c89837ad68db2f},
+ {0xb454e4a179dd1877, 0x29babe4598c311fb},
+ {0xe16a1dc9d8545e94, 0xf4296dd6fef3d67a},
+ {0x8ce2529e2734bb1d, 0x1899e4a65f58660c},
+ {0xb01ae745b101e9e4, 0x5ec05dcff72e7f8f},
+ {0xdc21a1171d42645d, 0x76707543f4fa1f73},
+ {0x899504ae72497eba, 0x6a06494a791c53a8},
+ {0xabfa45da0edbde69, 0x0487db9d17636892},
+ {0xd6f8d7509292d603, 0x45a9d2845d3c42b6},
+ {0x865b86925b9bc5c2, 0x0b8a2392ba45a9b2},
+ {0xa7f26836f282b732, 0x8e6cac7768d7141e},
+ {0xd1ef0244af2364ff, 0x3207d795430cd926},
+ {0x8335616aed761f1f, 0x7f44e6bd49e807b8},
+ {0xa402b9c5a8d3a6e7, 0x5f16206c9c6209a6},
+ {0xcd036837130890a1, 0x36dba887c37a8c0f},
+ {0x802221226be55a64, 0xc2494954da2c9789},
+ {0xa02aa96b06deb0fd, 0xf2db9baa10b7bd6c},
+ {0xc83553c5c8965d3d, 0x6f92829494e5acc7},
+ {0xfa42a8b73abbf48c, 0xcb772339ba1f17f9},
+ {0x9c69a97284b578d7, 0xff2a760414536efb},
+ {0xc38413cf25e2d70d, 0xfef5138519684aba},
+ {0xf46518c2ef5b8cd1, 0x7eb258665fc25d69},
+ {0x98bf2f79d5993802, 0xef2f773ffbd97a61},
+ {0xbeeefb584aff8603, 0xaafb550ffacfd8fa},
+ {0xeeaaba2e5dbf6784, 0x95ba2a53f983cf38},
+ {0x952ab45cfa97a0b2, 0xdd945a747bf26183},
+ {0xba756174393d88df, 0x94f971119aeef9e4},
+ {0xe912b9d1478ceb17, 0x7a37cd5601aab85d},
+ {0x91abb422ccb812ee, 0xac62e055c10ab33a},
+ {0xb616a12b7fe617aa, 0x577b986b314d6009},
+ {0xe39c49765fdf9d94, 0xed5a7e85fda0b80b},
+ {0x8e41ade9fbebc27d, 0x14588f13be847307},
+ {0xb1d219647ae6b31c, 0x596eb2d8ae258fc8},
+ {0xde469fbd99a05fe3, 0x6fca5f8ed9aef3bb},
+ {0x8aec23d680043bee, 0x25de7bb9480d5854},
+ {0xada72ccc20054ae9, 0xaf561aa79a10ae6a},
+ {0xd910f7ff28069da4, 0x1b2ba1518094da04},
+ {0x87aa9aff79042286, 0x90fb44d2f05d0842},
+ {0xa99541bf57452b28, 0x353a1607ac744a53},
+ {0xd3fa922f2d1675f2, 0x42889b8997915ce8},
+ {0x847c9b5d7c2e09b7, 0x69956135febada11},
+ {0xa59bc234db398c25, 0x43fab9837e699095},
+ {0xcf02b2c21207ef2e, 0x94f967e45e03f4bb},
+ {0x8161afb94b44f57d, 0x1d1be0eebac278f5},
+ {0xa1ba1ba79e1632dc, 0x6462d92a69731732},
+ {0xca28a291859bbf93, 0x7d7b8f7503cfdcfe},
+ {0xfcb2cb35e702af78, 0x5cda735244c3d43e},
+ {0x9defbf01b061adab, 0x3a0888136afa64a7},
+ {0xc56baec21c7a1916, 0x088aaa1845b8fdd0},
+ {0xf6c69a72a3989f5b, 0x8aad549e57273d45},
+ {0x9a3c2087a63f6399, 0x36ac54e2f678864b},
+ {0xc0cb28a98fcf3c7f, 0x84576a1bb416a7dd},
+ {0xf0fdf2d3f3c30b9f, 0x656d44a2a11c51d5},
+ {0x969eb7c47859e743, 0x9f644ae5a4b1b325},
+ {0xbc4665b596706114, 0x873d5d9f0dde1fee},
+ {0xeb57ff22fc0c7959, 0xa90cb506d155a7ea},
+ {0x9316ff75dd87cbd8, 0x09a7f12442d588f2},
+ {0xb7dcbf5354e9bece, 0x0c11ed6d538aeb2f},
+ {0xe5d3ef282a242e81, 0x8f1668c8a86da5fa},
+ {0x8fa475791a569d10, 0xf96e017d694487bc},
+ {0xb38d92d760ec4455, 0x37c981dcc395a9ac},
+ {0xe070f78d3927556a, 0x85bbe253f47b1417},
+ {0x8c469ab843b89562, 0x93956d7478ccec8e},
+ {0xaf58416654a6babb, 0x387ac8d1970027b2},
+ {0xdb2e51bfe9d0696a, 0x06997b05fcc0319e},
+ {0x88fcf317f22241e2, 0x441fece3bdf81f03},
+ {0xab3c2fddeeaad25a, 0xd527e81cad7626c3},
+ {0xd60b3bd56a5586f1, 0x8a71e223d8d3b074},
+ {0x85c7056562757456, 0xf6872d5667844e49},
+ {0xa738c6bebb12d16c, 0xb428f8ac016561db},
+ {0xd106f86e69d785c7, 0xe13336d701beba52},
+ {0x82a45b450226b39c, 0xecc0024661173473},
+ {0xa34d721642b06084, 0x27f002d7f95d0190},
+ {0xcc20ce9bd35c78a5, 0x31ec038df7b441f4},
+ {0xff290242c83396ce, 0x7e67047175a15271},
+ {0x9f79a169bd203e41, 0x0f0062c6e984d386},
+ {0xc75809c42c684dd1, 0x52c07b78a3e60868},
+ {0xf92e0c3537826145, 0xa7709a56ccdf8a82},
+ {0x9bbcc7a142b17ccb, 0x88a66076400bb691},
+ {0xc2abf989935ddbfe, 0x6acff893d00ea435},
+ {0xf356f7ebf83552fe, 0x0583f6b8c4124d43},
+ {0x98165af37b2153de, 0xc3727a337a8b704a},
+ {0xbe1bf1b059e9a8d6, 0x744f18c0592e4c5c},
+ {0xeda2ee1c7064130c, 0x1162def06f79df73},
+ {0x9485d4d1c63e8be7, 0x8addcb5645ac2ba8},
+ {0xb9a74a0637ce2ee1, 0x6d953e2bd7173692},
+ {0xe8111c87c5c1ba99, 0xc8fa8db6ccdd0437},
+ {0x910ab1d4db9914a0, 0x1d9c9892400a22a2},
+ {0xb54d5e4a127f59c8, 0x2503beb6d00cab4b},
+ {0xe2a0b5dc971f303a, 0x2e44ae64840fd61d},
+ {0x8da471a9de737e24, 0x5ceaecfed289e5d2},
+ {0xb10d8e1456105dad, 0x7425a83e872c5f47},
+ {0xdd50f1996b947518, 0xd12f124e28f77719},
+ {0x8a5296ffe33cc92f, 0x82bd6b70d99aaa6f},
+ {0xace73cbfdc0bfb7b, 0x636cc64d1001550b},
+ {0xd8210befd30efa5a, 0x3c47f7e05401aa4e},
+ {0x8714a775e3e95c78, 0x65acfaec34810a71},
+ {0xa8d9d1535ce3b396, 0x7f1839a741a14d0d},
+ {0xd31045a8341ca07c, 0x1ede48111209a050},
+ {0x83ea2b892091e44d, 0x934aed0aab460432},
+ {0xa4e4b66b68b65d60, 0xf81da84d5617853f},
+ {0xce1de40642e3f4b9, 0x36251260ab9d668e},
+ {0x80d2ae83e9ce78f3, 0xc1d72b7c6b426019},
+ {0xa1075a24e4421730, 0xb24cf65b8612f81f},
+ {0xc94930ae1d529cfc, 0xdee033f26797b627},
+ {0xfb9b7cd9a4a7443c, 0x169840ef017da3b1},
+ {0x9d412e0806e88aa5, 0x8e1f289560ee864e},
+ {0xc491798a08a2ad4e, 0xf1a6f2bab92a27e2},
+ {0xf5b5d7ec8acb58a2, 0xae10af696774b1db},
+ {0x9991a6f3d6bf1765, 0xacca6da1e0a8ef29},
+ {0xbff610b0cc6edd3f, 0x17fd090a58d32af3},
+ {0xeff394dcff8a948e, 0xddfc4b4cef07f5b0},
+ {0x95f83d0a1fb69cd9, 0x4abdaf101564f98e},
+ {0xbb764c4ca7a4440f, 0x9d6d1ad41abe37f1},
+ {0xea53df5fd18d5513, 0x84c86189216dc5ed},
+ {0x92746b9be2f8552c, 0x32fd3cf5b4e49bb4},
+ {0xb7118682dbb66a77, 0x3fbc8c33221dc2a1},
+ {0xe4d5e82392a40515, 0x0fabaf3feaa5334a},
+ {0x8f05b1163ba6832d, 0x29cb4d87f2a7400e},
+ {0xb2c71d5bca9023f8, 0x743e20e9ef511012},
+ {0xdf78e4b2bd342cf6, 0x914da9246b255416},
+ {0x8bab8eefb6409c1a, 0x1ad089b6c2f7548e},
+ {0xae9672aba3d0c320, 0xa184ac2473b529b1},
+ {0xda3c0f568cc4f3e8, 0xc9e5d72d90a2741e},
+ {0x8865899617fb1871, 0x7e2fa67c7a658892},
+ {0xaa7eebfb9df9de8d, 0xddbb901b98feeab7},
+ {0xd51ea6fa85785631, 0x552a74227f3ea565},
+ {0x8533285c936b35de, 0xd53a88958f87275f},
+ {0xa67ff273b8460356, 0x8a892abaf368f137},
+ {0xd01fef10a657842c, 0x2d2b7569b0432d85},
+ {0x8213f56a67f6b29b, 0x9c3b29620e29fc73},
+ {0xa298f2c501f45f42, 0x8349f3ba91b47b8f},
+ {0xcb3f2f7642717713, 0x241c70a936219a73},
+ {0xfe0efb53d30dd4d7, 0xed238cd383aa0110},
+ {0x9ec95d1463e8a506, 0xf4363804324a40aa},
+ {0xc67bb4597ce2ce48, 0xb143c6053edcd0d5},
+ {0xf81aa16fdc1b81da, 0xdd94b7868e94050a},
+ {0x9b10a4e5e9913128, 0xca7cf2b4191c8326},
+ {0xc1d4ce1f63f57d72, 0xfd1c2f611f63a3f0},
+ {0xf24a01a73cf2dccf, 0xbc633b39673c8cec},
+ {0x976e41088617ca01, 0xd5be0503e085d813},
+ {0xbd49d14aa79dbc82, 0x4b2d8644d8a74e18},
+ {0xec9c459d51852ba2, 0xddf8e7d60ed1219e},
+ {0x93e1ab8252f33b45, 0xcabb90e5c942b503},
+ {0xb8da1662e7b00a17, 0x3d6a751f3b936243},
+ {0xe7109bfba19c0c9d, 0x0cc512670a783ad4},
+ {0x906a617d450187e2, 0x27fb2b80668b24c5},
+ {0xb484f9dc9641e9da, 0xb1f9f660802dedf6},
+ {0xe1a63853bbd26451, 0x5e7873f8a0396973},
+ {0x8d07e33455637eb2, 0xdb0b487b6423e1e8},
+ {0xb049dc016abc5e5f, 0x91ce1a9a3d2cda62},
+ {0xdc5c5301c56b75f7, 0x7641a140cc7810fb},
+ {0x89b9b3e11b6329ba, 0xa9e904c87fcb0a9d},
+ {0xac2820d9623bf429, 0x546345fa9fbdcd44},
+ {0xd732290fbacaf133, 0xa97c177947ad4095},
+ {0x867f59a9d4bed6c0, 0x49ed8eabcccc485d},
+ {0xa81f301449ee8c70, 0x5c68f256bfff5a74},
+ {0xd226fc195c6a2f8c, 0x73832eec6fff3111},
+ {0x83585d8fd9c25db7, 0xc831fd53c5ff7eab},
+ {0xa42e74f3d032f525, 0xba3e7ca8b77f5e55},
+ {0xcd3a1230c43fb26f, 0x28ce1bd2e55f35eb},
+ {0x80444b5e7aa7cf85, 0x7980d163cf5b81b3},
+ {0xa0555e361951c366, 0xd7e105bcc332621f},
+ {0xc86ab5c39fa63440, 0x8dd9472bf3fefaa7},
+ {0xfa856334878fc150, 0xb14f98f6f0feb951},
+ {0x9c935e00d4b9d8d2, 0x6ed1bf9a569f33d3},
+ {0xc3b8358109e84f07, 0x0a862f80ec4700c8},
+ {0xf4a642e14c6262c8, 0xcd27bb612758c0fa},
+ {0x98e7e9cccfbd7dbd, 0x8038d51cb897789c},
+ {0xbf21e44003acdd2c, 0xe0470a63e6bd56c3},
+ {0xeeea5d5004981478, 0x1858ccfce06cac74},
+ {0x95527a5202df0ccb, 0x0f37801e0c43ebc8},
+ {0xbaa718e68396cffd, 0xd30560258f54e6ba},
+ {0xe950df20247c83fd, 0x47c6b82ef32a2069},
+ {0x91d28b7416cdd27e, 0x4cdc331d57fa5441},
+ {0xb6472e511c81471d, 0xe0133fe4adf8e952},
+ {0xe3d8f9e563a198e5, 0x58180fddd97723a6},
+ {0x8e679c2f5e44ff8f, 0x570f09eaa7ea7648},
+ {0xb201833b35d63f73, 0x2cd2cc6551e513da},
+ {0xde81e40a034bcf4f, 0xf8077f7ea65e58d1},
+ {0x8b112e86420f6191, 0xfb04afaf27faf782},
+ {0xadd57a27d29339f6, 0x79c5db9af1f9b563},
+ {0xd94ad8b1c7380874, 0x18375281ae7822bc},
+ {0x87cec76f1c830548, 0x8f2293910d0b15b5},
+ {0xa9c2794ae3a3c69a, 0xb2eb3875504ddb22},
+ {0xd433179d9c8cb841, 0x5fa60692a46151eb},
+ {0x849feec281d7f328, 0xdbc7c41ba6bcd333},
+ {0xa5c7ea73224deff3, 0x12b9b522906c0800},
+ {0xcf39e50feae16bef, 0xd768226b34870a00},
+ {0x81842f29f2cce375, 0xe6a1158300d46640},
+ {0xa1e53af46f801c53, 0x60495ae3c1097fd0},
+ {0xca5e89b18b602368, 0x385bb19cb14bdfc4},
+ {0xfcf62c1dee382c42, 0x46729e03dd9ed7b5},
+ {0x9e19db92b4e31ba9, 0x6c07a2c26a8346d1},
+ {0xc5a05277621be293, 0xc7098b7305241885},
+ { 0xf70867153aa2db38,
+ 0xb8cbee4fc66d1ea7 }
+#else
+ {0xff77b1fcbebcdc4f, 0x25e8e89c13bb0f7b},
+ {0xce5d73ff402d98e3, 0xfb0a3d212dc81290},
+ {0xa6b34ad8c9dfc06f, 0xf42faa48c0ea481f},
+ {0x86a8d39ef77164bc, 0xae5dff9c02033198},
+ {0xd98ddaee19068c76, 0x3badd624dd9b0958},
+ {0xafbd2350644eeacf, 0xe5d1929ef90898fb},
+ {0x8df5efabc5979c8f, 0xca8d3ffa1ef463c2},
+ {0xe55990879ddcaabd, 0xcc420a6a101d0516},
+ {0xb94470938fa89bce, 0xf808e40e8d5b3e6a},
+ {0x95a8637627989aad, 0xdde7001379a44aa9},
+ {0xf1c90080baf72cb1, 0x5324c68b12dd6339},
+ {0xc350000000000000, 0x0000000000000000},
+ {0x9dc5ada82b70b59d, 0xf020000000000000},
+ {0xfee50b7025c36a08, 0x02f236d04753d5b4},
+ {0xcde6fd5e09abcf26, 0xed4c0226b55e6f86},
+ {0xa6539930bf6bff45, 0x84db8346b786151c},
+ {0x865b86925b9bc5c2, 0x0b8a2392ba45a9b2},
+ {0xd910f7ff28069da4, 0x1b2ba1518094da04},
+ {0xaf58416654a6babb, 0x387ac8d1970027b2},
+ {0x8da471a9de737e24, 0x5ceaecfed289e5d2},
+ {0xe4d5e82392a40515, 0x0fabaf3feaa5334a},
+ {0xb8da1662e7b00a17, 0x3d6a751f3b936243},
+ { 0x95527a5202df0ccb,
+ 0x0f37801e0c43ebc8 }
+#endif
+ };
+
+#if FMT_USE_FULL_CACHE_DRAGONBOX
+ return pow10_significands[k - float_info<double>::min_k];
+#else
+ static constexpr const uint64_t powers_of_5_64[] = {
+ 0x0000000000000001, 0x0000000000000005, 0x0000000000000019,
+ 0x000000000000007d, 0x0000000000000271, 0x0000000000000c35,
+ 0x0000000000003d09, 0x000000000001312d, 0x000000000005f5e1,
+ 0x00000000001dcd65, 0x00000000009502f9, 0x0000000002e90edd,
+ 0x000000000e8d4a51, 0x0000000048c27395, 0x000000016bcc41e9,
+ 0x000000071afd498d, 0x0000002386f26fc1, 0x000000b1a2bc2ec5,
+ 0x000003782dace9d9, 0x00001158e460913d, 0x000056bc75e2d631,
+ 0x0001b1ae4d6e2ef5, 0x000878678326eac9, 0x002a5a058fc295ed,
+ 0x00d3c21bcecceda1, 0x0422ca8b0a00a425, 0x14adf4b7320334b9};
+
+ static constexpr const uint32_t pow10_recovery_errors[] = {
+ 0x50001400, 0x54044100, 0x54014555, 0x55954415, 0x54115555, 0x00000001,
+ 0x50000000, 0x00104000, 0x54010004, 0x05004001, 0x55555544, 0x41545555,
+ 0x54040551, 0x15445545, 0x51555514, 0x10000015, 0x00101100, 0x01100015,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x04450514, 0x45414110,
+ 0x55555145, 0x50544050, 0x15040155, 0x11054140, 0x50111514, 0x11451454,
+ 0x00400541, 0x00000000, 0x55555450, 0x10056551, 0x10054011, 0x55551014,
+ 0x69514555, 0x05151109, 0x00155555};
+
+ static const int compression_ratio = 27;
+
+ // Compute base index.
+ int cache_index = (k - float_info<double>::min_k) / compression_ratio;
+ int kb = cache_index * compression_ratio + float_info<double>::min_k;
+ int offset = k - kb;
+
+ // Get base cache.
+ uint128_wrapper base_cache = pow10_significands[cache_index];
+ if (offset == 0) return base_cache;
+
+ // Compute the required amount of bit-shift.
+ int alpha = floor_log2_pow10(kb + offset) - floor_log2_pow10(kb) - offset;
+ FMT_ASSERT(alpha > 0 && alpha < 64, "shifting error detected");
+
+ // Try to recover the real cache.
+ uint64_t pow5 = powers_of_5_64[offset];
+ uint128_wrapper recovered_cache = umul128(base_cache.high(), pow5);
+ uint128_wrapper middle_low =
+ umul128(base_cache.low() - (kb < 0 ? 1u : 0u), pow5);
+
+ recovered_cache += middle_low.high();
+
+ uint64_t high_to_middle = recovered_cache.high() << (64 - alpha);
+ uint64_t middle_to_low = recovered_cache.low() << (64 - alpha);
+
+ recovered_cache =
+ uint128_wrapper{(recovered_cache.low() >> alpha) | high_to_middle,
+ ((middle_low.low() >> alpha) | middle_to_low)};
+
+ if (kb < 0) recovered_cache += 1;
+
+ // Get error.
+ int error_idx = (k - float_info<double>::min_k) / 16;
+ uint32_t error = (pow10_recovery_errors[error_idx] >>
+ ((k - float_info<double>::min_k) % 16) * 2) &
+ 0x3;
+
+ // Add the error back.
+ FMT_ASSERT(recovered_cache.low() + error >= recovered_cache.low(), "");
+ return {recovered_cache.high(), recovered_cache.low() + error};
+#endif
+ }
+
+ static carrier_uint compute_mul(carrier_uint u,
+ const cache_entry_type& cache) FMT_NOEXCEPT {
+ return umul192_upper64(u, cache);
+ }
+
+ static uint32_t compute_delta(cache_entry_type const& cache,
+ int beta_minus_1) FMT_NOEXCEPT {
+ return static_cast<uint32_t>(cache.high() >> (64 - 1 - beta_minus_1));
+ }
+
+ static bool compute_mul_parity(carrier_uint two_f,
+ const cache_entry_type& cache,
+ int beta_minus_1) FMT_NOEXCEPT {
+ FMT_ASSERT(beta_minus_1 >= 1, "");
+ FMT_ASSERT(beta_minus_1 < 64, "");
+
+ return ((umul192_middle64(two_f, cache) >> (64 - beta_minus_1)) & 1) != 0;
+ }
+
+ static carrier_uint compute_left_endpoint_for_shorter_interval_case(
+ const cache_entry_type& cache, int beta_minus_1) FMT_NOEXCEPT {
+ return (cache.high() -
+ (cache.high() >> (float_info<double>::significand_bits + 2))) >>
+ (64 - float_info<double>::significand_bits - 1 - beta_minus_1);
+ }
+
+ static carrier_uint compute_right_endpoint_for_shorter_interval_case(
+ const cache_entry_type& cache, int beta_minus_1) FMT_NOEXCEPT {
+ return (cache.high() +
+ (cache.high() >> (float_info<double>::significand_bits + 1))) >>
+ (64 - float_info<double>::significand_bits - 1 - beta_minus_1);
+ }
+
+ static carrier_uint compute_round_up_for_shorter_interval_case(
+ const cache_entry_type& cache, int beta_minus_1) FMT_NOEXCEPT {
+ return ((cache.high() >>
+ (64 - float_info<double>::significand_bits - 2 - beta_minus_1)) +
+ 1) /
+ 2;
+ }
+};
+
+// Various integer checks
+template <class T>
+bool is_left_endpoint_integer_shorter_interval(int exponent) FMT_NOEXCEPT {
+ return exponent >=
+ float_info<
+ T>::case_shorter_interval_left_endpoint_lower_threshold &&
+ exponent <=
+ float_info<T>::case_shorter_interval_left_endpoint_upper_threshold;
+}
+template <class T>
+bool is_endpoint_integer(typename float_info<T>::carrier_uint two_f,
+ int exponent, int minus_k) FMT_NOEXCEPT {
+ if (exponent < float_info<T>::case_fc_pm_half_lower_threshold) return false;
+ // For k >= 0.
+ if (exponent <= float_info<T>::case_fc_pm_half_upper_threshold) return true;
+ // For k < 0.
+ if (exponent > float_info<T>::divisibility_check_by_5_threshold) return false;
+ return divisible_by_power_of_5(two_f, minus_k);
+}
+
+template <class T>
+bool is_center_integer(typename float_info<T>::carrier_uint two_f, int exponent,
+ int minus_k) FMT_NOEXCEPT {
+ // Exponent for 5 is negative.
+ if (exponent > float_info<T>::divisibility_check_by_5_threshold) return false;
+ if (exponent > float_info<T>::case_fc_upper_threshold)
+ return divisible_by_power_of_5(two_f, minus_k);
+ // Both exponents are nonnegative.
+ if (exponent >= float_info<T>::case_fc_lower_threshold) return true;
+ // Exponent for 2 is negative.
+ return divisible_by_power_of_2(two_f, minus_k - exponent + 1);
+}
+
+// Remove trailing zeros from n and return the number of zeros removed (float)
+FMT_INLINE int remove_trailing_zeros(uint32_t& n) FMT_NOEXCEPT {
+#ifdef FMT_BUILTIN_CTZ
+ int t = FMT_BUILTIN_CTZ(n);
+#else
+ int t = ctz(n);
+#endif
+ if (t > float_info<float>::max_trailing_zeros)
+ t = float_info<float>::max_trailing_zeros;
+
+ const uint32_t mod_inv1 = 0xcccccccd;
+ const uint32_t max_quotient1 = 0x33333333;
+ const uint32_t mod_inv2 = 0xc28f5c29;
+ const uint32_t max_quotient2 = 0x0a3d70a3;
+
+ int s = 0;
+ for (; s < t - 1; s += 2) {
+ if (n * mod_inv2 > max_quotient2) break;
+ n *= mod_inv2;
+ }
+ if (s < t && n * mod_inv1 <= max_quotient1) {
+ n *= mod_inv1;
+ ++s;
+ }
+ n >>= s;
+ return s;
+}
+
+// Removes trailing zeros and returns the number of zeros removed (double)
+FMT_INLINE int remove_trailing_zeros(uint64_t& n) FMT_NOEXCEPT {
+#ifdef FMT_BUILTIN_CTZLL
+ int t = FMT_BUILTIN_CTZLL(n);
+#else
+ int t = ctzll(n);
+#endif
+ if (t > float_info<double>::max_trailing_zeros)
+ t = float_info<double>::max_trailing_zeros;
+ // Divide by 10^8 and reduce to 32-bits
+ // Since ret_value.significand <= (2^64 - 1) / 1000 < 10^17,
+ // both of the quotient and the r should fit in 32-bits
+
+ const uint32_t mod_inv1 = 0xcccccccd;
+ const uint32_t max_quotient1 = 0x33333333;
+ const uint64_t mod_inv8 = 0xc767074b22e90e21;
+ const uint64_t max_quotient8 = 0x00002af31dc46118;
+
+ // If the number is divisible by 1'0000'0000, work with the quotient
+ if (t >= 8) {
+ auto quotient_candidate = n * mod_inv8;
+
+ if (quotient_candidate <= max_quotient8) {
+ auto quotient = static_cast<uint32_t>(quotient_candidate >> 8);
+
+ int s = 8;
+ for (; s < t; ++s) {
+ if (quotient * mod_inv1 > max_quotient1) break;
+ quotient *= mod_inv1;
+ }
+ quotient >>= (s - 8);
+ n = quotient;
+ return s;
+ }
+ }
+
+ // Otherwise, work with the remainder
+ auto quotient = static_cast<uint32_t>(n / 100000000);
+ auto remainder = static_cast<uint32_t>(n - 100000000 * quotient);
+
+ if (t == 0 || remainder * mod_inv1 > max_quotient1) {
+ return 0;
+ }
+ remainder *= mod_inv1;
+
+ if (t == 1 || remainder * mod_inv1 > max_quotient1) {
+ n = (remainder >> 1) + quotient * 10000000ull;
+ return 1;
+ }
+ remainder *= mod_inv1;
+
+ if (t == 2 || remainder * mod_inv1 > max_quotient1) {
+ n = (remainder >> 2) + quotient * 1000000ull;
+ return 2;
+ }
+ remainder *= mod_inv1;
+
+ if (t == 3 || remainder * mod_inv1 > max_quotient1) {
+ n = (remainder >> 3) + quotient * 100000ull;
+ return 3;
+ }
+ remainder *= mod_inv1;
+
+ if (t == 4 || remainder * mod_inv1 > max_quotient1) {
+ n = (remainder >> 4) + quotient * 10000ull;
+ return 4;
+ }
+ remainder *= mod_inv1;
+
+ if (t == 5 || remainder * mod_inv1 > max_quotient1) {
+ n = (remainder >> 5) + quotient * 1000ull;
+ return 5;
+ }
+ remainder *= mod_inv1;
+
+ if (t == 6 || remainder * mod_inv1 > max_quotient1) {
+ n = (remainder >> 6) + quotient * 100ull;
+ return 6;
+ }
+ remainder *= mod_inv1;
+
+ n = (remainder >> 7) + quotient * 10ull;
+ return 7;
+}
+
+// The main algorithm for shorter interval case
+template <class T>
+FMT_INLINE decimal_fp<T> shorter_interval_case(int exponent) FMT_NOEXCEPT {
+ decimal_fp<T> ret_value;
+ // Compute k and beta
+ const int minus_k = floor_log10_pow2_minus_log10_4_over_3(exponent);
+ const int beta_minus_1 = exponent + floor_log2_pow10(-minus_k);
+
+ // Compute xi and zi
+ using cache_entry_type = typename cache_accessor<T>::cache_entry_type;
+ const cache_entry_type cache = cache_accessor<T>::get_cached_power(-minus_k);
+
+ auto xi = cache_accessor<T>::compute_left_endpoint_for_shorter_interval_case(
+ cache, beta_minus_1);
+ auto zi = cache_accessor<T>::compute_right_endpoint_for_shorter_interval_case(
+ cache, beta_minus_1);
+
+ // If the left endpoint is not an integer, increase it
+ if (!is_left_endpoint_integer_shorter_interval<T>(exponent)) ++xi;
+
+ // Try bigger divisor
+ ret_value.significand = zi / 10;
+
+ // If succeed, remove trailing zeros if necessary and return
+ if (ret_value.significand * 10 >= xi) {
+ ret_value.exponent = minus_k + 1;
+ ret_value.exponent += remove_trailing_zeros(ret_value.significand);
+ return ret_value;
+ }
+
+ // Otherwise, compute the round-up of y
+ ret_value.significand =
+ cache_accessor<T>::compute_round_up_for_shorter_interval_case(
+ cache, beta_minus_1);
+ ret_value.exponent = minus_k;
+
+ // When tie occurs, choose one of them according to the rule
+ if (exponent >= float_info<T>::shorter_interval_tie_lower_threshold &&
+ exponent <= float_info<T>::shorter_interval_tie_upper_threshold) {
+ ret_value.significand = ret_value.significand % 2 == 0
+ ? ret_value.significand
+ : ret_value.significand - 1;
+ } else if (ret_value.significand < xi) {
+ ++ret_value.significand;
+ }
+ return ret_value;
+}
+
+template <typename T> decimal_fp<T> to_decimal(T x) FMT_NOEXCEPT {
+ // Step 1: integer promotion & Schubfach multiplier calculation.
+
+ using carrier_uint = typename float_info<T>::carrier_uint;
+ using cache_entry_type = typename cache_accessor<T>::cache_entry_type;
+ auto br = bit_cast<carrier_uint>(x);
+
+ // Extract significand bits and exponent bits.
+ const carrier_uint significand_mask =
+ (static_cast<carrier_uint>(1) << float_info<T>::significand_bits) - 1;
+ carrier_uint significand = (br & significand_mask);
+ int exponent = static_cast<int>((br & exponent_mask<T>()) >>
+ float_info<T>::significand_bits);
+
+ if (exponent != 0) { // Check if normal.
+ exponent += float_info<T>::exponent_bias - float_info<T>::significand_bits;
+
+ // Shorter interval case; proceed like Schubfach.
+ if (significand == 0) return shorter_interval_case<T>(exponent);
+
+ significand |=
+ (static_cast<carrier_uint>(1) << float_info<T>::significand_bits);
+ } else {
+ // Subnormal case; the interval is always regular.
+ if (significand == 0) return {0, 0};
+ exponent = float_info<T>::min_exponent - float_info<T>::significand_bits;
+ }
+
+ const bool include_left_endpoint = (significand % 2 == 0);
+ const bool include_right_endpoint = include_left_endpoint;
+
+ // Compute k and beta.
+ const int minus_k = floor_log10_pow2(exponent) - float_info<T>::kappa;
+ const cache_entry_type cache = cache_accessor<T>::get_cached_power(-minus_k);
+ const int beta_minus_1 = exponent + floor_log2_pow10(-minus_k);
+
+ // Compute zi and deltai
+ // 10^kappa <= deltai < 10^(kappa + 1)
+ const uint32_t deltai = cache_accessor<T>::compute_delta(cache, beta_minus_1);
+ const carrier_uint two_fc = significand << 1;
+ const carrier_uint two_fr = two_fc | 1;
+ const carrier_uint zi =
+ cache_accessor<T>::compute_mul(two_fr << beta_minus_1, cache);
+
+ // Step 2: Try larger divisor; remove trailing zeros if necessary
+
+ // Using an upper bound on zi, we might be able to optimize the division
+ // better than the compiler; we are computing zi / big_divisor here
+ decimal_fp<T> ret_value;
+ ret_value.significand = divide_by_10_to_kappa_plus_1(zi);
+ uint32_t r = static_cast<uint32_t>(zi - float_info<T>::big_divisor *
+ ret_value.significand);
+
+ if (r > deltai) {
+ goto small_divisor_case_label;
+ } else if (r < deltai) {
+ // Exclude the right endpoint if necessary
+ if (r == 0 && !include_right_endpoint &&
+ is_endpoint_integer<T>(two_fr, exponent, minus_k)) {
+ --ret_value.significand;
+ r = float_info<T>::big_divisor;
+ goto small_divisor_case_label;
+ }
+ } else {
+ // r == deltai; compare fractional parts
+ // Check conditions in the order different from the paper
+ // to take advantage of short-circuiting
+ const carrier_uint two_fl = two_fc - 1;
+ if ((!include_left_endpoint ||
+ !is_endpoint_integer<T>(two_fl, exponent, minus_k)) &&
+ !cache_accessor<T>::compute_mul_parity(two_fl, cache, beta_minus_1)) {
+ goto small_divisor_case_label;
+ }
+ }
+ ret_value.exponent = minus_k + float_info<T>::kappa + 1;
+
+ // We may need to remove trailing zeros
+ ret_value.exponent += remove_trailing_zeros(ret_value.significand);
+ return ret_value;
+
+ // Step 3: Find the significand with the smaller divisor
+
+small_divisor_case_label:
+ ret_value.significand *= 10;
+ ret_value.exponent = minus_k + float_info<T>::kappa;
+
+ const uint32_t mask = (1u << float_info<T>::kappa) - 1;
+ auto dist = r - (deltai / 2) + (float_info<T>::small_divisor / 2);
+
+ // Is dist divisible by 2^kappa?
+ if ((dist & mask) == 0) {
+ const bool approx_y_parity =
+ ((dist ^ (float_info<T>::small_divisor / 2)) & 1) != 0;
+ dist >>= float_info<T>::kappa;
+
+ // Is dist divisible by 5^kappa?
+ if (check_divisibility_and_divide_by_pow5<float_info<T>::kappa>(dist)) {
+ ret_value.significand += dist;
+
+ // Check z^(f) >= epsilon^(f)
+ // We have either yi == zi - epsiloni or yi == (zi - epsiloni) - 1,
+ // where yi == zi - epsiloni if and only if z^(f) >= epsilon^(f)
+ // Since there are only 2 possibilities, we only need to care about the
+ // parity. Also, zi and r should have the same parity since the divisor
+ // is an even number
+ if (cache_accessor<T>::compute_mul_parity(two_fc, cache, beta_minus_1) !=
+ approx_y_parity) {
+ --ret_value.significand;
+ } else {
+ // If z^(f) >= epsilon^(f), we might have a tie
+ // when z^(f) == epsilon^(f), or equivalently, when y is an integer
+ if (is_center_integer<T>(two_fc, exponent, minus_k)) {
+ ret_value.significand = ret_value.significand % 2 == 0
+ ? ret_value.significand
+ : ret_value.significand - 1;
+ }
+ }
+ }
+ // Is dist not divisible by 5^kappa?
+ else {
+ ret_value.significand += dist;
+ }
+ }
+ // Is dist not divisible by 2^kappa?
+ else {
+ // Since we know dist is small, we might be able to optimize the division
+ // better than the compiler; we are computing dist / small_divisor here
+ ret_value.significand +=
+ small_division_by_pow10<float_info<T>::kappa>(dist);
+ }
+ return ret_value;
+}
+} // namespace dragonbox
+
+// Formats a floating-point number using a variation of the Fixed-Precision
+// Positive Floating-Point Printout ((FPP)^2) algorithm by Steele & White:
+// https://fmt.dev/papers/p372-steele.pdf.
+FMT_CONSTEXPR20 inline void format_dragon(fp value, bool is_predecessor_closer,
+ int num_digits, buffer<char>& buf,
+ int& exp10) {
+ bigint numerator; // 2 * R in (FPP)^2.
+ bigint denominator; // 2 * S in (FPP)^2.
+ // lower and upper are differences between value and corresponding boundaries.
+ bigint lower; // (M^- in (FPP)^2).
+ bigint upper_store; // upper's value if different from lower.
+ bigint* upper = nullptr; // (M^+ in (FPP)^2).
+ // Shift numerator and denominator by an extra bit or two (if lower boundary
+ // is closer) to make lower and upper integers. This eliminates multiplication
+ // by 2 during later computations.
+ int shift = is_predecessor_closer ? 2 : 1;
+ uint64_t significand = value.f << shift;
+ if (value.e >= 0) {
+ numerator.assign(significand);
+ numerator <<= value.e;
+ lower.assign(1);
+ lower <<= value.e;
+ if (shift != 1) {
+ upper_store.assign(1);
+ upper_store <<= value.e + 1;
+ upper = &upper_store;
+ }
+ denominator.assign_pow10(exp10);
+ denominator <<= shift;
+ } else if (exp10 < 0) {
+ numerator.assign_pow10(-exp10);
+ lower.assign(numerator);
+ if (shift != 1) {
+ upper_store.assign(numerator);
+ upper_store <<= 1;
+ upper = &upper_store;
+ }
+ numerator *= significand;
+ denominator.assign(1);
+ denominator <<= shift - value.e;
+ } else {
+ numerator.assign(significand);
+ denominator.assign_pow10(exp10);
+ denominator <<= shift - value.e;
+ lower.assign(1);
+ if (shift != 1) {
+ upper_store.assign(1ULL << 1);
+ upper = &upper_store;
+ }
+ }
+ // Invariant: value == (numerator / denominator) * pow(10, exp10).
+ if (num_digits < 0) {
+ // Generate the shortest representation.
+ if (!upper) upper = &lower;
+ bool even = (value.f & 1) == 0;
+ num_digits = 0;
+ char* data = buf.data();
+ for (;;) {
+ int digit = numerator.divmod_assign(denominator);
+ bool low = compare(numerator, lower) - even < 0; // numerator <[=] lower.
+ // numerator + upper >[=] pow10:
+ bool high = add_compare(numerator, *upper, denominator) + even > 0;
+ data[num_digits++] = static_cast<char>('0' + digit);
+ if (low || high) {
+ if (!low) {
+ ++data[num_digits - 1];
+ } else if (high) {
+ int result = add_compare(numerator, numerator, denominator);
+ // Round half to even.
+ if (result > 0 || (result == 0 && (digit % 2) != 0))
+ ++data[num_digits - 1];
+ }
+ buf.try_resize(to_unsigned(num_digits));
+ exp10 -= num_digits - 1;
+ return;
+ }
+ numerator *= 10;
+ lower *= 10;
+ if (upper != &lower) *upper *= 10;
+ }
+ }
+ // Generate the given number of digits.
+ exp10 -= num_digits - 1;
+ if (num_digits == 0) {
+ denominator *= 10;
+ auto digit = add_compare(numerator, numerator, denominator) > 0 ? '1' : '0';
+ buf.push_back(digit);
+ return;
+ }
+ buf.try_resize(to_unsigned(num_digits));
+ for (int i = 0; i < num_digits - 1; ++i) {
+ int digit = numerator.divmod_assign(denominator);
+ buf[i] = static_cast<char>('0' + digit);
+ numerator *= 10;
+ }
+ int digit = numerator.divmod_assign(denominator);
+ auto result = add_compare(numerator, numerator, denominator);
+ if (result > 0 || (result == 0 && (digit % 2) != 0)) {
+ if (digit == 9) {
+ const auto overflow = '0' + 10;
+ buf[num_digits - 1] = overflow;
+ // Propagate the carry.
+ for (int i = num_digits - 1; i > 0 && buf[i] == overflow; --i) {
+ buf[i] = '0';
+ ++buf[i - 1];
+ }
+ if (buf[0] == overflow) {
+ buf[0] = '1';
+ ++exp10;
+ }
+ return;
+ }
+ ++digit;
+ }
+ buf[num_digits - 1] = static_cast<char>('0' + digit);
+}
+
+template <typename Float>
+FMT_HEADER_ONLY_CONSTEXPR20 int format_float(Float value, int precision,
+ float_specs specs,
+ buffer<char>& buf) {
+ // float is passed as double to reduce the number of instantiations.
+ static_assert(!std::is_same<Float, float>::value, "");
+ FMT_ASSERT(value >= 0, "value is negative");
+
+ const bool fixed = specs.format == float_format::fixed;
+ if (value <= 0) { // <= instead of == to silence a warning.
+ if (precision <= 0 || !fixed) {
+ buf.push_back('0');
+ return 0;
+ }
+ buf.try_resize(to_unsigned(precision));
+ fill_n(buf.data(), precision, '0');
+ return -precision;
+ }
+
+ if (specs.fallback) return snprintf_float(value, precision, specs, buf);
+
+ if (!is_constant_evaluated() && precision < 0) {
+ // Use Dragonbox for the shortest format.
+ if (specs.binary32) {
+ auto dec = dragonbox::to_decimal(static_cast<float>(value));
+ write<char>(buffer_appender<char>(buf), dec.significand);
+ return dec.exponent;
+ }
+ auto dec = dragonbox::to_decimal(static_cast<double>(value));
+ write<char>(buffer_appender<char>(buf), dec.significand);
+ return dec.exponent;
+ }
+
+ int exp = 0;
+ bool use_dragon = true;
+ if (is_fast_float<Float>()) {
+ // Use Grisu + Dragon4 for the given precision:
+ // https://www.cs.tufts.edu/~nr/cs257/archive/florian-loitsch/printf.pdf.
+ const int min_exp = -60; // alpha in Grisu.
+ int cached_exp10 = 0; // K in Grisu.
+ fp normalized = normalize(fp(value));
+ const auto cached_pow = get_cached_power(
+ min_exp - (normalized.e + fp::num_significand_bits), cached_exp10);
+ normalized = normalized * cached_pow;
+ gen_digits_handler handler{buf.data(), 0, precision, -cached_exp10, fixed};
+ if (grisu_gen_digits(normalized, 1, exp, handler) != digits::error &&
+ !is_constant_evaluated()) {
+ exp += handler.exp10;
+ buf.try_resize(to_unsigned(handler.size));
+ use_dragon = false;
+ } else {
+ exp += handler.size - cached_exp10 - 1;
+ precision = handler.precision;
+ }
+ }
+ if (use_dragon) {
+ auto f = fp();
+ bool is_predecessor_closer =
+ specs.binary32 ? f.assign(static_cast<float>(value)) : f.assign(value);
+ // Limit precision to the maximum possible number of significant digits in
+ // an IEEE754 double because we don't need to generate zeros.
+ const int max_double_digits = 767;
+ if (precision > max_double_digits) precision = max_double_digits;
+ format_dragon(f, is_predecessor_closer, precision, buf, exp);
+ }
+ if (!fixed && !specs.showpoint) {
+ // Remove trailing zeros.
+ auto num_digits = buf.size();
+ while (num_digits > 0 && buf[num_digits - 1] == '0') {
+ --num_digits;
+ ++exp;
+ }
+ buf.try_resize(num_digits);
+ }
+ return exp;
+}
+
+template <typename T>
+int snprintf_float(T value, int precision, float_specs specs,
+ buffer<char>& buf) {
+ // Buffer capacity must be non-zero, otherwise MSVC's vsnprintf_s will fail.
+ FMT_ASSERT(buf.capacity() > buf.size(), "empty buffer");
+ static_assert(!std::is_same<T, float>::value, "");
+
+ // Subtract 1 to account for the difference in precision since we use %e for
+ // both general and exponent format.
+ if (specs.format == float_format::general ||
+ specs.format == float_format::exp)
+ precision = (precision >= 0 ? precision : 6) - 1;
+
+ // Build the format string.
+ enum { max_format_size = 7 }; // The longest format is "%#.*Le".
+ char format[max_format_size];
+ char* format_ptr = format;
+ *format_ptr++ = '%';
+ if (specs.showpoint && specs.format == float_format::hex) *format_ptr++ = '#';
+ if (precision >= 0) {
+ *format_ptr++ = '.';
+ *format_ptr++ = '*';
+ }
+ if (std::is_same<T, long double>()) *format_ptr++ = 'L';
+ *format_ptr++ = specs.format != float_format::hex
+ ? (specs.format == float_format::fixed ? 'f' : 'e')
+ : (specs.upper ? 'A' : 'a');
+ *format_ptr = '\0';
+
+ // Format using snprintf.
+ auto offset = buf.size();
+ for (;;) {
+ auto begin = buf.data() + offset;
+ auto capacity = buf.capacity() - offset;
+#ifdef FMT_FUZZ
+ if (precision > 100000)
+ throw std::runtime_error(
+ "fuzz mode - avoid large allocation inside snprintf");
+#endif
+ // Suppress the warning about a nonliteral format string.
+ // Cannot use auto because of a bug in MinGW (#1532).
+ int (*snprintf_ptr)(char*, size_t, const char*, ...) = FMT_SNPRINTF;
+ int result = precision >= 0
+ ? snprintf_ptr(begin, capacity, format, precision, value)
+ : snprintf_ptr(begin, capacity, format, value);
+ if (result < 0) {
+ // The buffer will grow exponentially.
+ buf.try_reserve(buf.capacity() + 1);
+ continue;
+ }
+ auto size = to_unsigned(result);
+ // Size equal to capacity means that the last character was truncated.
+ if (size >= capacity) {
+ buf.try_reserve(size + offset + 1); // Add 1 for the terminating '\0'.
+ continue;
+ }
+ auto is_digit = [](char c) { return c >= '0' && c <= '9'; };
+ if (specs.format == float_format::fixed) {
+ if (precision == 0) {
+ buf.try_resize(size);
+ return 0;
+ }
+ // Find and remove the decimal point.
+ auto end = begin + size, p = end;
+ do {
+ --p;
+ } while (is_digit(*p));
+ int fraction_size = static_cast<int>(end - p - 1);
+ std::memmove(p, p + 1, to_unsigned(fraction_size));
+ buf.try_resize(size - 1);
+ return -fraction_size;
+ }
+ if (specs.format == float_format::hex) {
+ buf.try_resize(size + offset);
+ return 0;
+ }
+ // Find and parse the exponent.
+ auto end = begin + size, exp_pos = end;
+ do {
+ --exp_pos;
+ } while (*exp_pos != 'e');
+ char sign = exp_pos[1];
+ FMT_ASSERT(sign == '+' || sign == '-', "");
+ int exp = 0;
+ auto p = exp_pos + 2; // Skip 'e' and sign.
+ do {
+ FMT_ASSERT(is_digit(*p), "");
+ exp = exp * 10 + (*p++ - '0');
+ } while (p != end);
+ if (sign == '-') exp = -exp;
+ int fraction_size = 0;
+ if (exp_pos != begin + 1) {
+ // Remove trailing zeros.
+ auto fraction_end = exp_pos - 1;
+ while (*fraction_end == '0') --fraction_end;
+ // Move the fractional part left to get rid of the decimal point.
+ fraction_size = static_cast<int>(fraction_end - begin - 1);
+ std::memmove(begin + 1, begin + 2, to_unsigned(fraction_size));
+ }
+ buf.try_resize(to_unsigned(fraction_size) + offset + 1);
+ return exp - fraction_size;
+ }
+}
+} // namespace detail
+
+template <> struct formatter<detail::bigint> {
+ FMT_CONSTEXPR format_parse_context::iterator parse(
+ format_parse_context& ctx) {
+ return ctx.begin();
+ }
+
+ format_context::iterator format(const detail::bigint& n,
+ format_context& ctx) {
+ auto out = ctx.out();
+ bool first = true;
+ for (auto i = n.bigits_.size(); i > 0; --i) {
+ auto value = n.bigits_[i - 1u];
+ if (first) {
+ out = format_to(out, FMT_STRING("{:x}"), value);
+ first = false;
+ continue;
+ }
+ out = format_to(out, FMT_STRING("{:08x}"), value);
+ }
+ if (n.exp_ > 0)
+ out = format_to(out, FMT_STRING("p{}"),
+ n.exp_ * detail::bigint::bigit_bits);
+ return out;
+ }
+};
+
+FMT_FUNC detail::utf8_to_utf16::utf8_to_utf16(string_view s) {
+ for_each_codepoint(s, [this](uint32_t cp, string_view) {
+ if (cp == invalid_code_point) FMT_THROW(std::runtime_error("invalid utf8"));
+ if (cp <= 0xFFFF) {
+ buffer_.push_back(static_cast<wchar_t>(cp));
+ } else {
+ cp -= 0x10000;
+ buffer_.push_back(static_cast<wchar_t>(0xD800 + (cp >> 10)));
+ buffer_.push_back(static_cast<wchar_t>(0xDC00 + (cp & 0x3FF)));
+ }
+ return true;
+ });
+ buffer_.push_back(0);
+}
+
+FMT_FUNC void format_system_error(detail::buffer<char>& out, int error_code,
+ const char* message) FMT_NOEXCEPT {
+ FMT_TRY {
+ auto ec = std::error_code(error_code, std::generic_category());
+ write(std::back_inserter(out), std::system_error(ec, message).what());
+ return;
+ }
+ FMT_CATCH(...) {}
+ format_error_code(out, error_code, message);
+}
+
+FMT_FUNC void report_system_error(int error_code,
+ const char* message) FMT_NOEXCEPT {
+ report_error(format_system_error, error_code, message);
+}
+
+// DEPRECATED!
+// This function is defined here and not inline for ABI compatiblity.
+FMT_FUNC void detail::error_handler::on_error(const char* message) {
+ throw_format_error(message);
+}
+
+FMT_FUNC std::string vformat(string_view fmt, format_args args) {
+ // Don't optimize the "{}" case to keep the binary size small and because it
+ // can be better optimized in fmt::format anyway.
+ auto buffer = memory_buffer();
+ detail::vformat_to(buffer, fmt, args);
+ return to_string(buffer);
+}
+
+#ifdef _WIN32
+namespace detail {
+using dword = conditional_t<sizeof(long) == 4, unsigned long, unsigned>;
+extern "C" __declspec(dllimport) int __stdcall WriteConsoleW( //
+ void*, const void*, dword, dword*, void*);
+} // namespace detail
+#endif
+
+namespace detail {
+FMT_FUNC void print(std::FILE* f, string_view text) {
+#ifdef _WIN32
+ auto fd = _fileno(f);
+ if (_isatty(fd)) {
+ detail::utf8_to_utf16 u16(string_view(text.data(), text.size()));
+ auto written = detail::dword();
+ if (detail::WriteConsoleW(reinterpret_cast<void*>(_get_osfhandle(fd)),
+ u16.c_str(), static_cast<uint32_t>(u16.size()),
+ &written, nullptr)) {
+ return;
+ }
+ // Fallback to fwrite on failure. It can happen if the output has been
+ // redirected to NUL.
+ }
+#endif
+ detail::fwrite_fully(text.data(), 1, text.size(), f);
+}
+} // namespace detail
+
+FMT_FUNC void vprint(std::FILE* f, string_view format_str, format_args args) {
+ memory_buffer buffer;
+ detail::vformat_to(buffer, format_str, args);
+ detail::print(f, {buffer.data(), buffer.size()});
+}
+
+#ifdef _WIN32
+// Print assuming legacy (non-Unicode) encoding.
+FMT_FUNC void detail::vprint_mojibake(std::FILE* f, string_view format_str,
+ format_args args) {
+ memory_buffer buffer;
+ detail::vformat_to(buffer, format_str,
+ basic_format_args<buffer_context<char>>(args));
+ fwrite_fully(buffer.data(), 1, buffer.size(), f);
+}
+#endif
+
+FMT_FUNC void vprint(string_view format_str, format_args args) {
+ vprint(stdout, format_str, args);
+}
+
+FMT_END_NAMESPACE
+
+#endif // FMT_FORMAT_INL_H_
diff --git a/extern/fmtlib/include/fmt/format.h b/extern/fmtlib/include/fmt/format.h
new file mode 100644
index 00000000000..ee69651ca54
--- /dev/null
+++ b/extern/fmtlib/include/fmt/format.h
@@ -0,0 +1,3104 @@
+/*
+ Formatting library for C++
+
+ Copyright (c) 2012 - present, Victor Zverovich
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+ --- Optional exception to the license ---
+
+ As an exception, if, as a result of your compiling your source code, portions
+ of this Software are embedded into a machine-executable object form of such
+ source code, you may redistribute such embedded portions in such object form
+ without including the above copyright and permission notices.
+ */
+
+#ifndef FMT_FORMAT_H_
+#define FMT_FORMAT_H_
+
+#include <cmath> // std::signbit
+#include <cstdint> // uint32_t
+#include <limits> // std::numeric_limits
+#include <memory> // std::uninitialized_copy
+#include <stdexcept> // std::runtime_error
+#include <system_error> // std::system_error
+#include <utility> // std::swap
+
+#ifdef __cpp_lib_bit_cast
+# include <bit> // std::bitcast
+#endif
+
+#include "core.h"
+
+#if FMT_GCC_VERSION
+# define FMT_GCC_VISIBILITY_HIDDEN __attribute__((visibility("hidden")))
+#else
+# define FMT_GCC_VISIBILITY_HIDDEN
+#endif
+
+#ifdef __NVCC__
+# define FMT_CUDA_VERSION (__CUDACC_VER_MAJOR__ * 100 + __CUDACC_VER_MINOR__)
+#else
+# define FMT_CUDA_VERSION 0
+#endif
+
+#ifdef __has_builtin
+# define FMT_HAS_BUILTIN(x) __has_builtin(x)
+#else
+# define FMT_HAS_BUILTIN(x) 0
+#endif
+
+#if FMT_GCC_VERSION || FMT_CLANG_VERSION
+# define FMT_NOINLINE __attribute__((noinline))
+#else
+# define FMT_NOINLINE
+#endif
+
+#if FMT_MSC_VER
+# define FMT_MSC_DEFAULT = default
+#else
+# define FMT_MSC_DEFAULT
+#endif
+
+#ifndef FMT_THROW
+# if FMT_EXCEPTIONS
+# if FMT_MSC_VER || FMT_NVCC
+FMT_BEGIN_NAMESPACE
+namespace detail {
+template <typename Exception> inline void do_throw(const Exception& x) {
+ // Silence unreachable code warnings in MSVC and NVCC because these
+ // are nearly impossible to fix in a generic code.
+ volatile bool b = true;
+ if (b) throw x;
+}
+} // namespace detail
+FMT_END_NAMESPACE
+# define FMT_THROW(x) detail::do_throw(x)
+# else
+# define FMT_THROW(x) throw x
+# endif
+# else
+# define FMT_THROW(x) \
+ do { \
+ FMT_ASSERT(false, (x).what()); \
+ } while (false)
+# endif
+#endif
+
+#if FMT_EXCEPTIONS
+# define FMT_TRY try
+# define FMT_CATCH(x) catch (x)
+#else
+# define FMT_TRY if (true)
+# define FMT_CATCH(x) if (false)
+#endif
+
+#ifndef FMT_MAYBE_UNUSED
+# if FMT_HAS_CPP17_ATTRIBUTE(maybe_unused)
+# define FMT_MAYBE_UNUSED [[maybe_unused]]
+# else
+# define FMT_MAYBE_UNUSED
+# endif
+#endif
+
+// Workaround broken [[deprecated]] in the Intel, PGI and NVCC compilers.
+#if FMT_ICC_VERSION || defined(__PGI) || FMT_NVCC
+# define FMT_DEPRECATED_ALIAS
+#else
+# define FMT_DEPRECATED_ALIAS FMT_DEPRECATED
+#endif
+
+#ifndef FMT_USE_USER_DEFINED_LITERALS
+// EDG based compilers (Intel, NVIDIA, Elbrus, etc), GCC and MSVC support UDLs.
+# if (FMT_HAS_FEATURE(cxx_user_literals) || FMT_GCC_VERSION >= 407 || \
+ FMT_MSC_VER >= 1900) && \
+ (!defined(__EDG_VERSION__) || __EDG_VERSION__ >= /* UDL feature */ 480)
+# define FMT_USE_USER_DEFINED_LITERALS 1
+# else
+# define FMT_USE_USER_DEFINED_LITERALS 0
+# endif
+#endif
+
+// Defining FMT_REDUCE_INT_INSTANTIATIONS to 1, will reduce the number of
+// integer formatter template instantiations to just one by only using the
+// largest integer type. This results in a reduction in binary size but will
+// cause a decrease in integer formatting performance.
+#if !defined(FMT_REDUCE_INT_INSTANTIATIONS)
+# define FMT_REDUCE_INT_INSTANTIATIONS 0
+#endif
+
+// __builtin_clz is broken in clang with Microsoft CodeGen:
+// https://github.com/fmtlib/fmt/issues/519.
+#if !FMT_MSC_VER
+# if FMT_HAS_BUILTIN(__builtin_clz) || FMT_GCC_VERSION || FMT_ICC_VERSION
+# define FMT_BUILTIN_CLZ(n) __builtin_clz(n)
+# endif
+# if FMT_HAS_BUILTIN(__builtin_clzll) || FMT_GCC_VERSION || FMT_ICC_VERSION
+# define FMT_BUILTIN_CLZLL(n) __builtin_clzll(n)
+# endif
+#endif
+
+// __builtin_ctz is broken in Intel Compiler Classic on Windows:
+// https://github.com/fmtlib/fmt/issues/2510.
+#ifndef __ICL
+# if FMT_HAS_BUILTIN(__builtin_ctz) || FMT_GCC_VERSION || FMT_ICC_VERSION
+# define FMT_BUILTIN_CTZ(n) __builtin_ctz(n)
+# endif
+# if FMT_HAS_BUILTIN(__builtin_ctzll) || FMT_GCC_VERSION || FMT_ICC_VERSION
+# define FMT_BUILTIN_CTZLL(n) __builtin_ctzll(n)
+# endif
+#endif
+
+#if FMT_MSC_VER
+# include <intrin.h> // _BitScanReverse[64], _BitScanForward[64], _umul128
+#endif
+
+// Some compilers masquerade as both MSVC and GCC-likes or otherwise support
+// __builtin_clz and __builtin_clzll, so only define FMT_BUILTIN_CLZ using the
+// MSVC intrinsics if the clz and clzll builtins are not available.
+#if FMT_MSC_VER && !defined(FMT_BUILTIN_CLZLL) && !defined(FMT_BUILTIN_CTZLL)
+FMT_BEGIN_NAMESPACE
+namespace detail {
+// Avoid Clang with Microsoft CodeGen's -Wunknown-pragmas warning.
+# if !defined(__clang__)
+# pragma intrinsic(_BitScanForward)
+# pragma intrinsic(_BitScanReverse)
+# if defined(_WIN64)
+# pragma intrinsic(_BitScanForward64)
+# pragma intrinsic(_BitScanReverse64)
+# endif
+# endif
+
+inline auto clz(uint32_t x) -> int {
+ unsigned long r = 0;
+ _BitScanReverse(&r, x);
+ FMT_ASSERT(x != 0, "");
+ // Static analysis complains about using uninitialized data
+ // "r", but the only way that can happen is if "x" is 0,
+ // which the callers guarantee to not happen.
+ FMT_MSC_WARNING(suppress : 6102)
+ return 31 ^ static_cast<int>(r);
+}
+# define FMT_BUILTIN_CLZ(n) detail::clz(n)
+
+inline auto clzll(uint64_t x) -> int {
+ unsigned long r = 0;
+# ifdef _WIN64
+ _BitScanReverse64(&r, x);
+# else
+ // Scan the high 32 bits.
+ if (_BitScanReverse(&r, static_cast<uint32_t>(x >> 32))) return 63 ^ (r + 32);
+ // Scan the low 32 bits.
+ _BitScanReverse(&r, static_cast<uint32_t>(x));
+# endif
+ FMT_ASSERT(x != 0, "");
+ FMT_MSC_WARNING(suppress : 6102) // Suppress a bogus static analysis warning.
+ return 63 ^ static_cast<int>(r);
+}
+# define FMT_BUILTIN_CLZLL(n) detail::clzll(n)
+
+inline auto ctz(uint32_t x) -> int {
+ unsigned long r = 0;
+ _BitScanForward(&r, x);
+ FMT_ASSERT(x != 0, "");
+ FMT_MSC_WARNING(suppress : 6102) // Suppress a bogus static analysis warning.
+ return static_cast<int>(r);
+}
+# define FMT_BUILTIN_CTZ(n) detail::ctz(n)
+
+inline auto ctzll(uint64_t x) -> int {
+ unsigned long r = 0;
+ FMT_ASSERT(x != 0, "");
+ FMT_MSC_WARNING(suppress : 6102) // Suppress a bogus static analysis warning.
+# ifdef _WIN64
+ _BitScanForward64(&r, x);
+# else
+ // Scan the low 32 bits.
+ if (_BitScanForward(&r, static_cast<uint32_t>(x))) return static_cast<int>(r);
+ // Scan the high 32 bits.
+ _BitScanForward(&r, static_cast<uint32_t>(x >> 32));
+ r += 32;
+# endif
+ return static_cast<int>(r);
+}
+# define FMT_BUILTIN_CTZLL(n) detail::ctzll(n)
+} // namespace detail
+FMT_END_NAMESPACE
+#endif
+
+#ifdef FMT_HEADER_ONLY
+# define FMT_HEADER_ONLY_CONSTEXPR20 FMT_CONSTEXPR20
+#else
+# define FMT_HEADER_ONLY_CONSTEXPR20
+#endif
+
+FMT_BEGIN_NAMESPACE
+namespace detail {
+
+template <typename Streambuf> class formatbuf : public Streambuf {
+ private:
+ using char_type = typename Streambuf::char_type;
+ using streamsize = decltype(std::declval<Streambuf>().sputn(nullptr, 0));
+ using int_type = typename Streambuf::int_type;
+ using traits_type = typename Streambuf::traits_type;
+
+ buffer<char_type>& buffer_;
+
+ public:
+ explicit formatbuf(buffer<char_type>& buf) : buffer_(buf) {}
+
+ protected:
+ // The put area is always empty. This makes the implementation simpler and has
+ // the advantage that the streambuf and the buffer are always in sync and
+ // sputc never writes into uninitialized memory. A disadvantage is that each
+ // call to sputc always results in a (virtual) call to overflow. There is no
+ // disadvantage here for sputn since this always results in a call to xsputn.
+
+ auto overflow(int_type ch) -> int_type override {
+ if (!traits_type::eq_int_type(ch, traits_type::eof()))
+ buffer_.push_back(static_cast<char_type>(ch));
+ return ch;
+ }
+
+ auto xsputn(const char_type* s, streamsize count) -> streamsize override {
+ buffer_.append(s, s + count);
+ return count;
+ }
+};
+
+// Implementation of std::bit_cast for pre-C++20.
+template <typename To, typename From>
+FMT_CONSTEXPR20 auto bit_cast(const From& from) -> To {
+ static_assert(sizeof(To) == sizeof(From), "size mismatch");
+#ifdef __cpp_lib_bit_cast
+ if (is_constant_evaluated()) return std::bit_cast<To>(from);
+#endif
+ auto to = To();
+ std::memcpy(&to, &from, sizeof(to));
+ return to;
+}
+
+inline auto is_big_endian() -> bool {
+#ifdef _WIN32
+ return false;
+#elif defined(__BIG_ENDIAN__)
+ return true;
+#elif defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__)
+ return __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__;
+#else
+ struct bytes {
+ char data[sizeof(int)];
+ };
+ return bit_cast<bytes>(1).data[0] == 0;
+#endif
+}
+
+// A fallback implementation of uintptr_t for systems that lack it.
+struct fallback_uintptr {
+ unsigned char value[sizeof(void*)];
+
+ fallback_uintptr() = default;
+ explicit fallback_uintptr(const void* p) {
+ *this = bit_cast<fallback_uintptr>(p);
+ if (const_check(is_big_endian())) {
+ for (size_t i = 0, j = sizeof(void*) - 1; i < j; ++i, --j)
+ std::swap(value[i], value[j]);
+ }
+ }
+};
+#ifdef UINTPTR_MAX
+using uintptr_t = ::uintptr_t;
+inline auto to_uintptr(const void* p) -> uintptr_t {
+ return bit_cast<uintptr_t>(p);
+}
+#else
+using uintptr_t = fallback_uintptr;
+inline auto to_uintptr(const void* p) -> fallback_uintptr {
+ return fallback_uintptr(p);
+}
+#endif
+
+// Returns the largest possible value for type T. Same as
+// std::numeric_limits<T>::max() but shorter and not affected by the max macro.
+template <typename T> constexpr auto max_value() -> T {
+ return (std::numeric_limits<T>::max)();
+}
+template <typename T> constexpr auto num_bits() -> int {
+ return std::numeric_limits<T>::digits;
+}
+// std::numeric_limits<T>::digits may return 0 for 128-bit ints.
+template <> constexpr auto num_bits<int128_t>() -> int { return 128; }
+template <> constexpr auto num_bits<uint128_t>() -> int { return 128; }
+template <> constexpr auto num_bits<fallback_uintptr>() -> int {
+ return static_cast<int>(sizeof(void*) *
+ std::numeric_limits<unsigned char>::digits);
+}
+
+FMT_INLINE void assume(bool condition) {
+ (void)condition;
+#if FMT_HAS_BUILTIN(__builtin_assume)
+ __builtin_assume(condition);
+#endif
+}
+
+// An approximation of iterator_t for pre-C++20 systems.
+template <typename T>
+using iterator_t = decltype(std::begin(std::declval<T&>()));
+template <typename T> using sentinel_t = decltype(std::end(std::declval<T&>()));
+
+// A workaround for std::string not having mutable data() until C++17.
+template <typename Char>
+inline auto get_data(std::basic_string<Char>& s) -> Char* {
+ return &s[0];
+}
+template <typename Container>
+inline auto get_data(Container& c) -> typename Container::value_type* {
+ return c.data();
+}
+
+#if defined(_SECURE_SCL) && _SECURE_SCL
+// Make a checked iterator to avoid MSVC warnings.
+template <typename T> using checked_ptr = stdext::checked_array_iterator<T*>;
+template <typename T>
+constexpr auto make_checked(T* p, size_t size) -> checked_ptr<T> {
+ return {p, size};
+}
+#else
+template <typename T> using checked_ptr = T*;
+template <typename T> constexpr auto make_checked(T* p, size_t) -> T* {
+ return p;
+}
+#endif
+
+// Attempts to reserve space for n extra characters in the output range.
+// Returns a pointer to the reserved range or a reference to it.
+template <typename Container, FMT_ENABLE_IF(is_contiguous<Container>::value)>
+#if FMT_CLANG_VERSION >= 307 && !FMT_ICC_VERSION
+__attribute__((no_sanitize("undefined")))
+#endif
+inline auto
+reserve(std::back_insert_iterator<Container> it, size_t n)
+ -> checked_ptr<typename Container::value_type> {
+ Container& c = get_container(it);
+ size_t size = c.size();
+ c.resize(size + n);
+ return make_checked(get_data(c) + size, n);
+}
+
+template <typename T>
+inline auto reserve(buffer_appender<T> it, size_t n) -> buffer_appender<T> {
+ buffer<T>& buf = get_container(it);
+ buf.try_reserve(buf.size() + n);
+ return it;
+}
+
+template <typename Iterator>
+constexpr auto reserve(Iterator& it, size_t) -> Iterator& {
+ return it;
+}
+
+template <typename OutputIt>
+using reserve_iterator =
+ remove_reference_t<decltype(reserve(std::declval<OutputIt&>(), 0))>;
+
+template <typename T, typename OutputIt>
+constexpr auto to_pointer(OutputIt, size_t) -> T* {
+ return nullptr;
+}
+template <typename T> auto to_pointer(buffer_appender<T> it, size_t n) -> T* {
+ buffer<T>& buf = get_container(it);
+ auto size = buf.size();
+ if (buf.capacity() < size + n) return nullptr;
+ buf.try_resize(size + n);
+ return buf.data() + size;
+}
+
+template <typename Container, FMT_ENABLE_IF(is_contiguous<Container>::value)>
+inline auto base_iterator(std::back_insert_iterator<Container>& it,
+ checked_ptr<typename Container::value_type>)
+ -> std::back_insert_iterator<Container> {
+ return it;
+}
+
+template <typename Iterator>
+constexpr auto base_iterator(Iterator, Iterator it) -> Iterator {
+ return it;
+}
+
+// <algorithm> is spectacularly slow to compile in C++20 so use a simple fill_n
+// instead (#1998).
+template <typename OutputIt, typename Size, typename T>
+FMT_CONSTEXPR auto fill_n(OutputIt out, Size count, const T& value)
+ -> OutputIt {
+ for (Size i = 0; i < count; ++i) *out++ = value;
+ return out;
+}
+template <typename T, typename Size>
+FMT_CONSTEXPR20 auto fill_n(T* out, Size count, char value) -> T* {
+ if (is_constant_evaluated()) {
+ return fill_n<T*, Size, T>(out, count, value);
+ }
+ std::memset(out, value, to_unsigned(count));
+ return out + count;
+}
+
+#ifdef __cpp_char8_t
+using char8_type = char8_t;
+#else
+enum char8_type : unsigned char {};
+#endif
+
+template <typename OutChar, typename InputIt, typename OutputIt>
+FMT_CONSTEXPR FMT_NOINLINE auto copy_str_noinline(InputIt begin, InputIt end,
+ OutputIt out) -> OutputIt {
+ return copy_str<OutChar>(begin, end, out);
+}
+
+// A public domain branchless UTF-8 decoder by Christopher Wellons:
+// https://github.com/skeeto/branchless-utf8
+/* Decode the next character, c, from s, reporting errors in e.
+ *
+ * Since this is a branchless decoder, four bytes will be read from the
+ * buffer regardless of the actual length of the next character. This
+ * means the buffer _must_ have at least three bytes of zero padding
+ * following the end of the data stream.
+ *
+ * Errors are reported in e, which will be non-zero if the parsed
+ * character was somehow invalid: invalid byte sequence, non-canonical
+ * encoding, or a surrogate half.
+ *
+ * The function returns a pointer to the next character. When an error
+ * occurs, this pointer will be a guess that depends on the particular
+ * error, but it will always advance at least one byte.
+ */
+FMT_CONSTEXPR inline auto utf8_decode(const char* s, uint32_t* c, int* e)
+ -> const char* {
+ constexpr const int masks[] = {0x00, 0x7f, 0x1f, 0x0f, 0x07};
+ constexpr const uint32_t mins[] = {4194304, 0, 128, 2048, 65536};
+ constexpr const int shiftc[] = {0, 18, 12, 6, 0};
+ constexpr const int shifte[] = {0, 6, 4, 2, 0};
+
+ int len = code_point_length(s);
+ const char* next = s + len;
+
+ // Assume a four-byte character and load four bytes. Unused bits are
+ // shifted out.
+ *c = uint32_t(s[0] & masks[len]) << 18;
+ *c |= uint32_t(s[1] & 0x3f) << 12;
+ *c |= uint32_t(s[2] & 0x3f) << 6;
+ *c |= uint32_t(s[3] & 0x3f) << 0;
+ *c >>= shiftc[len];
+
+ // Accumulate the various error conditions.
+ using uchar = unsigned char;
+ *e = (*c < mins[len]) << 6; // non-canonical encoding
+ *e |= ((*c >> 11) == 0x1b) << 7; // surrogate half?
+ *e |= (*c > 0x10FFFF) << 8; // out of range?
+ *e |= (uchar(s[1]) & 0xc0) >> 2;
+ *e |= (uchar(s[2]) & 0xc0) >> 4;
+ *e |= uchar(s[3]) >> 6;
+ *e ^= 0x2a; // top two bits of each tail byte correct?
+ *e >>= shifte[len];
+
+ return next;
+}
+
+constexpr uint32_t invalid_code_point = ~uint32_t();
+
+// Invokes f(cp, sv) for every code point cp in s with sv being the string view
+// corresponding to the code point. cp is invalid_code_point on error.
+template <typename F>
+FMT_CONSTEXPR void for_each_codepoint(string_view s, F f) {
+ auto decode = [f](const char* buf_ptr, const char* ptr) {
+ auto cp = uint32_t();
+ auto error = 0;
+ auto end = utf8_decode(buf_ptr, &cp, &error);
+ bool result = f(error ? invalid_code_point : cp,
+ string_view(ptr, to_unsigned(end - buf_ptr)));
+ return result ? end : nullptr;
+ };
+ auto p = s.data();
+ const size_t block_size = 4; // utf8_decode always reads blocks of 4 chars.
+ if (s.size() >= block_size) {
+ for (auto end = p + s.size() - block_size + 1; p < end;) {
+ p = decode(p, p);
+ if (!p) return;
+ }
+ }
+ if (auto num_chars_left = s.data() + s.size() - p) {
+ char buf[2 * block_size - 1] = {};
+ copy_str<char>(p, p + num_chars_left, buf);
+ const char* buf_ptr = buf;
+ do {
+ auto end = decode(buf_ptr, p);
+ if (!end) return;
+ p += end - buf_ptr;
+ buf_ptr = end;
+ } while (buf_ptr - buf < num_chars_left);
+ }
+}
+
+template <typename Char>
+inline auto compute_width(basic_string_view<Char> s) -> size_t {
+ return s.size();
+}
+
+// Computes approximate display width of a UTF-8 string.
+FMT_CONSTEXPR inline size_t compute_width(string_view s) {
+ size_t num_code_points = 0;
+ // It is not a lambda for compatibility with C++14.
+ struct count_code_points {
+ size_t* count;
+ FMT_CONSTEXPR auto operator()(uint32_t cp, string_view) const -> bool {
+ *count += detail::to_unsigned(
+ 1 +
+ (cp >= 0x1100 &&
+ (cp <= 0x115f || // Hangul Jamo init. consonants
+ cp == 0x2329 || // LEFT-POINTING ANGLE BRACKET
+ cp == 0x232a || // RIGHT-POINTING ANGLE BRACKET
+ // CJK ... Yi except IDEOGRAPHIC HALF FILL SPACE:
+ (cp >= 0x2e80 && cp <= 0xa4cf && cp != 0x303f) ||
+ (cp >= 0xac00 && cp <= 0xd7a3) || // Hangul Syllables
+ (cp >= 0xf900 && cp <= 0xfaff) || // CJK Compatibility Ideographs
+ (cp >= 0xfe10 && cp <= 0xfe19) || // Vertical Forms
+ (cp >= 0xfe30 && cp <= 0xfe6f) || // CJK Compatibility Forms
+ (cp >= 0xff00 && cp <= 0xff60) || // Fullwidth Forms
+ (cp >= 0xffe0 && cp <= 0xffe6) || // Fullwidth Forms
+ (cp >= 0x20000 && cp <= 0x2fffd) || // CJK
+ (cp >= 0x30000 && cp <= 0x3fffd) ||
+ // Miscellaneous Symbols and Pictographs + Emoticons:
+ (cp >= 0x1f300 && cp <= 0x1f64f) ||
+ // Supplemental Symbols and Pictographs:
+ (cp >= 0x1f900 && cp <= 0x1f9ff))));
+ return true;
+ }
+ };
+ for_each_codepoint(s, count_code_points{&num_code_points});
+ return num_code_points;
+}
+
+inline auto compute_width(basic_string_view<char8_type> s) -> size_t {
+ return compute_width(basic_string_view<char>(
+ reinterpret_cast<const char*>(s.data()), s.size()));
+}
+
+template <typename Char>
+inline auto code_point_index(basic_string_view<Char> s, size_t n) -> size_t {
+ size_t size = s.size();
+ return n < size ? n : size;
+}
+
+// Calculates the index of the nth code point in a UTF-8 string.
+inline auto code_point_index(basic_string_view<char8_type> s, size_t n)
+ -> size_t {
+ const char8_type* data = s.data();
+ size_t num_code_points = 0;
+ for (size_t i = 0, size = s.size(); i != size; ++i) {
+ if ((data[i] & 0xc0) != 0x80 && ++num_code_points > n) return i;
+ }
+ return s.size();
+}
+
+template <typename T, bool = std::is_floating_point<T>::value>
+struct is_fast_float : bool_constant<std::numeric_limits<T>::is_iec559 &&
+ sizeof(T) <= sizeof(double)> {};
+template <typename T> struct is_fast_float<T, false> : std::false_type {};
+
+#ifndef FMT_USE_FULL_CACHE_DRAGONBOX
+# define FMT_USE_FULL_CACHE_DRAGONBOX 0
+#endif
+
+template <typename T>
+template <typename U>
+void buffer<T>::append(const U* begin, const U* end) {
+ while (begin != end) {
+ auto count = to_unsigned(end - begin);
+ try_reserve(size_ + count);
+ auto free_cap = capacity_ - size_;
+ if (free_cap < count) count = free_cap;
+ std::uninitialized_copy_n(begin, count, make_checked(ptr_ + size_, count));
+ size_ += count;
+ begin += count;
+ }
+}
+
+template <typename T, typename Enable = void>
+struct is_locale : std::false_type {};
+template <typename T>
+struct is_locale<T, void_t<decltype(T::classic())>> : std::true_type {};
+} // namespace detail
+
+FMT_MODULE_EXPORT_BEGIN
+
+// The number of characters to store in the basic_memory_buffer object itself
+// to avoid dynamic memory allocation.
+enum { inline_buffer_size = 500 };
+
+/**
+ \rst
+ A dynamically growing memory buffer for trivially copyable/constructible types
+ with the first ``SIZE`` elements stored in the object itself.
+
+ You can use the ``memory_buffer`` type alias for ``char`` instead.
+
+ **Example**::
+
+ auto out = fmt::memory_buffer();
+ format_to(std::back_inserter(out), "The answer is {}.", 42);
+
+ This will append the following output to the ``out`` object:
+
+ .. code-block:: none
+
+ The answer is 42.
+
+ The output can be converted to an ``std::string`` with ``to_string(out)``.
+ \endrst
+ */
+template <typename T, size_t SIZE = inline_buffer_size,
+ typename Allocator = std::allocator<T>>
+class basic_memory_buffer final : public detail::buffer<T> {
+ private:
+ T store_[SIZE];
+
+ // Don't inherit from Allocator avoid generating type_info for it.
+ Allocator alloc_;
+
+ // Deallocate memory allocated by the buffer.
+ FMT_CONSTEXPR20 void deallocate() {
+ T* data = this->data();
+ if (data != store_) alloc_.deallocate(data, this->capacity());
+ }
+
+ protected:
+ FMT_CONSTEXPR20 void grow(size_t size) override;
+
+ public:
+ using value_type = T;
+ using const_reference = const T&;
+
+ FMT_CONSTEXPR20 explicit basic_memory_buffer(
+ const Allocator& alloc = Allocator())
+ : alloc_(alloc) {
+ this->set(store_, SIZE);
+ if (detail::is_constant_evaluated()) {
+ detail::fill_n(store_, SIZE, T{});
+ }
+ }
+ FMT_CONSTEXPR20 ~basic_memory_buffer() { deallocate(); }
+
+ private:
+ // Move data from other to this buffer.
+ FMT_CONSTEXPR20 void move(basic_memory_buffer& other) {
+ alloc_ = std::move(other.alloc_);
+ T* data = other.data();
+ size_t size = other.size(), capacity = other.capacity();
+ if (data == other.store_) {
+ this->set(store_, capacity);
+ if (detail::is_constant_evaluated()) {
+ detail::copy_str<T>(other.store_, other.store_ + size,
+ detail::make_checked(store_, capacity));
+ } else {
+ std::uninitialized_copy(other.store_, other.store_ + size,
+ detail::make_checked(store_, capacity));
+ }
+ } else {
+ this->set(data, capacity);
+ // Set pointer to the inline array so that delete is not called
+ // when deallocating.
+ other.set(other.store_, 0);
+ }
+ this->resize(size);
+ }
+
+ public:
+ /**
+ \rst
+ Constructs a :class:`fmt::basic_memory_buffer` object moving the content
+ of the other object to it.
+ \endrst
+ */
+ FMT_CONSTEXPR20 basic_memory_buffer(basic_memory_buffer&& other)
+ FMT_NOEXCEPT {
+ move(other);
+ }
+
+ /**
+ \rst
+ Moves the content of the other ``basic_memory_buffer`` object to this one.
+ \endrst
+ */
+ auto operator=(basic_memory_buffer&& other) FMT_NOEXCEPT
+ -> basic_memory_buffer& {
+ FMT_ASSERT(this != &other, "");
+ deallocate();
+ move(other);
+ return *this;
+ }
+
+ // Returns a copy of the allocator associated with this buffer.
+ auto get_allocator() const -> Allocator { return alloc_; }
+
+ /**
+ Resizes the buffer to contain *count* elements. If T is a POD type new
+ elements may not be initialized.
+ */
+ FMT_CONSTEXPR20 void resize(size_t count) { this->try_resize(count); }
+
+ /** Increases the buffer capacity to *new_capacity*. */
+ void reserve(size_t new_capacity) { this->try_reserve(new_capacity); }
+
+ // Directly append data into the buffer
+ using detail::buffer<T>::append;
+ template <typename ContiguousRange>
+ void append(const ContiguousRange& range) {
+ append(range.data(), range.data() + range.size());
+ }
+};
+
+template <typename T, size_t SIZE, typename Allocator>
+FMT_CONSTEXPR20 void basic_memory_buffer<T, SIZE, Allocator>::grow(
+ size_t size) {
+#ifdef FMT_FUZZ
+ if (size > 5000) throw std::runtime_error("fuzz mode - won't grow that much");
+#endif
+ const size_t max_size = std::allocator_traits<Allocator>::max_size(alloc_);
+ size_t old_capacity = this->capacity();
+ size_t new_capacity = old_capacity + old_capacity / 2;
+ if (size > new_capacity)
+ new_capacity = size;
+ else if (new_capacity > max_size)
+ new_capacity = size > max_size ? size : max_size;
+ T* old_data = this->data();
+ T* new_data =
+ std::allocator_traits<Allocator>::allocate(alloc_, new_capacity);
+ // The following code doesn't throw, so the raw pointer above doesn't leak.
+ std::uninitialized_copy(old_data, old_data + this->size(),
+ detail::make_checked(new_data, new_capacity));
+ this->set(new_data, new_capacity);
+ // deallocate must not throw according to the standard, but even if it does,
+ // the buffer already uses the new storage and will deallocate it in
+ // destructor.
+ if (old_data != store_) alloc_.deallocate(old_data, old_capacity);
+}
+
+using memory_buffer = basic_memory_buffer<char>;
+
+template <typename T, size_t SIZE, typename Allocator>
+struct is_contiguous<basic_memory_buffer<T, SIZE, Allocator>> : std::true_type {
+};
+
+namespace detail {
+FMT_API void print(std::FILE*, string_view);
+}
+
+/** A formatting error such as invalid format string. */
+FMT_CLASS_API
+class FMT_API format_error : public std::runtime_error {
+ public:
+ explicit format_error(const char* message) : std::runtime_error(message) {}
+ explicit format_error(const std::string& message)
+ : std::runtime_error(message) {}
+ format_error(const format_error&) = default;
+ format_error& operator=(const format_error&) = default;
+ format_error(format_error&&) = default;
+ format_error& operator=(format_error&&) = default;
+ ~format_error() FMT_NOEXCEPT override FMT_MSC_DEFAULT;
+};
+
+/**
+ \rst
+ Constructs a `~fmt::format_arg_store` object that contains references
+ to arguments and can be implicitly converted to `~fmt::format_args`.
+ If ``fmt`` is a compile-time string then `make_args_checked` checks
+ its validity at compile time.
+ \endrst
+ */
+template <typename... Args, typename S, typename Char = char_t<S>>
+FMT_INLINE auto make_args_checked(const S& fmt,
+ const remove_reference_t<Args>&... args)
+ -> format_arg_store<buffer_context<Char>, remove_reference_t<Args>...> {
+ static_assert(
+ detail::count<(
+ std::is_base_of<detail::view, remove_reference_t<Args>>::value &&
+ std::is_reference<Args>::value)...>() == 0,
+ "passing views as lvalues is disallowed");
+ detail::check_format_string<Args...>(fmt);
+ return {args...};
+}
+
+// compile-time support
+namespace detail_exported {
+#if FMT_USE_NONTYPE_TEMPLATE_PARAMETERS
+template <typename Char, size_t N> struct fixed_string {
+ constexpr fixed_string(const Char (&str)[N]) {
+ detail::copy_str<Char, const Char*, Char*>(static_cast<const Char*>(str),
+ str + N, data);
+ }
+ Char data[N]{};
+};
+#endif
+
+// Converts a compile-time string to basic_string_view.
+template <typename Char, size_t N>
+constexpr auto compile_string_to_view(const Char (&s)[N])
+ -> basic_string_view<Char> {
+ // Remove trailing NUL character if needed. Won't be present if this is used
+ // with a raw character array (i.e. not defined as a string).
+ return {s, N - (std::char_traits<Char>::to_int_type(s[N - 1]) == 0 ? 1 : 0)};
+}
+template <typename Char>
+constexpr auto compile_string_to_view(detail::std_string_view<Char> s)
+ -> basic_string_view<Char> {
+ return {s.data(), s.size()};
+}
+} // namespace detail_exported
+
+FMT_BEGIN_DETAIL_NAMESPACE
+
+template <typename T> struct is_integral : std::is_integral<T> {};
+template <> struct is_integral<int128_t> : std::true_type {};
+template <> struct is_integral<uint128_t> : std::true_type {};
+
+template <typename T>
+using is_signed =
+ std::integral_constant<bool, std::numeric_limits<T>::is_signed ||
+ std::is_same<T, int128_t>::value>;
+
+// Returns true if value is negative, false otherwise.
+// Same as `value < 0` but doesn't produce warnings if T is an unsigned type.
+template <typename T, FMT_ENABLE_IF(is_signed<T>::value)>
+FMT_CONSTEXPR auto is_negative(T value) -> bool {
+ return value < 0;
+}
+template <typename T, FMT_ENABLE_IF(!is_signed<T>::value)>
+FMT_CONSTEXPR auto is_negative(T) -> bool {
+ return false;
+}
+
+template <typename T, FMT_ENABLE_IF(std::is_floating_point<T>::value)>
+FMT_CONSTEXPR auto is_supported_floating_point(T) -> uint16_t {
+ return (std::is_same<T, float>::value && FMT_USE_FLOAT) ||
+ (std::is_same<T, double>::value && FMT_USE_DOUBLE) ||
+ (std::is_same<T, long double>::value && FMT_USE_LONG_DOUBLE);
+}
+
+// Smallest of uint32_t, uint64_t, uint128_t that is large enough to
+// represent all values of an integral type T.
+template <typename T>
+using uint32_or_64_or_128_t =
+ conditional_t<num_bits<T>() <= 32 && !FMT_REDUCE_INT_INSTANTIATIONS,
+ uint32_t,
+ conditional_t<num_bits<T>() <= 64, uint64_t, uint128_t>>;
+template <typename T>
+using uint64_or_128_t = conditional_t<num_bits<T>() <= 64, uint64_t, uint128_t>;
+
+#define FMT_POWERS_OF_10(factor) \
+ factor * 10, (factor)*100, (factor)*1000, (factor)*10000, (factor)*100000, \
+ (factor)*1000000, (factor)*10000000, (factor)*100000000, \
+ (factor)*1000000000
+
+// Converts value in the range [0, 100) to a string.
+constexpr const char* digits2(size_t value) {
+ // GCC generates slightly better code when value is pointer-size.
+ return &"0001020304050607080910111213141516171819"
+ "2021222324252627282930313233343536373839"
+ "4041424344454647484950515253545556575859"
+ "6061626364656667686970717273747576777879"
+ "8081828384858687888990919293949596979899"[value * 2];
+}
+
+// Sign is a template parameter to workaround a bug in gcc 4.8.
+template <typename Char, typename Sign> constexpr Char sign(Sign s) {
+#if !FMT_GCC_VERSION || FMT_GCC_VERSION >= 604
+ static_assert(std::is_same<Sign, sign_t>::value, "");
+#endif
+ return static_cast<Char>("\0-+ "[s]);
+}
+
+template <typename T> FMT_CONSTEXPR auto count_digits_fallback(T n) -> int {
+ int count = 1;
+ for (;;) {
+ // Integer division is slow so do it for a group of four digits instead
+ // of for every digit. The idea comes from the talk by Alexandrescu
+ // "Three Optimization Tips for C++". See speed-test for a comparison.
+ if (n < 10) return count;
+ if (n < 100) return count + 1;
+ if (n < 1000) return count + 2;
+ if (n < 10000) return count + 3;
+ n /= 10000u;
+ count += 4;
+ }
+}
+#if FMT_USE_INT128
+FMT_CONSTEXPR inline auto count_digits(uint128_t n) -> int {
+ return count_digits_fallback(n);
+}
+#endif
+
+#ifdef FMT_BUILTIN_CLZLL
+// It is a separate function rather than a part of count_digits to workaround
+// the lack of static constexpr in constexpr functions.
+inline auto do_count_digits(uint64_t n) -> int {
+ // This has comparable performance to the version by Kendall Willets
+ // (https://github.com/fmtlib/format-benchmark/blob/master/digits10)
+ // but uses smaller tables.
+ // Maps bsr(n) to ceil(log10(pow(2, bsr(n) + 1) - 1)).
+ static constexpr uint8_t bsr2log10[] = {
+ 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5,
+ 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10, 10, 10,
+ 10, 11, 11, 11, 12, 12, 12, 13, 13, 13, 13, 14, 14, 14, 15, 15,
+ 15, 16, 16, 16, 16, 17, 17, 17, 18, 18, 18, 19, 19, 19, 19, 20};
+ auto t = bsr2log10[FMT_BUILTIN_CLZLL(n | 1) ^ 63];
+ static constexpr const uint64_t zero_or_powers_of_10[] = {
+ 0, 0, FMT_POWERS_OF_10(1U), FMT_POWERS_OF_10(1000000000ULL),
+ 10000000000000000000ULL};
+ return t - (n < zero_or_powers_of_10[t]);
+}
+#endif
+
+// Returns the number of decimal digits in n. Leading zeros are not counted
+// except for n == 0 in which case count_digits returns 1.
+FMT_CONSTEXPR20 inline auto count_digits(uint64_t n) -> int {
+#ifdef FMT_BUILTIN_CLZLL
+ if (!is_constant_evaluated()) {
+ return do_count_digits(n);
+ }
+#endif
+ return count_digits_fallback(n);
+}
+
+// Counts the number of digits in n. BITS = log2(radix).
+template <int BITS, typename UInt>
+FMT_CONSTEXPR auto count_digits(UInt n) -> int {
+#ifdef FMT_BUILTIN_CLZ
+ if (num_bits<UInt>() == 32)
+ return (FMT_BUILTIN_CLZ(static_cast<uint32_t>(n) | 1) ^ 31) / BITS + 1;
+#endif
+ // Lambda avoids unreachable code warnings from NVHPC.
+ return [](UInt m) {
+ int num_digits = 0;
+ do {
+ ++num_digits;
+ } while ((m >>= BITS) != 0);
+ return num_digits;
+ }(n);
+}
+
+template <> auto count_digits<4>(detail::fallback_uintptr n) -> int;
+
+#ifdef FMT_BUILTIN_CLZ
+// It is a separate function rather than a part of count_digits to workaround
+// the lack of static constexpr in constexpr functions.
+FMT_INLINE auto do_count_digits(uint32_t n) -> int {
+// An optimization by Kendall Willets from https://bit.ly/3uOIQrB.
+// This increments the upper 32 bits (log10(T) - 1) when >= T is added.
+# define FMT_INC(T) (((sizeof(# T) - 1ull) << 32) - T)
+ static constexpr uint64_t table[] = {
+ FMT_INC(0), FMT_INC(0), FMT_INC(0), // 8
+ FMT_INC(10), FMT_INC(10), FMT_INC(10), // 64
+ FMT_INC(100), FMT_INC(100), FMT_INC(100), // 512
+ FMT_INC(1000), FMT_INC(1000), FMT_INC(1000), // 4096
+ FMT_INC(10000), FMT_INC(10000), FMT_INC(10000), // 32k
+ FMT_INC(100000), FMT_INC(100000), FMT_INC(100000), // 256k
+ FMT_INC(1000000), FMT_INC(1000000), FMT_INC(1000000), // 2048k
+ FMT_INC(10000000), FMT_INC(10000000), FMT_INC(10000000), // 16M
+ FMT_INC(100000000), FMT_INC(100000000), FMT_INC(100000000), // 128M
+ FMT_INC(1000000000), FMT_INC(1000000000), FMT_INC(1000000000), // 1024M
+ FMT_INC(1000000000), FMT_INC(1000000000) // 4B
+ };
+ auto inc = table[FMT_BUILTIN_CLZ(n | 1) ^ 31];
+ return static_cast<int>((n + inc) >> 32);
+}
+#endif
+
+// Optional version of count_digits for better performance on 32-bit platforms.
+FMT_CONSTEXPR20 inline auto count_digits(uint32_t n) -> int {
+#ifdef FMT_BUILTIN_CLZ
+ if (!is_constant_evaluated()) {
+ return do_count_digits(n);
+ }
+#endif
+ return count_digits_fallback(n);
+}
+
+template <typename Int> constexpr auto digits10() FMT_NOEXCEPT -> int {
+ return std::numeric_limits<Int>::digits10;
+}
+template <> constexpr auto digits10<int128_t>() FMT_NOEXCEPT -> int {
+ return 38;
+}
+template <> constexpr auto digits10<uint128_t>() FMT_NOEXCEPT -> int {
+ return 38;
+}
+
+template <typename Char> struct thousands_sep_result {
+ std::string grouping;
+ Char thousands_sep;
+};
+
+template <typename Char>
+FMT_API auto thousands_sep_impl(locale_ref loc) -> thousands_sep_result<Char>;
+template <typename Char>
+inline auto thousands_sep(locale_ref loc) -> thousands_sep_result<Char> {
+ auto result = thousands_sep_impl<char>(loc);
+ return {result.grouping, Char(result.thousands_sep)};
+}
+template <>
+inline auto thousands_sep(locale_ref loc) -> thousands_sep_result<wchar_t> {
+ return thousands_sep_impl<wchar_t>(loc);
+}
+
+template <typename Char>
+FMT_API auto decimal_point_impl(locale_ref loc) -> Char;
+template <typename Char> inline auto decimal_point(locale_ref loc) -> Char {
+ return Char(decimal_point_impl<char>(loc));
+}
+template <> inline auto decimal_point(locale_ref loc) -> wchar_t {
+ return decimal_point_impl<wchar_t>(loc);
+}
+
+// Compares two characters for equality.
+template <typename Char> auto equal2(const Char* lhs, const char* rhs) -> bool {
+ return lhs[0] == Char(rhs[0]) && lhs[1] == Char(rhs[1]);
+}
+inline auto equal2(const char* lhs, const char* rhs) -> bool {
+ return memcmp(lhs, rhs, 2) == 0;
+}
+
+// Copies two characters from src to dst.
+template <typename Char>
+FMT_CONSTEXPR20 FMT_INLINE void copy2(Char* dst, const char* src) {
+ if (!is_constant_evaluated() && sizeof(Char) == sizeof(char)) {
+ memcpy(dst, src, 2);
+ return;
+ }
+ *dst++ = static_cast<Char>(*src++);
+ *dst = static_cast<Char>(*src);
+}
+
+template <typename Iterator> struct format_decimal_result {
+ Iterator begin;
+ Iterator end;
+};
+
+// Formats a decimal unsigned integer value writing into out pointing to a
+// buffer of specified size. The caller must ensure that the buffer is large
+// enough.
+template <typename Char, typename UInt>
+FMT_CONSTEXPR20 auto format_decimal(Char* out, UInt value, int size)
+ -> format_decimal_result<Char*> {
+ FMT_ASSERT(size >= count_digits(value), "invalid digit count");
+ out += size;
+ Char* end = out;
+ while (value >= 100) {
+ // Integer division is slow so do it for a group of two digits instead
+ // of for every digit. The idea comes from the talk by Alexandrescu
+ // "Three Optimization Tips for C++". See speed-test for a comparison.
+ out -= 2;
+ copy2(out, digits2(static_cast<size_t>(value % 100)));
+ value /= 100;
+ }
+ if (value < 10) {
+ *--out = static_cast<Char>('0' + value);
+ return {out, end};
+ }
+ out -= 2;
+ copy2(out, digits2(static_cast<size_t>(value)));
+ return {out, end};
+}
+
+template <typename Char, typename UInt, typename Iterator,
+ FMT_ENABLE_IF(!std::is_pointer<remove_cvref_t<Iterator>>::value)>
+inline auto format_decimal(Iterator out, UInt value, int size)
+ -> format_decimal_result<Iterator> {
+ // Buffer is large enough to hold all digits (digits10 + 1).
+ Char buffer[digits10<UInt>() + 1];
+ auto end = format_decimal(buffer, value, size).end;
+ return {out, detail::copy_str_noinline<Char>(buffer, end, out)};
+}
+
+template <unsigned BASE_BITS, typename Char, typename UInt>
+FMT_CONSTEXPR auto format_uint(Char* buffer, UInt value, int num_digits,
+ bool upper = false) -> Char* {
+ buffer += num_digits;
+ Char* end = buffer;
+ do {
+ const char* digits = upper ? "0123456789ABCDEF" : "0123456789abcdef";
+ unsigned digit = (value & ((1 << BASE_BITS) - 1));
+ *--buffer = static_cast<Char>(BASE_BITS < 4 ? static_cast<char>('0' + digit)
+ : digits[digit]);
+ } while ((value >>= BASE_BITS) != 0);
+ return end;
+}
+
+template <unsigned BASE_BITS, typename Char>
+auto format_uint(Char* buffer, detail::fallback_uintptr n, int num_digits,
+ bool = false) -> Char* {
+ auto char_digits = std::numeric_limits<unsigned char>::digits / 4;
+ int start = (num_digits + char_digits - 1) / char_digits - 1;
+ if (int start_digits = num_digits % char_digits) {
+ unsigned value = n.value[start--];
+ buffer = format_uint<BASE_BITS>(buffer, value, start_digits);
+ }
+ for (; start >= 0; --start) {
+ unsigned value = n.value[start];
+ buffer += char_digits;
+ auto p = buffer;
+ for (int i = 0; i < char_digits; ++i) {
+ unsigned digit = (value & ((1 << BASE_BITS) - 1));
+ *--p = static_cast<Char>("0123456789abcdef"[digit]);
+ value >>= BASE_BITS;
+ }
+ }
+ return buffer;
+}
+
+template <unsigned BASE_BITS, typename Char, typename It, typename UInt>
+inline auto format_uint(It out, UInt value, int num_digits, bool upper = false)
+ -> It {
+ if (auto ptr = to_pointer<Char>(out, to_unsigned(num_digits))) {
+ format_uint<BASE_BITS>(ptr, value, num_digits, upper);
+ return out;
+ }
+ // Buffer should be large enough to hold all digits (digits / BASE_BITS + 1).
+ char buffer[num_bits<UInt>() / BASE_BITS + 1];
+ format_uint<BASE_BITS>(buffer, value, num_digits, upper);
+ return detail::copy_str_noinline<Char>(buffer, buffer + num_digits, out);
+}
+
+// A converter from UTF-8 to UTF-16.
+class utf8_to_utf16 {
+ private:
+ basic_memory_buffer<wchar_t> buffer_;
+
+ public:
+ FMT_API explicit utf8_to_utf16(string_view s);
+ operator basic_string_view<wchar_t>() const { return {&buffer_[0], size()}; }
+ auto size() const -> size_t { return buffer_.size() - 1; }
+ auto c_str() const -> const wchar_t* { return &buffer_[0]; }
+ auto str() const -> std::wstring { return {&buffer_[0], size()}; }
+};
+
+namespace dragonbox {
+
+// Type-specific information that Dragonbox uses.
+template <class T> struct float_info;
+
+template <> struct float_info<float> {
+ using carrier_uint = uint32_t;
+ static const int significand_bits = 23;
+ static const int exponent_bits = 8;
+ static const int min_exponent = -126;
+ static const int max_exponent = 127;
+ static const int exponent_bias = -127;
+ static const int decimal_digits = 9;
+ static const int kappa = 1;
+ static const int big_divisor = 100;
+ static const int small_divisor = 10;
+ static const int min_k = -31;
+ static const int max_k = 46;
+ static const int cache_bits = 64;
+ static const int divisibility_check_by_5_threshold = 39;
+ static const int case_fc_pm_half_lower_threshold = -1;
+ static const int case_fc_pm_half_upper_threshold = 6;
+ static const int case_fc_lower_threshold = -2;
+ static const int case_fc_upper_threshold = 6;
+ static const int case_shorter_interval_left_endpoint_lower_threshold = 2;
+ static const int case_shorter_interval_left_endpoint_upper_threshold = 3;
+ static const int shorter_interval_tie_lower_threshold = -35;
+ static const int shorter_interval_tie_upper_threshold = -35;
+ static const int max_trailing_zeros = 7;
+};
+
+template <> struct float_info<double> {
+ using carrier_uint = uint64_t;
+ static const int significand_bits = 52;
+ static const int exponent_bits = 11;
+ static const int min_exponent = -1022;
+ static const int max_exponent = 1023;
+ static const int exponent_bias = -1023;
+ static const int decimal_digits = 17;
+ static const int kappa = 2;
+ static const int big_divisor = 1000;
+ static const int small_divisor = 100;
+ static const int min_k = -292;
+ static const int max_k = 326;
+ static const int cache_bits = 128;
+ static const int divisibility_check_by_5_threshold = 86;
+ static const int case_fc_pm_half_lower_threshold = -2;
+ static const int case_fc_pm_half_upper_threshold = 9;
+ static const int case_fc_lower_threshold = -4;
+ static const int case_fc_upper_threshold = 9;
+ static const int case_shorter_interval_left_endpoint_lower_threshold = 2;
+ static const int case_shorter_interval_left_endpoint_upper_threshold = 3;
+ static const int shorter_interval_tie_lower_threshold = -77;
+ static const int shorter_interval_tie_upper_threshold = -77;
+ static const int max_trailing_zeros = 16;
+};
+
+template <typename T> struct decimal_fp {
+ using significand_type = typename float_info<T>::carrier_uint;
+ significand_type significand;
+ int exponent;
+};
+
+template <typename T>
+FMT_API auto to_decimal(T x) FMT_NOEXCEPT -> decimal_fp<T>;
+} // namespace dragonbox
+
+template <typename T>
+constexpr auto exponent_mask() ->
+ typename dragonbox::float_info<T>::carrier_uint {
+ using uint = typename dragonbox::float_info<T>::carrier_uint;
+ return ((uint(1) << dragonbox::float_info<T>::exponent_bits) - 1)
+ << dragonbox::float_info<T>::significand_bits;
+}
+
+// Writes the exponent exp in the form "[+-]d{2,3}" to buffer.
+template <typename Char, typename It>
+FMT_CONSTEXPR auto write_exponent(int exp, It it) -> It {
+ FMT_ASSERT(-10000 < exp && exp < 10000, "exponent out of range");
+ if (exp < 0) {
+ *it++ = static_cast<Char>('-');
+ exp = -exp;
+ } else {
+ *it++ = static_cast<Char>('+');
+ }
+ if (exp >= 100) {
+ const char* top = digits2(to_unsigned(exp / 100));
+ if (exp >= 1000) *it++ = static_cast<Char>(top[0]);
+ *it++ = static_cast<Char>(top[1]);
+ exp %= 100;
+ }
+ const char* d = digits2(to_unsigned(exp));
+ *it++ = static_cast<Char>(d[0]);
+ *it++ = static_cast<Char>(d[1]);
+ return it;
+}
+
+template <typename T>
+FMT_HEADER_ONLY_CONSTEXPR20 auto format_float(T value, int precision,
+ float_specs specs,
+ buffer<char>& buf) -> int;
+
+// Formats a floating-point number with snprintf.
+template <typename T>
+auto snprintf_float(T value, int precision, float_specs specs,
+ buffer<char>& buf) -> int;
+
+template <typename T> constexpr auto promote_float(T value) -> T {
+ return value;
+}
+constexpr auto promote_float(float value) -> double {
+ return static_cast<double>(value);
+}
+
+template <typename OutputIt, typename Char>
+FMT_NOINLINE FMT_CONSTEXPR auto fill(OutputIt it, size_t n,
+ const fill_t<Char>& fill) -> OutputIt {
+ auto fill_size = fill.size();
+ if (fill_size == 1) return detail::fill_n(it, n, fill[0]);
+ auto data = fill.data();
+ for (size_t i = 0; i < n; ++i)
+ it = copy_str<Char>(data, data + fill_size, it);
+ return it;
+}
+
+// Writes the output of f, padded according to format specifications in specs.
+// size: output size in code units.
+// width: output display width in (terminal) column positions.
+template <align::type align = align::left, typename OutputIt, typename Char,
+ typename F>
+FMT_CONSTEXPR auto write_padded(OutputIt out,
+ const basic_format_specs<Char>& specs,
+ size_t size, size_t width, F&& f) -> OutputIt {
+ static_assert(align == align::left || align == align::right, "");
+ unsigned spec_width = to_unsigned(specs.width);
+ size_t padding = spec_width > width ? spec_width - width : 0;
+ // Shifts are encoded as string literals because static constexpr is not
+ // supported in constexpr functions.
+ auto* shifts = align == align::left ? "\x1f\x1f\x00\x01" : "\x00\x1f\x00\x01";
+ size_t left_padding = padding >> shifts[specs.align];
+ size_t right_padding = padding - left_padding;
+ auto it = reserve(out, size + padding * specs.fill.size());
+ if (left_padding != 0) it = fill(it, left_padding, specs.fill);
+ it = f(it);
+ if (right_padding != 0) it = fill(it, right_padding, specs.fill);
+ return base_iterator(out, it);
+}
+
+template <align::type align = align::left, typename OutputIt, typename Char,
+ typename F>
+constexpr auto write_padded(OutputIt out, const basic_format_specs<Char>& specs,
+ size_t size, F&& f) -> OutputIt {
+ return write_padded<align>(out, specs, size, size, f);
+}
+
+template <align::type align = align::left, typename Char, typename OutputIt>
+FMT_CONSTEXPR auto write_bytes(OutputIt out, string_view bytes,
+ const basic_format_specs<Char>& specs)
+ -> OutputIt {
+ return write_padded<align>(
+ out, specs, bytes.size(), [bytes](reserve_iterator<OutputIt> it) {
+ const char* data = bytes.data();
+ return copy_str<Char>(data, data + bytes.size(), it);
+ });
+}
+
+template <typename Char, typename OutputIt, typename UIntPtr>
+auto write_ptr(OutputIt out, UIntPtr value,
+ const basic_format_specs<Char>* specs) -> OutputIt {
+ int num_digits = count_digits<4>(value);
+ auto size = to_unsigned(num_digits) + size_t(2);
+ auto write = [=](reserve_iterator<OutputIt> it) {
+ *it++ = static_cast<Char>('0');
+ *it++ = static_cast<Char>('x');
+ return format_uint<4, Char>(it, value, num_digits);
+ };
+ return specs ? write_padded<align::right>(out, *specs, size, write)
+ : base_iterator(out, write(reserve(out, size)));
+}
+
+template <typename Char, typename OutputIt>
+FMT_CONSTEXPR auto write_char(OutputIt out, Char value,
+ const basic_format_specs<Char>& specs)
+ -> OutputIt {
+ return write_padded(out, specs, 1, [=](reserve_iterator<OutputIt> it) {
+ *it++ = value;
+ return it;
+ });
+}
+template <typename Char, typename OutputIt>
+FMT_CONSTEXPR auto write(OutputIt out, Char value,
+ const basic_format_specs<Char>& specs,
+ locale_ref loc = {}) -> OutputIt {
+ return check_char_specs(specs)
+ ? write_char(out, value, specs)
+ : write(out, static_cast<int>(value), specs, loc);
+}
+
+// Data for write_int that doesn't depend on output iterator type. It is used to
+// avoid template code bloat.
+template <typename Char> struct write_int_data {
+ size_t size;
+ size_t padding;
+
+ FMT_CONSTEXPR write_int_data(int num_digits, unsigned prefix,
+ const basic_format_specs<Char>& specs)
+ : size((prefix >> 24) + to_unsigned(num_digits)), padding(0) {
+ if (specs.align == align::numeric) {
+ auto width = to_unsigned(specs.width);
+ if (width > size) {
+ padding = width - size;
+ size = width;
+ }
+ } else if (specs.precision > num_digits) {
+ size = (prefix >> 24) + to_unsigned(specs.precision);
+ padding = to_unsigned(specs.precision - num_digits);
+ }
+ }
+};
+
+// Writes an integer in the format
+// <left-padding><prefix><numeric-padding><digits><right-padding>
+// where <digits> are written by write_digits(it).
+// prefix contains chars in three lower bytes and the size in the fourth byte.
+template <typename OutputIt, typename Char, typename W>
+FMT_CONSTEXPR FMT_INLINE auto write_int(OutputIt out, int num_digits,
+ unsigned prefix,
+ const basic_format_specs<Char>& specs,
+ W write_digits) -> OutputIt {
+ // Slightly faster check for specs.width == 0 && specs.precision == -1.
+ if ((specs.width | (specs.precision + 1)) == 0) {
+ auto it = reserve(out, to_unsigned(num_digits) + (prefix >> 24));
+ if (prefix != 0) {
+ for (unsigned p = prefix & 0xffffff; p != 0; p >>= 8)
+ *it++ = static_cast<Char>(p & 0xff);
+ }
+ return base_iterator(out, write_digits(it));
+ }
+ auto data = write_int_data<Char>(num_digits, prefix, specs);
+ return write_padded<align::right>(
+ out, specs, data.size, [=](reserve_iterator<OutputIt> it) {
+ for (unsigned p = prefix & 0xffffff; p != 0; p >>= 8)
+ *it++ = static_cast<Char>(p & 0xff);
+ it = detail::fill_n(it, data.padding, static_cast<Char>('0'));
+ return write_digits(it);
+ });
+}
+
+template <typename Char> class digit_grouping {
+ private:
+ thousands_sep_result<Char> sep_;
+
+ struct next_state {
+ std::string::const_iterator group;
+ int pos;
+ };
+ next_state initial_state() const { return {sep_.grouping.begin(), 0}; }
+
+ // Returns the next digit group separator position.
+ int next(next_state& state) const {
+ if (!sep_.thousands_sep) return max_value<int>();
+ if (state.group == sep_.grouping.end())
+ return state.pos += sep_.grouping.back();
+ if (*state.group <= 0 || *state.group == max_value<char>())
+ return max_value<int>();
+ state.pos += *state.group++;
+ return state.pos;
+ }
+
+ public:
+ explicit digit_grouping(locale_ref loc, bool localized = true) {
+ if (localized)
+ sep_ = thousands_sep<Char>(loc);
+ else
+ sep_.thousands_sep = Char();
+ }
+ explicit digit_grouping(thousands_sep_result<Char> sep) : sep_(sep) {}
+
+ Char separator() const { return sep_.thousands_sep; }
+
+ int count_separators(int num_digits) const {
+ int count = 0;
+ auto state = initial_state();
+ while (num_digits > next(state)) ++count;
+ return count;
+ }
+
+ // Applies grouping to digits and write the output to out.
+ template <typename Out, typename C>
+ Out apply(Out out, basic_string_view<C> digits) const {
+ auto num_digits = static_cast<int>(digits.size());
+ auto separators = basic_memory_buffer<int>();
+ separators.push_back(0);
+ auto state = initial_state();
+ while (int i = next(state)) {
+ if (i >= num_digits) break;
+ separators.push_back(i);
+ }
+ for (int i = 0, sep_index = static_cast<int>(separators.size() - 1);
+ i < num_digits; ++i) {
+ if (num_digits - i == separators[sep_index]) {
+ *out++ = separator();
+ --sep_index;
+ }
+ *out++ = static_cast<Char>(digits[to_unsigned(i)]);
+ }
+ return out;
+ }
+};
+
+template <typename OutputIt, typename UInt, typename Char>
+auto write_int_localized(OutputIt out, UInt value, unsigned prefix,
+ const basic_format_specs<Char>& specs,
+ const digit_grouping<Char>& grouping) -> OutputIt {
+ static_assert(std::is_same<uint64_or_128_t<UInt>, UInt>::value, "");
+ int num_digits = count_digits(value);
+ char digits[40];
+ format_decimal(digits, value, num_digits);
+ unsigned size = to_unsigned((prefix != 0 ? 1 : 0) + num_digits +
+ grouping.count_separators(num_digits));
+ return write_padded<align::right>(
+ out, specs, size, size, [&](reserve_iterator<OutputIt> it) {
+ if (prefix != 0) *it++ = static_cast<Char>(prefix);
+ return grouping.apply(it, string_view(digits, to_unsigned(num_digits)));
+ });
+}
+
+template <typename OutputIt, typename UInt, typename Char>
+auto write_int_localized(OutputIt& out, UInt value, unsigned prefix,
+ const basic_format_specs<Char>& specs, locale_ref loc)
+ -> bool {
+ auto grouping = digit_grouping<Char>(loc);
+ out = write_int_localized(out, value, prefix, specs, grouping);
+ return true;
+}
+
+FMT_CONSTEXPR inline void prefix_append(unsigned& prefix, unsigned value) {
+ prefix |= prefix != 0 ? value << 8 : value;
+ prefix += (1u + (value > 0xff ? 1 : 0)) << 24;
+}
+
+template <typename UInt> struct write_int_arg {
+ UInt abs_value;
+ unsigned prefix;
+};
+
+template <typename T>
+FMT_CONSTEXPR auto make_write_int_arg(T value, sign_t sign)
+ -> write_int_arg<uint32_or_64_or_128_t<T>> {
+ auto prefix = 0u;
+ auto abs_value = static_cast<uint32_or_64_or_128_t<T>>(value);
+ if (is_negative(value)) {
+ prefix = 0x01000000 | '-';
+ abs_value = 0 - abs_value;
+ } else {
+ constexpr const unsigned prefixes[4] = {0, 0, 0x1000000u | '+',
+ 0x1000000u | ' '};
+ prefix = prefixes[sign];
+ }
+ return {abs_value, prefix};
+}
+
+template <typename Char, typename OutputIt, typename T>
+FMT_CONSTEXPR FMT_INLINE auto write_int(OutputIt out, write_int_arg<T> arg,
+ const basic_format_specs<Char>& specs,
+ locale_ref loc) -> OutputIt {
+ static_assert(std::is_same<T, uint32_or_64_or_128_t<T>>::value, "");
+ auto abs_value = arg.abs_value;
+ auto prefix = arg.prefix;
+ switch (specs.type) {
+ case presentation_type::none:
+ case presentation_type::dec: {
+ if (specs.localized &&
+ write_int_localized(out, static_cast<uint64_or_128_t<T>>(abs_value),
+ prefix, specs, loc)) {
+ return out;
+ }
+ auto num_digits = count_digits(abs_value);
+ return write_int(
+ out, num_digits, prefix, specs, [=](reserve_iterator<OutputIt> it) {
+ return format_decimal<Char>(it, abs_value, num_digits).end;
+ });
+ }
+ case presentation_type::hex_lower:
+ case presentation_type::hex_upper: {
+ bool upper = specs.type == presentation_type::hex_upper;
+ if (specs.alt)
+ prefix_append(prefix, unsigned(upper ? 'X' : 'x') << 8 | '0');
+ int num_digits = count_digits<4>(abs_value);
+ return write_int(
+ out, num_digits, prefix, specs, [=](reserve_iterator<OutputIt> it) {
+ return format_uint<4, Char>(it, abs_value, num_digits, upper);
+ });
+ }
+ case presentation_type::bin_lower:
+ case presentation_type::bin_upper: {
+ bool upper = specs.type == presentation_type::bin_upper;
+ if (specs.alt)
+ prefix_append(prefix, unsigned(upper ? 'B' : 'b') << 8 | '0');
+ int num_digits = count_digits<1>(abs_value);
+ return write_int(out, num_digits, prefix, specs,
+ [=](reserve_iterator<OutputIt> it) {
+ return format_uint<1, Char>(it, abs_value, num_digits);
+ });
+ }
+ case presentation_type::oct: {
+ int num_digits = count_digits<3>(abs_value);
+ // Octal prefix '0' is counted as a digit, so only add it if precision
+ // is not greater than the number of digits.
+ if (specs.alt && specs.precision <= num_digits && abs_value != 0)
+ prefix_append(prefix, '0');
+ return write_int(out, num_digits, prefix, specs,
+ [=](reserve_iterator<OutputIt> it) {
+ return format_uint<3, Char>(it, abs_value, num_digits);
+ });
+ }
+ case presentation_type::chr:
+ return write_char(out, static_cast<Char>(abs_value), specs);
+ default:
+ throw_format_error("invalid type specifier");
+ }
+ return out;
+}
+template <typename Char, typename OutputIt, typename T>
+FMT_CONSTEXPR FMT_NOINLINE auto write_int_noinline(
+ OutputIt out, write_int_arg<T> arg, const basic_format_specs<Char>& specs,
+ locale_ref loc) -> OutputIt {
+ return write_int(out, arg, specs, loc);
+}
+template <typename Char, typename OutputIt, typename T,
+ FMT_ENABLE_IF(is_integral<T>::value &&
+ !std::is_same<T, bool>::value &&
+ std::is_same<OutputIt, buffer_appender<Char>>::value)>
+FMT_CONSTEXPR FMT_INLINE auto write(OutputIt out, T value,
+ const basic_format_specs<Char>& specs,
+ locale_ref loc) -> OutputIt {
+ return write_int_noinline(out, make_write_int_arg(value, specs.sign), specs,
+ loc);
+}
+// An inlined version of write used in format string compilation.
+template <typename Char, typename OutputIt, typename T,
+ FMT_ENABLE_IF(is_integral<T>::value &&
+ !std::is_same<T, bool>::value &&
+ !std::is_same<OutputIt, buffer_appender<Char>>::value)>
+FMT_CONSTEXPR FMT_INLINE auto write(OutputIt out, T value,
+ const basic_format_specs<Char>& specs,
+ locale_ref loc) -> OutputIt {
+ return write_int(out, make_write_int_arg(value, specs.sign), specs, loc);
+}
+
+template <typename Char, typename OutputIt>
+FMT_CONSTEXPR auto write(OutputIt out, basic_string_view<Char> s,
+ const basic_format_specs<Char>& specs) -> OutputIt {
+ auto data = s.data();
+ auto size = s.size();
+ if (specs.precision >= 0 && to_unsigned(specs.precision) < size)
+ size = code_point_index(s, to_unsigned(specs.precision));
+ auto width =
+ specs.width != 0 ? compute_width(basic_string_view<Char>(data, size)) : 0;
+ return write_padded(out, specs, size, width,
+ [=](reserve_iterator<OutputIt> it) {
+ return copy_str<Char>(data, data + size, it);
+ });
+}
+template <typename Char, typename OutputIt>
+FMT_CONSTEXPR auto write(OutputIt out,
+ basic_string_view<type_identity_t<Char>> s,
+ const basic_format_specs<Char>& specs, locale_ref)
+ -> OutputIt {
+ check_string_type_spec(specs.type);
+ return write(out, s, specs);
+}
+template <typename Char, typename OutputIt>
+FMT_CONSTEXPR auto write(OutputIt out, const Char* s,
+ const basic_format_specs<Char>& specs, locale_ref)
+ -> OutputIt {
+ return check_cstring_type_spec(specs.type)
+ ? write(out, basic_string_view<Char>(s), specs, {})
+ : write_ptr<Char>(out, to_uintptr(s), &specs);
+}
+
+template <typename Char, typename OutputIt>
+FMT_CONSTEXPR20 auto write_nonfinite(OutputIt out, bool isinf,
+ basic_format_specs<Char> specs,
+ const float_specs& fspecs) -> OutputIt {
+ auto str =
+ isinf ? (fspecs.upper ? "INF" : "inf") : (fspecs.upper ? "NAN" : "nan");
+ constexpr size_t str_size = 3;
+ auto sign = fspecs.sign;
+ auto size = str_size + (sign ? 1 : 0);
+ // Replace '0'-padding with space for non-finite values.
+ const bool is_zero_fill =
+ specs.fill.size() == 1 && *specs.fill.data() == static_cast<Char>('0');
+ if (is_zero_fill) specs.fill[0] = static_cast<Char>(' ');
+ return write_padded(out, specs, size, [=](reserve_iterator<OutputIt> it) {
+ if (sign) *it++ = detail::sign<Char>(sign);
+ return copy_str<Char>(str, str + str_size, it);
+ });
+}
+
+// A decimal floating-point number significand * pow(10, exp).
+struct big_decimal_fp {
+ const char* significand;
+ int significand_size;
+ int exponent;
+};
+
+constexpr auto get_significand_size(const big_decimal_fp& fp) -> int {
+ return fp.significand_size;
+}
+template <typename T>
+inline auto get_significand_size(const dragonbox::decimal_fp<T>& fp) -> int {
+ return count_digits(fp.significand);
+}
+
+template <typename Char, typename OutputIt>
+constexpr auto write_significand(OutputIt out, const char* significand,
+ int significand_size) -> OutputIt {
+ return copy_str<Char>(significand, significand + significand_size, out);
+}
+template <typename Char, typename OutputIt, typename UInt>
+inline auto write_significand(OutputIt out, UInt significand,
+ int significand_size) -> OutputIt {
+ return format_decimal<Char>(out, significand, significand_size).end;
+}
+template <typename Char, typename OutputIt, typename T, typename Grouping>
+FMT_CONSTEXPR20 auto write_significand(OutputIt out, T significand,
+ int significand_size, int exponent,
+ const Grouping& grouping) -> OutputIt {
+ if (!grouping.separator()) {
+ out = write_significand<Char>(out, significand, significand_size);
+ return detail::fill_n(out, exponent, static_cast<Char>('0'));
+ }
+ auto buffer = memory_buffer();
+ write_significand<char>(appender(buffer), significand, significand_size);
+ detail::fill_n(appender(buffer), exponent, '0');
+ return grouping.apply(out, string_view(buffer.data(), buffer.size()));
+}
+
+template <typename Char, typename UInt,
+ FMT_ENABLE_IF(std::is_integral<UInt>::value)>
+inline auto write_significand(Char* out, UInt significand, int significand_size,
+ int integral_size, Char decimal_point) -> Char* {
+ if (!decimal_point)
+ return format_decimal(out, significand, significand_size).end;
+ out += significand_size + 1;
+ Char* end = out;
+ int floating_size = significand_size - integral_size;
+ for (int i = floating_size / 2; i > 0; --i) {
+ out -= 2;
+ copy2(out, digits2(significand % 100));
+ significand /= 100;
+ }
+ if (floating_size % 2 != 0) {
+ *--out = static_cast<Char>('0' + significand % 10);
+ significand /= 10;
+ }
+ *--out = decimal_point;
+ format_decimal(out - integral_size, significand, integral_size);
+ return end;
+}
+
+template <typename OutputIt, typename UInt, typename Char,
+ FMT_ENABLE_IF(!std::is_pointer<remove_cvref_t<OutputIt>>::value)>
+inline auto write_significand(OutputIt out, UInt significand,
+ int significand_size, int integral_size,
+ Char decimal_point) -> OutputIt {
+ // Buffer is large enough to hold digits (digits10 + 1) and a decimal point.
+ Char buffer[digits10<UInt>() + 2];
+ auto end = write_significand(buffer, significand, significand_size,
+ integral_size, decimal_point);
+ return detail::copy_str_noinline<Char>(buffer, end, out);
+}
+
+template <typename OutputIt, typename Char>
+FMT_CONSTEXPR auto write_significand(OutputIt out, const char* significand,
+ int significand_size, int integral_size,
+ Char decimal_point) -> OutputIt {
+ out = detail::copy_str_noinline<Char>(significand,
+ significand + integral_size, out);
+ if (!decimal_point) return out;
+ *out++ = decimal_point;
+ return detail::copy_str_noinline<Char>(significand + integral_size,
+ significand + significand_size, out);
+}
+
+template <typename OutputIt, typename Char, typename T, typename Grouping>
+FMT_CONSTEXPR20 auto write_significand(OutputIt out, T significand,
+ int significand_size, int integral_size,
+ Char decimal_point,
+ const Grouping& grouping) -> OutputIt {
+ if (!grouping.separator()) {
+ return write_significand(out, significand, significand_size, integral_size,
+ decimal_point);
+ }
+ auto buffer = basic_memory_buffer<Char>();
+ write_significand(buffer_appender<Char>(buffer), significand,
+ significand_size, integral_size, decimal_point);
+ grouping.apply(
+ out, basic_string_view<Char>(buffer.data(), to_unsigned(integral_size)));
+ return detail::copy_str_noinline<Char>(buffer.data() + integral_size,
+ buffer.end(), out);
+}
+
+template <typename OutputIt, typename DecimalFP, typename Char,
+ typename Grouping = digit_grouping<Char>>
+FMT_CONSTEXPR20 auto do_write_float(OutputIt out, const DecimalFP& fp,
+ const basic_format_specs<Char>& specs,
+ float_specs fspecs, locale_ref loc)
+ -> OutputIt {
+ auto significand = fp.significand;
+ int significand_size = get_significand_size(fp);
+ constexpr Char zero = static_cast<Char>('0');
+ auto sign = fspecs.sign;
+ size_t size = to_unsigned(significand_size) + (sign ? 1 : 0);
+ using iterator = reserve_iterator<OutputIt>;
+
+ Char decimal_point =
+ fspecs.locale ? detail::decimal_point<Char>(loc) : static_cast<Char>('.');
+
+ int output_exp = fp.exponent + significand_size - 1;
+ auto use_exp_format = [=]() {
+ if (fspecs.format == float_format::exp) return true;
+ if (fspecs.format != float_format::general) return false;
+ // Use the fixed notation if the exponent is in [exp_lower, exp_upper),
+ // e.g. 0.0001 instead of 1e-04. Otherwise use the exponent notation.
+ const int exp_lower = -4, exp_upper = 16;
+ return output_exp < exp_lower ||
+ output_exp >= (fspecs.precision > 0 ? fspecs.precision : exp_upper);
+ };
+ if (use_exp_format()) {
+ int num_zeros = 0;
+ if (fspecs.showpoint) {
+ num_zeros = fspecs.precision - significand_size;
+ if (num_zeros < 0) num_zeros = 0;
+ size += to_unsigned(num_zeros);
+ } else if (significand_size == 1) {
+ decimal_point = Char();
+ }
+ auto abs_output_exp = output_exp >= 0 ? output_exp : -output_exp;
+ int exp_digits = 2;
+ if (abs_output_exp >= 100) exp_digits = abs_output_exp >= 1000 ? 4 : 3;
+
+ size += to_unsigned((decimal_point ? 1 : 0) + 2 + exp_digits);
+ char exp_char = fspecs.upper ? 'E' : 'e';
+ auto write = [=](iterator it) {
+ if (sign) *it++ = detail::sign<Char>(sign);
+ // Insert a decimal point after the first digit and add an exponent.
+ it = write_significand(it, significand, significand_size, 1,
+ decimal_point);
+ if (num_zeros > 0) it = detail::fill_n(it, num_zeros, zero);
+ *it++ = static_cast<Char>(exp_char);
+ return write_exponent<Char>(output_exp, it);
+ };
+ return specs.width > 0 ? write_padded<align::right>(out, specs, size, write)
+ : base_iterator(out, write(reserve(out, size)));
+ }
+
+ int exp = fp.exponent + significand_size;
+ if (fp.exponent >= 0) {
+ // 1234e5 -> 123400000[.0+]
+ size += to_unsigned(fp.exponent);
+ int num_zeros = fspecs.precision - exp;
+#ifdef FMT_FUZZ
+ if (num_zeros > 5000)
+ throw std::runtime_error("fuzz mode - avoiding excessive cpu use");
+#endif
+ if (fspecs.showpoint) {
+ if (num_zeros <= 0 && fspecs.format != float_format::fixed) num_zeros = 1;
+ if (num_zeros > 0) size += to_unsigned(num_zeros) + 1;
+ }
+ auto grouping = Grouping(loc, fspecs.locale);
+ size += to_unsigned(grouping.count_separators(significand_size));
+ return write_padded<align::right>(out, specs, size, [&](iterator it) {
+ if (sign) *it++ = detail::sign<Char>(sign);
+ it = write_significand<Char>(it, significand, significand_size,
+ fp.exponent, grouping);
+ if (!fspecs.showpoint) return it;
+ *it++ = decimal_point;
+ return num_zeros > 0 ? detail::fill_n(it, num_zeros, zero) : it;
+ });
+ } else if (exp > 0) {
+ // 1234e-2 -> 12.34[0+]
+ int num_zeros = fspecs.showpoint ? fspecs.precision - significand_size : 0;
+ size += 1 + to_unsigned(num_zeros > 0 ? num_zeros : 0);
+ auto grouping = Grouping(loc, fspecs.locale);
+ size += to_unsigned(grouping.count_separators(significand_size));
+ return write_padded<align::right>(out, specs, size, [&](iterator it) {
+ if (sign) *it++ = detail::sign<Char>(sign);
+ it = write_significand(it, significand, significand_size, exp,
+ decimal_point, grouping);
+ return num_zeros > 0 ? detail::fill_n(it, num_zeros, zero) : it;
+ });
+ }
+ // 1234e-6 -> 0.001234
+ int num_zeros = -exp;
+ if (significand_size == 0 && fspecs.precision >= 0 &&
+ fspecs.precision < num_zeros) {
+ num_zeros = fspecs.precision;
+ }
+ bool pointy = num_zeros != 0 || significand_size != 0 || fspecs.showpoint;
+ size += 1 + (pointy ? 1 : 0) + to_unsigned(num_zeros);
+ return write_padded<align::right>(out, specs, size, [&](iterator it) {
+ if (sign) *it++ = detail::sign<Char>(sign);
+ *it++ = zero;
+ if (!pointy) return it;
+ *it++ = decimal_point;
+ it = detail::fill_n(it, num_zeros, zero);
+ return write_significand<Char>(it, significand, significand_size);
+ });
+}
+
+template <typename Char> class fallback_digit_grouping {
+ public:
+ constexpr fallback_digit_grouping(locale_ref, bool) {}
+
+ constexpr Char separator() const { return Char(); }
+
+ constexpr int count_separators(int) const { return 0; }
+
+ template <typename Out, typename C>
+ constexpr Out apply(Out out, basic_string_view<C>) const {
+ return out;
+ }
+};
+
+template <typename OutputIt, typename DecimalFP, typename Char>
+FMT_CONSTEXPR20 auto write_float(OutputIt out, const DecimalFP& fp,
+ const basic_format_specs<Char>& specs,
+ float_specs fspecs, locale_ref loc)
+ -> OutputIt {
+ if (is_constant_evaluated()) {
+ return do_write_float<OutputIt, DecimalFP, Char,
+ fallback_digit_grouping<Char>>(out, fp, specs, fspecs,
+ loc);
+ } else {
+ return do_write_float(out, fp, specs, fspecs, loc);
+ }
+}
+
+template <typename T, FMT_ENABLE_IF(std::is_floating_point<T>::value)>
+FMT_CONSTEXPR20 bool isinf(T value) {
+ if (is_constant_evaluated()) {
+#if defined(__cpp_if_constexpr)
+ if constexpr (std::numeric_limits<double>::is_iec559) {
+ auto bits = detail::bit_cast<uint64_t>(static_cast<double>(value));
+ constexpr auto significand_bits =
+ dragonbox::float_info<double>::significand_bits;
+ return (bits & exponent_mask<double>()) &&
+ !(bits & ((uint64_t(1) << significand_bits) - 1));
+ }
+#endif
+ }
+ return std::isinf(value);
+}
+
+template <typename T, FMT_ENABLE_IF(std::is_floating_point<T>::value)>
+FMT_CONSTEXPR20 bool isfinite(T value) {
+ if (is_constant_evaluated()) {
+#if defined(__cpp_if_constexpr)
+ if constexpr (std::numeric_limits<double>::is_iec559) {
+ auto bits = detail::bit_cast<uint64_t>(static_cast<double>(value));
+ return (bits & exponent_mask<double>()) != exponent_mask<double>();
+ }
+#endif
+ }
+ return std::isfinite(value);
+}
+
+template <typename T, FMT_ENABLE_IF(std::is_floating_point<T>::value)>
+FMT_INLINE FMT_CONSTEXPR bool signbit(T value) {
+ if (is_constant_evaluated()) {
+#ifdef __cpp_if_constexpr
+ if constexpr (std::numeric_limits<double>::is_iec559) {
+ auto bits = detail::bit_cast<uint64_t>(static_cast<double>(value));
+ return (bits & (uint64_t(1) << (num_bits<uint64_t>() - 1))) != 0;
+ }
+#endif
+ }
+ return std::signbit(value);
+}
+
+template <typename Char, typename OutputIt, typename T,
+ FMT_ENABLE_IF(std::is_floating_point<T>::value)>
+FMT_CONSTEXPR20 auto write(OutputIt out, T value,
+ basic_format_specs<Char> specs, locale_ref loc = {})
+ -> OutputIt {
+ if (const_check(!is_supported_floating_point(value))) return out;
+ float_specs fspecs = parse_float_type_spec(specs);
+ fspecs.sign = specs.sign;
+ if (detail::signbit(value)) { // value < 0 is false for NaN so use signbit.
+ fspecs.sign = sign::minus;
+ value = -value;
+ } else if (fspecs.sign == sign::minus) {
+ fspecs.sign = sign::none;
+ }
+
+ if (!detail::isfinite(value))
+ return write_nonfinite(out, detail::isinf(value), specs, fspecs);
+
+ if (specs.align == align::numeric && fspecs.sign) {
+ auto it = reserve(out, 1);
+ *it++ = detail::sign<Char>(fspecs.sign);
+ out = base_iterator(out, it);
+ fspecs.sign = sign::none;
+ if (specs.width != 0) --specs.width;
+ }
+
+ memory_buffer buffer;
+ if (fspecs.format == float_format::hex) {
+ if (fspecs.sign) buffer.push_back(detail::sign<char>(fspecs.sign));
+ snprintf_float(promote_float(value), specs.precision, fspecs, buffer);
+ return write_bytes<align::right>(out, {buffer.data(), buffer.size()},
+ specs);
+ }
+ int precision = specs.precision >= 0 || specs.type == presentation_type::none
+ ? specs.precision
+ : 6;
+ if (fspecs.format == float_format::exp) {
+ if (precision == max_value<int>())
+ throw_format_error("number is too big");
+ else
+ ++precision;
+ }
+ if (const_check(std::is_same<T, float>())) fspecs.binary32 = true;
+ if (!is_fast_float<T>()) fspecs.fallback = true;
+ int exp = format_float(promote_float(value), precision, fspecs, buffer);
+ fspecs.precision = precision;
+ auto fp = big_decimal_fp{buffer.data(), static_cast<int>(buffer.size()), exp};
+ return write_float(out, fp, specs, fspecs, loc);
+}
+
+template <typename Char, typename OutputIt, typename T,
+ FMT_ENABLE_IF(is_fast_float<T>::value)>
+FMT_CONSTEXPR20 auto write(OutputIt out, T value) -> OutputIt {
+ if (is_constant_evaluated()) {
+ return write(out, value, basic_format_specs<Char>());
+ }
+
+ if (const_check(!is_supported_floating_point(value))) return out;
+
+ using floaty = conditional_t<std::is_same<T, long double>::value, double, T>;
+ using uint = typename dragonbox::float_info<floaty>::carrier_uint;
+ auto bits = bit_cast<uint>(value);
+
+ auto fspecs = float_specs();
+ if (detail::signbit(value)) {
+ fspecs.sign = sign::minus;
+ value = -value;
+ }
+
+ constexpr auto specs = basic_format_specs<Char>();
+ uint mask = exponent_mask<floaty>();
+ if ((bits & mask) == mask)
+ return write_nonfinite(out, std::isinf(value), specs, fspecs);
+
+ auto dec = dragonbox::to_decimal(static_cast<floaty>(value));
+ return write_float(out, dec, specs, fspecs, {});
+}
+
+template <typename Char, typename OutputIt, typename T,
+ FMT_ENABLE_IF(std::is_floating_point<T>::value &&
+ !is_fast_float<T>::value)>
+inline auto write(OutputIt out, T value) -> OutputIt {
+ return write(out, value, basic_format_specs<Char>());
+}
+
+template <typename Char, typename OutputIt>
+auto write(OutputIt out, monostate, basic_format_specs<Char> = {},
+ locale_ref = {}) -> OutputIt {
+ FMT_ASSERT(false, "");
+ return out;
+}
+
+template <typename Char, typename OutputIt>
+FMT_CONSTEXPR auto write(OutputIt out, basic_string_view<Char> value)
+ -> OutputIt {
+ auto it = reserve(out, value.size());
+ it = copy_str_noinline<Char>(value.begin(), value.end(), it);
+ return base_iterator(out, it);
+}
+
+template <typename Char, typename OutputIt, typename T,
+ FMT_ENABLE_IF(is_string<T>::value)>
+constexpr auto write(OutputIt out, const T& value) -> OutputIt {
+ return write<Char>(out, to_string_view(value));
+}
+
+template <typename Char, typename OutputIt, typename T,
+ FMT_ENABLE_IF(is_integral<T>::value &&
+ !std::is_same<T, bool>::value &&
+ !std::is_same<T, Char>::value)>
+FMT_CONSTEXPR auto write(OutputIt out, T value) -> OutputIt {
+ auto abs_value = static_cast<uint32_or_64_or_128_t<T>>(value);
+ bool negative = is_negative(value);
+ // Don't do -abs_value since it trips unsigned-integer-overflow sanitizer.
+ if (negative) abs_value = ~abs_value + 1;
+ int num_digits = count_digits(abs_value);
+ auto size = (negative ? 1 : 0) + static_cast<size_t>(num_digits);
+ auto it = reserve(out, size);
+ if (auto ptr = to_pointer<Char>(it, size)) {
+ if (negative) *ptr++ = static_cast<Char>('-');
+ format_decimal<Char>(ptr, abs_value, num_digits);
+ return out;
+ }
+ if (negative) *it++ = static_cast<Char>('-');
+ it = format_decimal<Char>(it, abs_value, num_digits).end;
+ return base_iterator(out, it);
+}
+
+// FMT_ENABLE_IF() condition separated to workaround an MSVC bug.
+template <
+ typename Char, typename OutputIt, typename T,
+ bool check =
+ std::is_enum<T>::value && !std::is_same<T, Char>::value &&
+ mapped_type_constant<T, basic_format_context<OutputIt, Char>>::value !=
+ type::custom_type,
+ FMT_ENABLE_IF(check)>
+FMT_CONSTEXPR auto write(OutputIt out, T value) -> OutputIt {
+ return write<Char>(
+ out, static_cast<typename std::underlying_type<T>::type>(value));
+}
+
+template <typename Char, typename OutputIt, typename T,
+ FMT_ENABLE_IF(std::is_same<T, bool>::value)>
+FMT_CONSTEXPR auto write(OutputIt out, T value,
+ const basic_format_specs<Char>& specs = {},
+ locale_ref = {}) -> OutputIt {
+ return specs.type != presentation_type::none &&
+ specs.type != presentation_type::string
+ ? write(out, value ? 1 : 0, specs, {})
+ : write_bytes(out, value ? "true" : "false", specs);
+}
+
+template <typename Char, typename OutputIt>
+FMT_CONSTEXPR auto write(OutputIt out, Char value) -> OutputIt {
+ auto it = reserve(out, 1);
+ *it++ = value;
+ return base_iterator(out, it);
+}
+
+template <typename Char, typename OutputIt>
+FMT_CONSTEXPR_CHAR_TRAITS auto write(OutputIt out, const Char* value)
+ -> OutputIt {
+ if (!value) {
+ throw_format_error("string pointer is null");
+ } else {
+ out = write(out, basic_string_view<Char>(value));
+ }
+ return out;
+}
+
+template <typename Char, typename OutputIt, typename T,
+ FMT_ENABLE_IF(std::is_same<T, void>::value)>
+auto write(OutputIt out, const T* value,
+ const basic_format_specs<Char>& specs = {}, locale_ref = {})
+ -> OutputIt {
+ check_pointer_type_spec(specs.type, error_handler());
+ return write_ptr<Char>(out, to_uintptr(value), &specs);
+}
+
+// A write overload that handles implicit conversions.
+template <typename Char, typename OutputIt, typename T,
+ typename Context = basic_format_context<OutputIt, Char>>
+FMT_CONSTEXPR auto write(OutputIt out, const T& value) -> enable_if_t<
+ std::is_class<T>::value && !is_string<T>::value &&
+ !std::is_same<T, Char>::value &&
+ !std::is_same<const T&,
+ decltype(arg_mapper<Context>().map(value))>::value,
+ OutputIt> {
+ return write<Char>(out, arg_mapper<Context>().map(value));
+}
+
+template <typename Char, typename OutputIt, typename T,
+ typename Context = basic_format_context<OutputIt, Char>>
+FMT_CONSTEXPR auto write(OutputIt out, const T& value)
+ -> enable_if_t<mapped_type_constant<T, Context>::value == type::custom_type,
+ OutputIt> {
+ using formatter_type =
+ conditional_t<has_formatter<T, Context>::value,
+ typename Context::template formatter_type<T>,
+ fallback_formatter<T, Char>>;
+ auto ctx = Context(out, {}, {});
+ return formatter_type().format(value, ctx);
+}
+
+// An argument visitor that formats the argument and writes it via the output
+// iterator. It's a class and not a generic lambda for compatibility with C++11.
+template <typename Char> struct default_arg_formatter {
+ using iterator = buffer_appender<Char>;
+ using context = buffer_context<Char>;
+
+ iterator out;
+ basic_format_args<context> args;
+ locale_ref loc;
+
+ template <typename T> auto operator()(T value) -> iterator {
+ return write<Char>(out, value);
+ }
+ auto operator()(typename basic_format_arg<context>::handle h) -> iterator {
+ basic_format_parse_context<Char> parse_ctx({});
+ context format_ctx(out, args, loc);
+ h.format(parse_ctx, format_ctx);
+ return format_ctx.out();
+ }
+};
+
+template <typename Char> struct arg_formatter {
+ using iterator = buffer_appender<Char>;
+ using context = buffer_context<Char>;
+
+ iterator out;
+ const basic_format_specs<Char>& specs;
+ locale_ref locale;
+
+ template <typename T>
+ FMT_CONSTEXPR FMT_INLINE auto operator()(T value) -> iterator {
+ return detail::write(out, value, specs, locale);
+ }
+ auto operator()(typename basic_format_arg<context>::handle) -> iterator {
+ // User-defined types are handled separately because they require access
+ // to the parse context.
+ return out;
+ }
+};
+
+template <typename Char> struct custom_formatter {
+ basic_format_parse_context<Char>& parse_ctx;
+ buffer_context<Char>& ctx;
+
+ void operator()(
+ typename basic_format_arg<buffer_context<Char>>::handle h) const {
+ h.format(parse_ctx, ctx);
+ }
+ template <typename T> void operator()(T) const {}
+};
+
+template <typename T>
+using is_integer =
+ bool_constant<is_integral<T>::value && !std::is_same<T, bool>::value &&
+ !std::is_same<T, char>::value &&
+ !std::is_same<T, wchar_t>::value>;
+
+template <typename ErrorHandler> class width_checker {
+ public:
+ explicit FMT_CONSTEXPR width_checker(ErrorHandler& eh) : handler_(eh) {}
+
+ template <typename T, FMT_ENABLE_IF(is_integer<T>::value)>
+ FMT_CONSTEXPR auto operator()(T value) -> unsigned long long {
+ if (is_negative(value)) handler_.on_error("negative width");
+ return static_cast<unsigned long long>(value);
+ }
+
+ template <typename T, FMT_ENABLE_IF(!is_integer<T>::value)>
+ FMT_CONSTEXPR auto operator()(T) -> unsigned long long {
+ handler_.on_error("width is not integer");
+ return 0;
+ }
+
+ private:
+ ErrorHandler& handler_;
+};
+
+template <typename ErrorHandler> class precision_checker {
+ public:
+ explicit FMT_CONSTEXPR precision_checker(ErrorHandler& eh) : handler_(eh) {}
+
+ template <typename T, FMT_ENABLE_IF(is_integer<T>::value)>
+ FMT_CONSTEXPR auto operator()(T value) -> unsigned long long {
+ if (is_negative(value)) handler_.on_error("negative precision");
+ return static_cast<unsigned long long>(value);
+ }
+
+ template <typename T, FMT_ENABLE_IF(!is_integer<T>::value)>
+ FMT_CONSTEXPR auto operator()(T) -> unsigned long long {
+ handler_.on_error("precision is not integer");
+ return 0;
+ }
+
+ private:
+ ErrorHandler& handler_;
+};
+
+template <template <typename> class Handler, typename FormatArg,
+ typename ErrorHandler>
+FMT_CONSTEXPR auto get_dynamic_spec(FormatArg arg, ErrorHandler eh) -> int {
+ unsigned long long value = visit_format_arg(Handler<ErrorHandler>(eh), arg);
+ if (value > to_unsigned(max_value<int>())) eh.on_error("number is too big");
+ return static_cast<int>(value);
+}
+
+template <typename Context, typename ID>
+FMT_CONSTEXPR auto get_arg(Context& ctx, ID id) ->
+ typename Context::format_arg {
+ auto arg = ctx.arg(id);
+ if (!arg) ctx.on_error("argument not found");
+ return arg;
+}
+
+// The standard format specifier handler with checking.
+template <typename Char> class specs_handler : public specs_setter<Char> {
+ private:
+ basic_format_parse_context<Char>& parse_context_;
+ buffer_context<Char>& context_;
+
+ // This is only needed for compatibility with gcc 4.4.
+ using format_arg = basic_format_arg<buffer_context<Char>>;
+
+ FMT_CONSTEXPR auto get_arg(auto_id) -> format_arg {
+ return detail::get_arg(context_, parse_context_.next_arg_id());
+ }
+
+ FMT_CONSTEXPR auto get_arg(int arg_id) -> format_arg {
+ parse_context_.check_arg_id(arg_id);
+ return detail::get_arg(context_, arg_id);
+ }
+
+ FMT_CONSTEXPR auto get_arg(basic_string_view<Char> arg_id) -> format_arg {
+ parse_context_.check_arg_id(arg_id);
+ return detail::get_arg(context_, arg_id);
+ }
+
+ public:
+ FMT_CONSTEXPR specs_handler(basic_format_specs<Char>& specs,
+ basic_format_parse_context<Char>& parse_ctx,
+ buffer_context<Char>& ctx)
+ : specs_setter<Char>(specs), parse_context_(parse_ctx), context_(ctx) {}
+
+ template <typename Id> FMT_CONSTEXPR void on_dynamic_width(Id arg_id) {
+ this->specs_.width = get_dynamic_spec<width_checker>(
+ get_arg(arg_id), context_.error_handler());
+ }
+
+ template <typename Id> FMT_CONSTEXPR void on_dynamic_precision(Id arg_id) {
+ this->specs_.precision = get_dynamic_spec<precision_checker>(
+ get_arg(arg_id), context_.error_handler());
+ }
+
+ void on_error(const char* message) { context_.on_error(message); }
+};
+
+template <template <typename> class Handler, typename Context>
+FMT_CONSTEXPR void handle_dynamic_spec(int& value,
+ arg_ref<typename Context::char_type> ref,
+ Context& ctx) {
+ switch (ref.kind) {
+ case arg_id_kind::none:
+ break;
+ case arg_id_kind::index:
+ value = detail::get_dynamic_spec<Handler>(ctx.arg(ref.val.index),
+ ctx.error_handler());
+ break;
+ case arg_id_kind::name:
+ value = detail::get_dynamic_spec<Handler>(ctx.arg(ref.val.name),
+ ctx.error_handler());
+ break;
+ }
+}
+
+#define FMT_STRING_IMPL(s, base, explicit) \
+ [] { \
+ /* Use the hidden visibility as a workaround for a GCC bug (#1973). */ \
+ /* Use a macro-like name to avoid shadowing warnings. */ \
+ struct FMT_GCC_VISIBILITY_HIDDEN FMT_COMPILE_STRING : base { \
+ using char_type = fmt::remove_cvref_t<decltype(s[0])>; \
+ FMT_MAYBE_UNUSED FMT_CONSTEXPR explicit \
+ operator fmt::basic_string_view<char_type>() const { \
+ return fmt::detail_exported::compile_string_to_view<char_type>(s); \
+ } \
+ }; \
+ return FMT_COMPILE_STRING(); \
+ }()
+
+/**
+ \rst
+ Constructs a compile-time format string from a string literal *s*.
+
+ **Example**::
+
+ // A compile-time error because 'd' is an invalid specifier for strings.
+ std::string s = fmt::format(FMT_STRING("{:d}"), "foo");
+ \endrst
+ */
+#define FMT_STRING(s) FMT_STRING_IMPL(s, fmt::compile_string, )
+
+#if FMT_USE_USER_DEFINED_LITERALS
+template <typename Char> struct udl_formatter {
+ basic_string_view<Char> str;
+
+ template <typename... T>
+ auto operator()(T&&... args) const -> std::basic_string<Char> {
+ return vformat(str, fmt::make_args_checked<T...>(str, args...));
+ }
+};
+
+# if FMT_USE_NONTYPE_TEMPLATE_PARAMETERS
+template <typename T, typename Char, size_t N,
+ fmt::detail_exported::fixed_string<Char, N> Str>
+struct statically_named_arg : view {
+ static constexpr auto name = Str.data;
+
+ const T& value;
+ statically_named_arg(const T& v) : value(v) {}
+};
+
+template <typename T, typename Char, size_t N,
+ fmt::detail_exported::fixed_string<Char, N> Str>
+struct is_named_arg<statically_named_arg<T, Char, N, Str>> : std::true_type {};
+
+template <typename T, typename Char, size_t N,
+ fmt::detail_exported::fixed_string<Char, N> Str>
+struct is_statically_named_arg<statically_named_arg<T, Char, N, Str>>
+ : std::true_type {};
+
+template <typename Char, size_t N,
+ fmt::detail_exported::fixed_string<Char, N> Str>
+struct udl_arg {
+ template <typename T> auto operator=(T&& value) const {
+ return statically_named_arg<T, Char, N, Str>(std::forward<T>(value));
+ }
+};
+# else
+template <typename Char> struct udl_arg {
+ const Char* str;
+
+ template <typename T> auto operator=(T&& value) const -> named_arg<Char, T> {
+ return {str, std::forward<T>(value)};
+ }
+};
+# endif
+#endif // FMT_USE_USER_DEFINED_LITERALS
+
+template <typename Locale, typename Char>
+auto vformat(const Locale& loc, basic_string_view<Char> format_str,
+ basic_format_args<buffer_context<type_identity_t<Char>>> args)
+ -> std::basic_string<Char> {
+ basic_memory_buffer<Char> buffer;
+ detail::vformat_to(buffer, format_str, args, detail::locale_ref(loc));
+ return {buffer.data(), buffer.size()};
+}
+
+using format_func = void (*)(detail::buffer<char>&, int, const char*);
+
+FMT_API void format_error_code(buffer<char>& out, int error_code,
+ string_view message) FMT_NOEXCEPT;
+
+FMT_API void report_error(format_func func, int error_code,
+ const char* message) FMT_NOEXCEPT;
+FMT_END_DETAIL_NAMESPACE
+
+FMT_API auto vsystem_error(int error_code, string_view format_str,
+ format_args args) -> std::system_error;
+
+/**
+ \rst
+ Constructs :class:`std::system_error` with a message formatted with
+ ``fmt::format(fmt, args...)``.
+ *error_code* is a system error code as given by ``errno``.
+
+ **Example**::
+
+ // This throws std::system_error with the description
+ // cannot open file 'madeup': No such file or directory
+ // or similar (system message may vary).
+ const char* filename = "madeup";
+ std::FILE* file = std::fopen(filename, "r");
+ if (!file)
+ throw fmt::system_error(errno, "cannot open file '{}'", filename);
+ \endrst
+*/
+template <typename... T>
+auto system_error(int error_code, format_string<T...> fmt, T&&... args)
+ -> std::system_error {
+ return vsystem_error(error_code, fmt, fmt::make_format_args(args...));
+}
+
+/**
+ \rst
+ Formats an error message for an error returned by an operating system or a
+ language runtime, for example a file opening error, and writes it to *out*.
+ The format is the same as the one used by ``std::system_error(ec, message)``
+ where ``ec`` is ``std::error_code(error_code, std::generic_category()})``.
+ It is implementation-defined but normally looks like:
+
+ .. parsed-literal::
+ *<message>*: *<system-message>*
+
+ where *<message>* is the passed message and *<system-message>* is the system
+ message corresponding to the error code.
+ *error_code* is a system error code as given by ``errno``.
+ \endrst
+ */
+FMT_API void format_system_error(detail::buffer<char>& out, int error_code,
+ const char* message) FMT_NOEXCEPT;
+
+// Reports a system error without throwing an exception.
+// Can be used to report errors from destructors.
+FMT_API void report_system_error(int error_code,
+ const char* message) FMT_NOEXCEPT;
+
+/** Fast integer formatter. */
+class format_int {
+ private:
+ // Buffer should be large enough to hold all digits (digits10 + 1),
+ // a sign and a null character.
+ enum { buffer_size = std::numeric_limits<unsigned long long>::digits10 + 3 };
+ mutable char buffer_[buffer_size];
+ char* str_;
+
+ template <typename UInt> auto format_unsigned(UInt value) -> char* {
+ auto n = static_cast<detail::uint32_or_64_or_128_t<UInt>>(value);
+ return detail::format_decimal(buffer_, n, buffer_size - 1).begin;
+ }
+
+ template <typename Int> auto format_signed(Int value) -> char* {
+ auto abs_value = static_cast<detail::uint32_or_64_or_128_t<Int>>(value);
+ bool negative = value < 0;
+ if (negative) abs_value = 0 - abs_value;
+ auto begin = format_unsigned(abs_value);
+ if (negative) *--begin = '-';
+ return begin;
+ }
+
+ public:
+ explicit format_int(int value) : str_(format_signed(value)) {}
+ explicit format_int(long value) : str_(format_signed(value)) {}
+ explicit format_int(long long value) : str_(format_signed(value)) {}
+ explicit format_int(unsigned value) : str_(format_unsigned(value)) {}
+ explicit format_int(unsigned long value) : str_(format_unsigned(value)) {}
+ explicit format_int(unsigned long long value)
+ : str_(format_unsigned(value)) {}
+
+ /** Returns the number of characters written to the output buffer. */
+ auto size() const -> size_t {
+ return detail::to_unsigned(buffer_ - str_ + buffer_size - 1);
+ }
+
+ /**
+ Returns a pointer to the output buffer content. No terminating null
+ character is appended.
+ */
+ auto data() const -> const char* { return str_; }
+
+ /**
+ Returns a pointer to the output buffer content with terminating null
+ character appended.
+ */
+ auto c_str() const -> const char* {
+ buffer_[buffer_size - 1] = '\0';
+ return str_;
+ }
+
+ /**
+ \rst
+ Returns the content of the output buffer as an ``std::string``.
+ \endrst
+ */
+ auto str() const -> std::string { return std::string(str_, size()); }
+};
+
+template <typename T, typename Char>
+template <typename FormatContext>
+FMT_CONSTEXPR FMT_INLINE auto
+formatter<T, Char,
+ enable_if_t<detail::type_constant<T, Char>::value !=
+ detail::type::custom_type>>::format(const T& val,
+ FormatContext& ctx)
+ const -> decltype(ctx.out()) {
+ if (specs_.width_ref.kind != detail::arg_id_kind::none ||
+ specs_.precision_ref.kind != detail::arg_id_kind::none) {
+ auto specs = specs_;
+ detail::handle_dynamic_spec<detail::width_checker>(specs.width,
+ specs.width_ref, ctx);
+ detail::handle_dynamic_spec<detail::precision_checker>(
+ specs.precision, specs.precision_ref, ctx);
+ return detail::write<Char>(ctx.out(), val, specs, ctx.locale());
+ }
+ return detail::write<Char>(ctx.out(), val, specs_, ctx.locale());
+}
+
+#define FMT_FORMAT_AS(Type, Base) \
+ template <typename Char> \
+ struct formatter<Type, Char> : formatter<Base, Char> { \
+ template <typename FormatContext> \
+ auto format(Type const& val, FormatContext& ctx) const \
+ -> decltype(ctx.out()) { \
+ return formatter<Base, Char>::format(static_cast<Base>(val), ctx); \
+ } \
+ }
+
+FMT_FORMAT_AS(signed char, int);
+FMT_FORMAT_AS(unsigned char, unsigned);
+FMT_FORMAT_AS(short, int);
+FMT_FORMAT_AS(unsigned short, unsigned);
+FMT_FORMAT_AS(long, long long);
+FMT_FORMAT_AS(unsigned long, unsigned long long);
+FMT_FORMAT_AS(Char*, const Char*);
+FMT_FORMAT_AS(std::basic_string<Char>, basic_string_view<Char>);
+FMT_FORMAT_AS(std::nullptr_t, const void*);
+FMT_FORMAT_AS(detail::byte, unsigned char);
+FMT_FORMAT_AS(detail::std_string_view<Char>, basic_string_view<Char>);
+
+template <typename Char>
+struct formatter<void*, Char> : formatter<const void*, Char> {
+ template <typename FormatContext>
+ auto format(void* val, FormatContext& ctx) const -> decltype(ctx.out()) {
+ return formatter<const void*, Char>::format(val, ctx);
+ }
+};
+
+template <typename Char, size_t N>
+struct formatter<Char[N], Char> : formatter<basic_string_view<Char>, Char> {
+ template <typename FormatContext>
+ FMT_CONSTEXPR auto format(const Char* val, FormatContext& ctx) const
+ -> decltype(ctx.out()) {
+ return formatter<basic_string_view<Char>, Char>::format(val, ctx);
+ }
+};
+
+// A formatter for types known only at run time such as variant alternatives.
+//
+// Usage:
+// using variant = std::variant<int, std::string>;
+// template <>
+// struct formatter<variant>: dynamic_formatter<> {
+// auto format(const variant& v, format_context& ctx) {
+// return visit([&](const auto& val) {
+// return dynamic_formatter<>::format(val, ctx);
+// }, v);
+// }
+// };
+template <typename Char = char> class dynamic_formatter {
+ private:
+ detail::dynamic_format_specs<Char> specs_;
+ const Char* format_str_;
+
+ struct null_handler : detail::error_handler {
+ void on_align(align_t) {}
+ void on_sign(sign_t) {}
+ void on_hash() {}
+ };
+
+ template <typename Context> void handle_specs(Context& ctx) {
+ detail::handle_dynamic_spec<detail::width_checker>(specs_.width,
+ specs_.width_ref, ctx);
+ detail::handle_dynamic_spec<detail::precision_checker>(
+ specs_.precision, specs_.precision_ref, ctx);
+ }
+
+ public:
+ template <typename ParseContext>
+ FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
+ format_str_ = ctx.begin();
+ // Checks are deferred to formatting time when the argument type is known.
+ detail::dynamic_specs_handler<ParseContext> handler(specs_, ctx);
+ return detail::parse_format_specs(ctx.begin(), ctx.end(), handler);
+ }
+
+ template <typename T, typename FormatContext>
+ auto format(const T& val, FormatContext& ctx) -> decltype(ctx.out()) {
+ handle_specs(ctx);
+ detail::specs_checker<null_handler> checker(
+ null_handler(), detail::mapped_type_constant<T, FormatContext>::value);
+ checker.on_align(specs_.align);
+ if (specs_.sign != sign::none) checker.on_sign(specs_.sign);
+ if (specs_.alt) checker.on_hash();
+ if (specs_.precision >= 0) checker.end_precision();
+ return detail::write<Char>(ctx.out(), val, specs_, ctx.locale());
+ }
+};
+
+/**
+ \rst
+ Converts ``p`` to ``const void*`` for pointer formatting.
+
+ **Example**::
+
+ auto s = fmt::format("{}", fmt::ptr(p));
+ \endrst
+ */
+template <typename T> auto ptr(T p) -> const void* {
+ static_assert(std::is_pointer<T>::value, "");
+ return detail::bit_cast<const void*>(p);
+}
+template <typename T> auto ptr(const std::unique_ptr<T>& p) -> const void* {
+ return p.get();
+}
+template <typename T> auto ptr(const std::shared_ptr<T>& p) -> const void* {
+ return p.get();
+}
+
+class bytes {
+ private:
+ string_view data_;
+ friend struct formatter<bytes>;
+
+ public:
+ explicit bytes(string_view data) : data_(data) {}
+};
+
+template <> struct formatter<bytes> {
+ private:
+ detail::dynamic_format_specs<char> specs_;
+
+ public:
+ template <typename ParseContext>
+ FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
+ using handler_type = detail::dynamic_specs_handler<ParseContext>;
+ detail::specs_checker<handler_type> handler(handler_type(specs_, ctx),
+ detail::type::string_type);
+ auto it = parse_format_specs(ctx.begin(), ctx.end(), handler);
+ detail::check_string_type_spec(specs_.type, ctx.error_handler());
+ return it;
+ }
+
+ template <typename FormatContext>
+ auto format(bytes b, FormatContext& ctx) -> decltype(ctx.out()) {
+ detail::handle_dynamic_spec<detail::width_checker>(specs_.width,
+ specs_.width_ref, ctx);
+ detail::handle_dynamic_spec<detail::precision_checker>(
+ specs_.precision, specs_.precision_ref, ctx);
+ return detail::write_bytes(ctx.out(), b.data_, specs_);
+ }
+};
+
+// group_digits_view is not derived from view because it copies the argument.
+template <typename T> struct group_digits_view { T value; };
+
+/**
+ \rst
+ Returns a view that formats an integer value using ',' as a locale-independent
+ thousands separator.
+
+ **Example**::
+
+ fmt::print("{}", fmt::group_digits(12345));
+ // Output: "12,345"
+ \endrst
+ */
+template <typename T> auto group_digits(T value) -> group_digits_view<T> {
+ return {value};
+}
+
+template <typename T> struct formatter<group_digits_view<T>> : formatter<T> {
+ private:
+ detail::dynamic_format_specs<char> specs_;
+
+ public:
+ template <typename ParseContext>
+ FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
+ using handler_type = detail::dynamic_specs_handler<ParseContext>;
+ detail::specs_checker<handler_type> handler(handler_type(specs_, ctx),
+ detail::type::int_type);
+ auto it = parse_format_specs(ctx.begin(), ctx.end(), handler);
+ detail::check_string_type_spec(specs_.type, ctx.error_handler());
+ return it;
+ }
+
+ template <typename FormatContext>
+ auto format(group_digits_view<T> t, FormatContext& ctx)
+ -> decltype(ctx.out()) {
+ detail::handle_dynamic_spec<detail::width_checker>(specs_.width,
+ specs_.width_ref, ctx);
+ detail::handle_dynamic_spec<detail::precision_checker>(
+ specs_.precision, specs_.precision_ref, ctx);
+ return detail::write_int_localized(
+ ctx.out(), static_cast<detail::uint64_or_128_t<T>>(t.value), 0, specs_,
+ detail::digit_grouping<char>({"\3", ','}));
+ }
+};
+
+template <typename It, typename Sentinel, typename Char = char>
+struct join_view : detail::view {
+ It begin;
+ Sentinel end;
+ basic_string_view<Char> sep;
+
+ join_view(It b, Sentinel e, basic_string_view<Char> s)
+ : begin(b), end(e), sep(s) {}
+};
+
+template <typename It, typename Sentinel, typename Char>
+using arg_join FMT_DEPRECATED_ALIAS = join_view<It, Sentinel, Char>;
+
+template <typename It, typename Sentinel, typename Char>
+struct formatter<join_view<It, Sentinel, Char>, Char> {
+ private:
+ using value_type =
+#ifdef __cpp_lib_ranges
+ std::iter_value_t<It>;
+#else
+ typename std::iterator_traits<It>::value_type;
+#endif
+ using context = buffer_context<Char>;
+ using mapper = detail::arg_mapper<context>;
+
+ template <typename T, FMT_ENABLE_IF(has_formatter<T, context>::value)>
+ static auto map(const T& value) -> const T& {
+ return value;
+ }
+ template <typename T, FMT_ENABLE_IF(!has_formatter<T, context>::value)>
+ static auto map(const T& value) -> decltype(mapper().map(value)) {
+ return mapper().map(value);
+ }
+
+ using formatter_type =
+ conditional_t<is_formattable<value_type, Char>::value,
+ formatter<remove_cvref_t<decltype(map(
+ std::declval<const value_type&>()))>,
+ Char>,
+ detail::fallback_formatter<value_type, Char>>;
+
+ formatter_type value_formatter_;
+
+ public:
+ template <typename ParseContext>
+ FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
+ return value_formatter_.parse(ctx);
+ }
+
+ template <typename FormatContext>
+ auto format(const join_view<It, Sentinel, Char>& value, FormatContext& ctx)
+ -> decltype(ctx.out()) {
+ auto it = value.begin;
+ auto out = ctx.out();
+ if (it != value.end) {
+ out = value_formatter_.format(map(*it), ctx);
+ ++it;
+ while (it != value.end) {
+ out = detail::copy_str<Char>(value.sep.begin(), value.sep.end(), out);
+ ctx.advance_to(out);
+ out = value_formatter_.format(map(*it), ctx);
+ ++it;
+ }
+ }
+ return out;
+ }
+};
+
+/**
+ Returns a view that formats the iterator range `[begin, end)` with elements
+ separated by `sep`.
+ */
+template <typename It, typename Sentinel>
+auto join(It begin, Sentinel end, string_view sep) -> join_view<It, Sentinel> {
+ return {begin, end, sep};
+}
+
+/**
+ \rst
+ Returns a view that formats `range` with elements separated by `sep`.
+
+ **Example**::
+
+ std::vector<int> v = {1, 2, 3};
+ fmt::print("{}", fmt::join(v, ", "));
+ // Output: "1, 2, 3"
+
+ ``fmt::join`` applies passed format specifiers to the range elements::
+
+ fmt::print("{:02}", fmt::join(v, ", "));
+ // Output: "01, 02, 03"
+ \endrst
+ */
+template <typename Range>
+auto join(Range&& range, string_view sep)
+ -> join_view<detail::iterator_t<Range>, detail::sentinel_t<Range>> {
+ return join(std::begin(range), std::end(range), sep);
+}
+
+/**
+ \rst
+ Converts *value* to ``std::string`` using the default format for type *T*.
+
+ **Example**::
+
+ #include <fmt/format.h>
+
+ std::string answer = fmt::to_string(42);
+ \endrst
+ */
+template <typename T, FMT_ENABLE_IF(!std::is_integral<T>::value)>
+inline auto to_string(const T& value) -> std::string {
+ auto result = std::string();
+ detail::write<char>(std::back_inserter(result), value);
+ return result;
+}
+
+template <typename T, FMT_ENABLE_IF(std::is_integral<T>::value)>
+FMT_NODISCARD inline auto to_string(T value) -> std::string {
+ // The buffer should be large enough to store the number including the sign
+ // or "false" for bool.
+ constexpr int max_size = detail::digits10<T>() + 2;
+ char buffer[max_size > 5 ? static_cast<unsigned>(max_size) : 5];
+ char* begin = buffer;
+ return std::string(begin, detail::write<char>(begin, value));
+}
+
+template <typename Char, size_t SIZE>
+FMT_NODISCARD auto to_string(const basic_memory_buffer<Char, SIZE>& buf)
+ -> std::basic_string<Char> {
+ auto size = buf.size();
+ detail::assume(size < std::basic_string<Char>().max_size());
+ return std::basic_string<Char>(buf.data(), size);
+}
+
+FMT_BEGIN_DETAIL_NAMESPACE
+
+template <typename Char>
+void vformat_to(
+ buffer<Char>& buf, basic_string_view<Char> fmt,
+ basic_format_args<FMT_BUFFER_CONTEXT(type_identity_t<Char>)> args,
+ locale_ref loc) {
+ // workaround for msvc bug regarding name-lookup in module
+ // link names into function scope
+ using detail::arg_formatter;
+ using detail::buffer_appender;
+ using detail::custom_formatter;
+ using detail::default_arg_formatter;
+ using detail::get_arg;
+ using detail::locale_ref;
+ using detail::parse_format_specs;
+ using detail::specs_checker;
+ using detail::specs_handler;
+ using detail::to_unsigned;
+ using detail::type;
+ using detail::write;
+ auto out = buffer_appender<Char>(buf);
+ if (fmt.size() == 2 && equal2(fmt.data(), "{}")) {
+ auto arg = args.get(0);
+ if (!arg) error_handler().on_error("argument not found");
+ visit_format_arg(default_arg_formatter<Char>{out, args, loc}, arg);
+ return;
+ }
+
+ struct format_handler : error_handler {
+ basic_format_parse_context<Char> parse_context;
+ buffer_context<Char> context;
+
+ format_handler(buffer_appender<Char> out, basic_string_view<Char> str,
+ basic_format_args<buffer_context<Char>> args, locale_ref loc)
+ : parse_context(str), context(out, args, loc) {}
+
+ void on_text(const Char* begin, const Char* end) {
+ auto text = basic_string_view<Char>(begin, to_unsigned(end - begin));
+ context.advance_to(write<Char>(context.out(), text));
+ }
+
+ FMT_CONSTEXPR auto on_arg_id() -> int {
+ return parse_context.next_arg_id();
+ }
+ FMT_CONSTEXPR auto on_arg_id(int id) -> int {
+ return parse_context.check_arg_id(id), id;
+ }
+ FMT_CONSTEXPR auto on_arg_id(basic_string_view<Char> id) -> int {
+ int arg_id = context.arg_id(id);
+ if (arg_id < 0) on_error("argument not found");
+ return arg_id;
+ }
+
+ FMT_INLINE void on_replacement_field(int id, const Char*) {
+ auto arg = get_arg(context, id);
+ context.advance_to(visit_format_arg(
+ default_arg_formatter<Char>{context.out(), context.args(),
+ context.locale()},
+ arg));
+ }
+
+ auto on_format_specs(int id, const Char* begin, const Char* end)
+ -> const Char* {
+ auto arg = get_arg(context, id);
+ if (arg.type() == type::custom_type) {
+ parse_context.advance_to(parse_context.begin() +
+ (begin - &*parse_context.begin()));
+ visit_format_arg(custom_formatter<Char>{parse_context, context}, arg);
+ return parse_context.begin();
+ }
+ auto specs = basic_format_specs<Char>();
+ specs_checker<specs_handler<Char>> handler(
+ specs_handler<Char>(specs, parse_context, context), arg.type());
+ begin = parse_format_specs(begin, end, handler);
+ if (begin == end || *begin != '}')
+ on_error("missing '}' in format string");
+ auto f = arg_formatter<Char>{context.out(), specs, context.locale()};
+ context.advance_to(visit_format_arg(f, arg));
+ return begin;
+ }
+ };
+ detail::parse_format_string<false>(fmt, format_handler(out, fmt, args, loc));
+}
+
+#ifndef FMT_HEADER_ONLY
+extern template FMT_API auto thousands_sep_impl<char>(locale_ref)
+ -> thousands_sep_result<char>;
+extern template FMT_API auto thousands_sep_impl<wchar_t>(locale_ref)
+ -> thousands_sep_result<wchar_t>;
+extern template FMT_API auto decimal_point_impl(locale_ref) -> char;
+extern template FMT_API auto decimal_point_impl(locale_ref) -> wchar_t;
+extern template auto format_float<double>(double value, int precision,
+ float_specs specs, buffer<char>& buf)
+ -> int;
+extern template auto format_float<long double>(long double value, int precision,
+ float_specs specs,
+ buffer<char>& buf) -> int;
+void snprintf_float(float, int, float_specs, buffer<char>&) = delete;
+extern template auto snprintf_float<double>(double value, int precision,
+ float_specs specs,
+ buffer<char>& buf) -> int;
+extern template auto snprintf_float<long double>(long double value,
+ int precision,
+ float_specs specs,
+ buffer<char>& buf) -> int;
+#endif // FMT_HEADER_ONLY
+
+FMT_END_DETAIL_NAMESPACE
+
+#if FMT_USE_USER_DEFINED_LITERALS
+inline namespace literals {
+/**
+ \rst
+ User-defined literal equivalent of :func:`fmt::arg`.
+
+ **Example**::
+
+ using namespace fmt::literals;
+ fmt::print("Elapsed time: {s:.2f} seconds", "s"_a=1.23);
+ \endrst
+ */
+# if FMT_USE_NONTYPE_TEMPLATE_PARAMETERS
+template <detail_exported::fixed_string Str>
+constexpr auto operator""_a()
+ -> detail::udl_arg<remove_cvref_t<decltype(Str.data[0])>,
+ sizeof(Str.data) / sizeof(decltype(Str.data[0])), Str> {
+ return {};
+}
+# else
+constexpr auto operator"" _a(const char* s, size_t) -> detail::udl_arg<char> {
+ return {s};
+}
+# endif
+
+// DEPRECATED!
+// User-defined literal equivalent of fmt::format.
+FMT_DEPRECATED constexpr auto operator"" _format(const char* s, size_t n)
+ -> detail::udl_formatter<char> {
+ return {{s, n}};
+}
+} // namespace literals
+#endif // FMT_USE_USER_DEFINED_LITERALS
+
+template <typename Locale, FMT_ENABLE_IF(detail::is_locale<Locale>::value)>
+inline auto vformat(const Locale& loc, string_view fmt, format_args args)
+ -> std::string {
+ return detail::vformat(loc, fmt, args);
+}
+
+template <typename Locale, typename... T,
+ FMT_ENABLE_IF(detail::is_locale<Locale>::value)>
+inline auto format(const Locale& loc, format_string<T...> fmt, T&&... args)
+ -> std::string {
+ return vformat(loc, string_view(fmt), fmt::make_format_args(args...));
+}
+
+template <typename... T, size_t SIZE, typename Allocator>
+FMT_DEPRECATED auto format_to(basic_memory_buffer<char, SIZE, Allocator>& buf,
+ format_string<T...> fmt, T&&... args)
+ -> appender {
+ detail::vformat_to(buf, string_view(fmt), fmt::make_format_args(args...));
+ return appender(buf);
+}
+
+template <typename OutputIt, typename Locale,
+ FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, char>::value&&
+ detail::is_locale<Locale>::value)>
+auto vformat_to(OutputIt out, const Locale& loc, string_view fmt,
+ format_args args) -> OutputIt {
+ using detail::get_buffer;
+ auto&& buf = get_buffer<char>(out);
+ detail::vformat_to(buf, fmt, args, detail::locale_ref(loc));
+ return detail::get_iterator(buf);
+}
+
+template <typename OutputIt, typename Locale, typename... T,
+ FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, char>::value&&
+ detail::is_locale<Locale>::value)>
+FMT_INLINE auto format_to(OutputIt out, const Locale& loc,
+ format_string<T...> fmt, T&&... args) -> OutputIt {
+ return vformat_to(out, loc, fmt, fmt::make_format_args(args...));
+}
+
+FMT_MODULE_EXPORT_END
+FMT_END_NAMESPACE
+
+#ifdef FMT_DEPRECATED_INCLUDE_XCHAR
+# include "xchar.h"
+#endif
+
+#ifdef FMT_HEADER_ONLY
+# define FMT_FUNC inline
+# include "format-inl.h"
+#else
+# define FMT_FUNC
+#endif
+
+#endif // FMT_FORMAT_H_
diff --git a/intern/cycles/blender/addon/engine.py b/intern/cycles/blender/addon/engine.py
index 48dd26cc622..b7713dc7110 100644
--- a/intern/cycles/blender/addon/engine.py
+++ b/intern/cycles/blender/addon/engine.py
@@ -228,6 +228,10 @@ def list_render_passes(scene, srl):
else:
yield (aov.name, "RGB", 'COLOR')
+ # Light groups.
+ for lightgroup in srl.lightgroups:
+ yield ("Combined_%s" % lightgroup.name, "RGB", 'COLOR')
+
def register_passes(engine, scene, view_layer):
for name, channelids, channeltype in list_render_passes(scene, view_layer):
diff --git a/intern/cycles/blender/addon/properties.py b/intern/cycles/blender/addon/properties.py
index 24cc5735c96..51b3b3d2bcb 100644
--- a/intern/cycles/blender/addon/properties.py
+++ b/intern/cycles/blender/addon/properties.py
@@ -1012,6 +1012,12 @@ class CyclesLightSettings(bpy.types.PropertyGroup):
"note that this will make the light invisible",
default=False,
)
+ is_caustics_light: BoolProperty(
+ name="Shadow Caustics",
+ description="Generate approximate caustics in shadows of refractive surfaces. "
+ "Lights, caster and receiver objects must have shadow caustics options set to enable this",
+ default=False,
+ )
@classmethod
def register(cls):
@@ -1028,6 +1034,12 @@ class CyclesLightSettings(bpy.types.PropertyGroup):
class CyclesWorldSettings(bpy.types.PropertyGroup):
+ is_caustics_light: BoolProperty(
+ name="Shadow Caustics",
+ description="Generate approximate caustics in shadows of refractive surfaces. "
+ "Lights, caster and receiver objects must have shadow caustics options set to enable this",
+ default=False,
+ )
sampling_method: EnumProperty(
name="Sampling Method",
description="How to sample the background light",
@@ -1226,6 +1238,21 @@ class CyclesObjectSettings(bpy.types.PropertyGroup):
subtype='DISTANCE',
)
+ is_caustics_caster: BoolProperty(
+ name="Cast Shadow Caustics",
+ description="With refractive materials, generate approximate caustics in shadows of this object. "
+ "Up to 10 bounces inside this object are taken into account. Lights, caster and receiver objects "
+ "must have shadow caustics options set to enable this",
+ default=False,
+ )
+
+ is_caustics_receiver: BoolProperty(
+ name="Receive Shadow Caustics",
+ description="Receive approximate caustics from refractive materials in shadows on this object. "
+ "Lights, caster and receiver objects must have shadow caustics options set to enable this",
+ default=False,
+ )
+
@classmethod
def register(cls):
bpy.types.Object.cycles = PointerProperty(
diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py
index 1f50f3da7ae..c97afa86fad 100644
--- a/intern/cycles/blender/addon/ui.py
+++ b/intern/cycles/blender/addon/ui.py
@@ -12,7 +12,7 @@ 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
+from bl_ui.properties_view_layer import ViewLayerCryptomattePanel, ViewLayerAOVPanel, ViewLayerLightgroupsPanel
class CyclesPresetPanel(PresetPanel, Panel):
COMPAT_ENGINES = {'CYCLES'}
@@ -883,6 +883,12 @@ class CYCLES_RENDER_PT_passes_aov(CyclesButtonsPanel, ViewLayerAOVPanel):
bl_parent_id = "CYCLES_RENDER_PT_passes"
+class CYCLES_RENDER_PT_passes_lightgroups(CyclesButtonsPanel, ViewLayerLightgroupsPanel):
+ bl_label = "Light Groups"
+ bl_context = "view_layer"
+ bl_parent_id = "CYCLES_RENDER_PT_passes"
+
+
class CYCLES_PT_post_processing(CyclesButtonsPanel, Panel):
bl_label = "Post Processing"
bl_options = {'DEFAULT_CLOSED'}
@@ -1093,6 +1099,10 @@ class CYCLES_OBJECT_PT_shading_shadow_terminator(CyclesButtonsPanel, Panel):
bl_parent_id = "CYCLES_OBJECT_PT_shading"
bl_context = "object"
+ @classmethod
+ def poll(cls, context):
+ return context.object.type != 'LIGHT'
+
def draw(self, context):
layout = self.layout
layout.use_property_split = True
@@ -1110,6 +1120,10 @@ class CYCLES_OBJECT_PT_shading_gi_approximation(CyclesButtonsPanel, Panel):
bl_parent_id = "CYCLES_OBJECT_PT_shading"
bl_context = "object"
+ @classmethod
+ def poll(cls, context):
+ return context.object.type != 'LIGHT'
+
def draw(self, context):
layout = self.layout
layout.use_property_split = True
@@ -1125,6 +1139,45 @@ class CYCLES_OBJECT_PT_shading_gi_approximation(CyclesButtonsPanel, Panel):
col.prop(cob, "ao_distance")
+class CYCLES_OBJECT_PT_shading_caustics(CyclesButtonsPanel, Panel):
+ bl_label = "Caustics"
+ bl_parent_id = "CYCLES_OBJECT_PT_shading"
+ bl_context = "object"
+
+ @classmethod
+ def poll(cls, context):
+ return CyclesButtonsPanel.poll(context) and not use_metal(context) and context.object.type != 'LIGHT'
+
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
+ layout.use_property_decorate = False
+
+ col = layout.column()
+
+ ob = context.object
+ cob = ob.cycles
+ col.prop(cob, "is_caustics_caster")
+ col.prop(cob, "is_caustics_receiver")
+
+
+class CYCLES_OBJECT_PT_lightgroup(CyclesButtonsPanel, Panel):
+ bl_label = "Light Group"
+ bl_parent_id = "CYCLES_OBJECT_PT_shading"
+ bl_context = "object"
+
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
+
+ ob = context.object
+
+ view_layer = context.view_layer
+
+ col = layout.column(align=True)
+ col.prop_search(ob, "lightgroup", view_layer, "lightgroups", text="Light Group")
+
+
class CYCLES_OBJECT_PT_visibility(CyclesButtonsPanel, Panel):
bl_label = "Visibility"
bl_context = "object"
@@ -1300,6 +1353,8 @@ class CYCLES_LIGHT_PT_light(CyclesButtonsPanel, Panel):
sub.active = not (light.type == 'AREA' and clamp.is_portal)
sub.prop(clamp, "cast_shadow")
sub.prop(clamp, "use_multiple_importance_sampling", text="Multiple Importance")
+ if not use_metal(context):
+ sub.prop(clamp, "is_caustics_light", text="Shadow Caustics")
if light.type == 'AREA':
col.prop(clamp, "is_portal", text="Portal")
@@ -1375,10 +1430,14 @@ class CYCLES_WORLD_PT_surface(CyclesButtonsPanel, Panel):
layout.use_property_split = True
world = context.world
+ view_layer = context.view_layer
if not panel_node_draw(layout, world, 'OUTPUT_WORLD', 'Surface'):
layout.prop(world, "color")
+ col = layout.column(align=True)
+ col.prop_search(world, "lightgroup", view_layer, "lightgroups", text="Light Group")
+
class CYCLES_WORLD_PT_volume(CyclesButtonsPanel, Panel):
bl_label = "Volume"
@@ -1496,6 +1555,8 @@ class CYCLES_WORLD_PT_settings_surface(CyclesButtonsPanel, Panel):
subsub.active = cworld.sampling_method == 'MANUAL'
subsub.prop(cworld, "sample_map_resolution")
sub.prop(cworld, "max_bounces")
+ sub.prop(cworld, "is_caustics_light", text="Shadow Caustics")
+
class CYCLES_WORLD_PT_settings_volume(CyclesButtonsPanel, Panel):
@@ -2183,6 +2244,7 @@ classes = (
CYCLES_RENDER_PT_passes_light,
CYCLES_RENDER_PT_passes_crypto,
CYCLES_RENDER_PT_passes_aov,
+ CYCLES_RENDER_PT_passes_lightgroups,
CYCLES_RENDER_PT_filter,
CYCLES_RENDER_PT_override,
CYCLES_PT_post_processing,
@@ -2193,6 +2255,8 @@ classes = (
CYCLES_OBJECT_PT_shading,
CYCLES_OBJECT_PT_shading_shadow_terminator,
CYCLES_OBJECT_PT_shading_gi_approximation,
+ CYCLES_OBJECT_PT_shading_caustics,
+ CYCLES_OBJECT_PT_lightgroup,
CYCLES_OBJECT_PT_visibility,
CYCLES_OBJECT_PT_visibility_ray_visibility,
CYCLES_OBJECT_PT_visibility_culling,
diff --git a/intern/cycles/blender/light.cpp b/intern/cycles/blender/light.cpp
index bdfbdfd8618..5359fa13505 100644
--- a/intern/cycles/blender/light.cpp
+++ b/intern/cycles/blender/light.cpp
@@ -114,6 +114,9 @@ void BlenderSync::sync_light(BL::Object &b_parent,
light->set_cast_shadow(get_boolean(clight, "cast_shadow"));
light->set_use_mis(get_boolean(clight, "use_multiple_importance_sampling"));
+ /* caustics light */
+ light->set_use_caustics(get_boolean(clight, "is_caustics_light"));
+
light->set_max_bounces(get_int(clight, "max_bounces"));
if (b_ob_info.real_object != b_ob_info.iter_object) {
@@ -140,6 +143,9 @@ void BlenderSync::sync_light(BL::Object &b_parent,
light->set_use_scatter((visibility & PATH_RAY_VOLUME_SCATTER) != 0);
light->set_is_shadow_catcher(b_ob_info.real_object.is_shadow_catcher());
+ /* lightgroup */
+ light->set_lightgroup(ustring(b_ob_info.real_object.lightgroup()));
+
/* tag */
light->tag_update(scene);
}
@@ -176,6 +182,9 @@ void BlenderSync::sync_background_light(BL::SpaceView3D &b_v3d, bool use_portal)
/* force enable light again when world is resynced */
light->set_is_enabled(true);
+ /* caustic light */
+ light->set_use_caustics(get_boolean(cworld, "is_caustics_light"));
+
light->tag_update(scene);
light_map.set_recalc(b_world);
}
diff --git a/intern/cycles/blender/object.cpp b/intern/cycles/blender/object.cpp
index 3a95746d149..d8f236e0641 100644
--- a/intern/cycles/blender/object.cpp
+++ b/intern/cycles/blender/object.cpp
@@ -298,6 +298,12 @@ Object *BlenderSync::sync_object(BL::Depsgraph &b_depsgraph,
}
object->set_ao_distance(ao_distance);
+ bool is_caustics_caster = get_boolean(cobject, "is_caustics_caster");
+ object->set_is_caustics_caster(is_caustics_caster);
+
+ bool is_caustics_receiver = get_boolean(cobject, "is_caustics_receiver");
+ object->set_is_caustics_receiver(is_caustics_receiver);
+
/* sync the asset name for Cryptomatte */
BL::Object parent = b_ob.parent();
ustring parent_name;
@@ -337,6 +343,9 @@ Object *BlenderSync::sync_object(BL::Depsgraph &b_depsgraph,
object->set_random_id(hash_uint2(hash_string(object->name.c_str()), 0));
}
+ /* lightgroup */
+ object->set_lightgroup(ustring(b_ob.lightgroup()));
+
object->tag_update(scene);
}
@@ -621,10 +630,8 @@ void BlenderSync::sync_objects(BL::Depsgraph &b_depsgraph,
bool has_subdivision_modifier = false;
BL::MeshSequenceCacheModifier b_mesh_cache(PointerRNA_NULL);
- /* Experimental as Blender does not have good support for procedurals at the moment, also
- * only available in preview renders since currently do not have a good cache policy, the
- * data being loaded at once for all the frames. */
- if (experimental && b_v3d) {
+ /* Experimental as Blender does not have good support for procedurals at the moment. */
+ if (experimental) {
b_mesh_cache = object_mesh_cache_find(b_ob, &has_subdivision_modifier);
use_procedural = b_mesh_cache && b_mesh_cache.cache_file().use_render_procedural();
}
diff --git a/intern/cycles/blender/shader.cpp b/intern/cycles/blender/shader.cpp
index 224cbea85f3..d3527567b96 100644
--- a/intern/cycles/blender/shader.cpp
+++ b/intern/cycles/blender/shader.cpp
@@ -1532,6 +1532,8 @@ void BlenderSync::sync_world(BL::Depsgraph &b_depsgraph, BL::SpaceView3D &b_v3d,
background->set_use_shader(view_layer.use_background_shader ||
viewport_parameters.use_custom_shader());
+ background->set_lightgroup(ustring(b_world ? b_world.lightgroup() : ""));
+
background->tag_update(scene);
}
diff --git a/intern/cycles/blender/sync.cpp b/intern/cycles/blender/sync.cpp
index 8af2ee7a435..bd6bfafedeb 100644
--- a/intern/cycles/blender/sync.cpp
+++ b/intern/cycles/blender/sync.cpp
@@ -745,6 +745,20 @@ void BlenderSync::sync_render_passes(BL::RenderLayer &b_rlay, BL::ViewLayer &b_v
}
}
+ /* Light Group passes. */
+ BL::ViewLayer::lightgroups_iterator b_lightgroup_iter;
+ for (b_view_layer.lightgroups.begin(b_lightgroup_iter);
+ b_lightgroup_iter != b_view_layer.lightgroups.end();
+ ++b_lightgroup_iter) {
+ BL::Lightgroup b_lightgroup(*b_lightgroup_iter);
+
+ string name = string_printf("Combined_%s", b_lightgroup.name().c_str());
+
+ b_engine.add_pass(name.c_str(), 3, "RGB", b_view_layer.name().c_str());
+ Pass *pass = pass_add(scene, PASS_COMBINED, name.c_str(), PassMode::NOISY);
+ pass->set_lightgroup(ustring(b_lightgroup.name()));
+ }
+
scene->film->set_pass_alpha_threshold(b_view_layer.pass_alpha_threshold());
}
diff --git a/intern/cycles/integrator/pass_accessor.cpp b/intern/cycles/integrator/pass_accessor.cpp
index 0be3cf6860b..05318b7545b 100644
--- a/intern/cycles/integrator/pass_accessor.cpp
+++ b/intern/cycles/integrator/pass_accessor.cpp
@@ -18,7 +18,11 @@ CCL_NAMESPACE_BEGIN
*/
PassAccessor::PassAccessInfo::PassAccessInfo(const BufferPass &pass)
- : type(pass.type), mode(pass.mode), include_albedo(pass.include_albedo), offset(pass.offset)
+ : type(pass.type),
+ mode(pass.mode),
+ include_albedo(pass.include_albedo),
+ is_lightgroup(!pass.lightgroup.empty()),
+ offset(pass.offset)
{
}
@@ -127,7 +131,8 @@ bool PassAccessor::get_render_tile_pixels(const RenderBuffers *render_buffers,
const PassType type = pass_access_info_.type;
const PassMode mode = pass_access_info_.mode;
- const PassInfo pass_info = Pass::get_info(type, pass_access_info_.include_albedo);
+ const PassInfo pass_info = Pass::get_info(
+ type, pass_access_info_.include_albedo, pass_access_info_.is_lightgroup);
int num_written_components = pass_info.num_components;
if (pass_info.num_components == 1) {
@@ -215,8 +220,8 @@ void PassAccessor::init_kernel_film_convert(KernelFilmConvert *kfilm_convert,
const Destination &destination) const
{
const PassMode mode = pass_access_info_.mode;
- const PassInfo &pass_info = Pass::get_info(pass_access_info_.type,
- pass_access_info_.include_albedo);
+ const PassInfo &pass_info = Pass::get_info(
+ pass_access_info_.type, pass_access_info_.include_albedo, pass_access_info_.is_lightgroup);
kfilm_convert->pass_offset = pass_access_info_.offset;
kfilm_convert->pass_stride = buffer_params.pass_stride;
@@ -279,8 +284,8 @@ bool PassAccessor::set_render_tile_pixels(RenderBuffers *render_buffers, const S
return false;
}
- const PassInfo pass_info = Pass::get_info(pass_access_info_.type,
- pass_access_info_.include_albedo);
+ const PassInfo pass_info = Pass::get_info(
+ pass_access_info_.type, pass_access_info_.include_albedo, pass_access_info_.is_lightgroup);
const BufferParams &buffer_params = render_buffers->params;
diff --git a/intern/cycles/integrator/pass_accessor.h b/intern/cycles/integrator/pass_accessor.h
index 7de1d03961b..683d3a35272 100644
--- a/intern/cycles/integrator/pass_accessor.h
+++ b/intern/cycles/integrator/pass_accessor.h
@@ -28,6 +28,7 @@ class PassAccessor {
PassType type = PASS_NONE;
PassMode mode = PassMode::NOISY;
bool include_albedo = false;
+ bool is_lightgroup = false;
int offset = -1;
/* For the shadow catcher matte pass: whether to approximate shadow catcher pass into its
diff --git a/intern/cycles/kernel/CMakeLists.txt b/intern/cycles/kernel/CMakeLists.txt
index 6e3ac1bd32f..cfd503a621d 100644
--- a/intern/cycles/kernel/CMakeLists.txt
+++ b/intern/cycles/kernel/CMakeLists.txt
@@ -223,6 +223,7 @@ set(SRC_KERNEL_INTEGRATOR_HEADERS
integrator/intersect_subsurface.h
integrator/intersect_volume_stack.h
integrator/megakernel.h
+ integrator/mnee.h
integrator/path_state.h
integrator/shade_background.h
integrator/shade_light.h
diff --git a/intern/cycles/kernel/device/cuda/compat.h b/intern/cycles/kernel/device/cuda/compat.h
index b392455c740..51e1381d552 100644
--- a/intern/cycles/kernel/device/cuda/compat.h
+++ b/intern/cycles/kernel/device/cuda/compat.h
@@ -76,10 +76,11 @@ typedef unsigned long long uint64_t;
/* GPU texture objects */
typedef unsigned long long CUtexObject;
-typedef CUtexObject ccl_gpu_tex_object;
+typedef CUtexObject ccl_gpu_tex_object_2D;
+typedef CUtexObject ccl_gpu_tex_object_3D;
template<typename T>
-ccl_device_forceinline T ccl_gpu_tex_object_read_2D(const ccl_gpu_tex_object texobj,
+ccl_device_forceinline T ccl_gpu_tex_object_read_2D(const ccl_gpu_tex_object_2D texobj,
const float x,
const float y)
{
@@ -87,7 +88,7 @@ ccl_device_forceinline T ccl_gpu_tex_object_read_2D(const ccl_gpu_tex_object tex
}
template<typename T>
-ccl_device_forceinline T ccl_gpu_tex_object_read_3D(const ccl_gpu_tex_object texobj,
+ccl_device_forceinline T ccl_gpu_tex_object_read_3D(const ccl_gpu_tex_object_3D texobj,
const float x,
const float y,
const float z)
diff --git a/intern/cycles/kernel/device/cuda/config.h b/intern/cycles/kernel/device/cuda/config.h
index 1f66bb0175a..88149e92ec9 100644
--- a/intern/cycles/kernel/device/cuda/config.h
+++ b/intern/cycles/kernel/device/cuda/config.h
@@ -88,6 +88,7 @@
extern "C" __global__ void __launch_bounds__(block_num_threads)
#define ccl_gpu_kernel_signature(name, ...) kernel_gpu_##name(__VA_ARGS__)
+#define ccl_gpu_kernel_postfix
#define ccl_gpu_kernel_call(x) x
diff --git a/intern/cycles/kernel/device/gpu/image.h b/intern/cycles/kernel/device/gpu/image.h
index 83e7aa869c1..c5bc7d88e02 100644
--- a/intern/cycles/kernel/device/gpu/image.h
+++ b/intern/cycles/kernel/device/gpu/image.h
@@ -56,7 +56,7 @@ ccl_device_noinline T kernel_tex_image_interp_bicubic(ccl_global const TextureIn
float x,
float y)
{
- ccl_gpu_tex_object tex = (ccl_gpu_tex_object)info.data;
+ ccl_gpu_tex_object_2D tex = (ccl_gpu_tex_object_2D)info.data;
x = (x * info.width) - 0.5f;
y = (y * info.height) - 0.5f;
@@ -85,7 +85,7 @@ template<typename T>
ccl_device_noinline T
kernel_tex_image_interp_tricubic(ccl_global const TextureInfo &info, float x, float y, float z)
{
- ccl_gpu_tex_object tex = (ccl_gpu_tex_object)info.data;
+ ccl_gpu_tex_object_3D tex = (ccl_gpu_tex_object_3D)info.data;
x = (x * info.width) - 0.5f;
y = (y * info.height) - 0.5f;
@@ -190,7 +190,7 @@ ccl_device float4 kernel_tex_image_interp(KernelGlobals kg, int id, float x, flo
return kernel_tex_image_interp_bicubic<float4>(info, x, y);
}
else {
- ccl_gpu_tex_object tex = (ccl_gpu_tex_object)info.data;
+ ccl_gpu_tex_object_2D tex = (ccl_gpu_tex_object_2D)info.data;
return ccl_gpu_tex_object_read_2D<float4>(tex, x, y);
}
}
@@ -202,7 +202,7 @@ ccl_device float4 kernel_tex_image_interp(KernelGlobals kg, int id, float x, flo
f = kernel_tex_image_interp_bicubic<float>(info, x, y);
}
else {
- ccl_gpu_tex_object tex = (ccl_gpu_tex_object)info.data;
+ ccl_gpu_tex_object_2D tex = (ccl_gpu_tex_object_2D)info.data;
f = ccl_gpu_tex_object_read_2D<float>(tex, x, y);
}
@@ -245,7 +245,7 @@ ccl_device float4 kernel_tex_image_interp_3d(KernelGlobals kg,
return kernel_tex_image_interp_tricubic<float4>(info, x, y, z);
}
else {
- ccl_gpu_tex_object tex = (ccl_gpu_tex_object)info.data;
+ ccl_gpu_tex_object_3D tex = (ccl_gpu_tex_object_3D)info.data;
return ccl_gpu_tex_object_read_3D<float4>(tex, x, y, z);
}
}
@@ -256,7 +256,7 @@ ccl_device float4 kernel_tex_image_interp_3d(KernelGlobals kg,
f = kernel_tex_image_interp_tricubic<float>(info, x, y, z);
}
else {
- ccl_gpu_tex_object tex = (ccl_gpu_tex_object)info.data;
+ ccl_gpu_tex_object_3D tex = (ccl_gpu_tex_object_3D)info.data;
f = ccl_gpu_tex_object_read_3D<float>(tex, x, y, z);
}
diff --git a/intern/cycles/kernel/device/gpu/kernel.h b/intern/cycles/kernel/device/gpu/kernel.h
index 26ab99766ad..82b51843864 100644
--- a/intern/cycles/kernel/device/gpu/kernel.h
+++ b/intern/cycles/kernel/device/gpu/kernel.h
@@ -58,6 +58,7 @@ ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
INTEGRATOR_STATE_WRITE(state, shadow_path, queued_kernel) = 0;
}
}
+ccl_gpu_kernel_postfix
ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
ccl_gpu_kernel_signature(integrator_init_from_camera,
@@ -89,6 +90,7 @@ ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
ccl_gpu_kernel_call(
integrator_init_from_camera(nullptr, state, tile, render_buffer, x, y, sample));
}
+ccl_gpu_kernel_postfix
ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
ccl_gpu_kernel_signature(integrator_init_from_bake,
@@ -120,6 +122,7 @@ ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
ccl_gpu_kernel_call(
integrator_init_from_bake(nullptr, state, tile, render_buffer, x, y, sample));
}
+ccl_gpu_kernel_postfix
ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
ccl_gpu_kernel_signature(integrator_intersect_closest,
@@ -134,6 +137,7 @@ ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
ccl_gpu_kernel_call(integrator_intersect_closest(NULL, state, render_buffer));
}
}
+ccl_gpu_kernel_postfix
ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
ccl_gpu_kernel_signature(integrator_intersect_shadow,
@@ -147,6 +151,7 @@ ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
ccl_gpu_kernel_call(integrator_intersect_shadow(NULL, state));
}
}
+ccl_gpu_kernel_postfix
ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
ccl_gpu_kernel_signature(integrator_intersect_subsurface,
@@ -160,6 +165,7 @@ ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
ccl_gpu_kernel_call(integrator_intersect_subsurface(NULL, state));
}
}
+ccl_gpu_kernel_postfix
ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
ccl_gpu_kernel_signature(integrator_intersect_volume_stack,
@@ -173,6 +179,7 @@ ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
ccl_gpu_kernel_call(integrator_intersect_volume_stack(NULL, state));
}
}
+ccl_gpu_kernel_postfix
ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
ccl_gpu_kernel_signature(integrator_shade_background,
@@ -187,6 +194,7 @@ ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
ccl_gpu_kernel_call(integrator_shade_background(NULL, state, render_buffer));
}
}
+ccl_gpu_kernel_postfix
ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
ccl_gpu_kernel_signature(integrator_shade_light,
@@ -201,6 +209,7 @@ ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
ccl_gpu_kernel_call(integrator_shade_light(NULL, state, render_buffer));
}
}
+ccl_gpu_kernel_postfix
ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
ccl_gpu_kernel_signature(integrator_shade_shadow,
@@ -215,6 +224,7 @@ ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
ccl_gpu_kernel_call(integrator_shade_shadow(NULL, state, render_buffer));
}
}
+ccl_gpu_kernel_postfix
ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
ccl_gpu_kernel_signature(integrator_shade_surface,
@@ -229,6 +239,7 @@ ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
ccl_gpu_kernel_call(integrator_shade_surface(NULL, state, render_buffer));
}
}
+ccl_gpu_kernel_postfix
#ifdef __KERNEL_METAL__
constant int __dummy_constant [[function_constant(0)]];
@@ -256,6 +267,7 @@ ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
#endif
}
}
+ccl_gpu_kernel_postfix
ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
ccl_gpu_kernel_signature(integrator_shade_volume,
@@ -270,6 +282,7 @@ ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
ccl_gpu_kernel_call(integrator_shade_volume(NULL, state, render_buffer));
}
}
+ccl_gpu_kernel_postfix
ccl_gpu_kernel_threads(GPU_PARALLEL_ACTIVE_INDEX_DEFAULT_BLOCK_SIZE)
ccl_gpu_kernel_signature(integrator_queued_paths_array,
@@ -288,6 +301,7 @@ ccl_gpu_kernel_threads(GPU_PARALLEL_ACTIVE_INDEX_DEFAULT_BLOCK_SIZE)
num_indices,
ccl_gpu_kernel_lambda_pass);
}
+ccl_gpu_kernel_postfix
ccl_gpu_kernel_threads(GPU_PARALLEL_ACTIVE_INDEX_DEFAULT_BLOCK_SIZE)
ccl_gpu_kernel_signature(integrator_queued_shadow_paths_array,
@@ -306,6 +320,7 @@ ccl_gpu_kernel_threads(GPU_PARALLEL_ACTIVE_INDEX_DEFAULT_BLOCK_SIZE)
num_indices,
ccl_gpu_kernel_lambda_pass);
}
+ccl_gpu_kernel_postfix
ccl_gpu_kernel_threads(GPU_PARALLEL_ACTIVE_INDEX_DEFAULT_BLOCK_SIZE)
ccl_gpu_kernel_signature(integrator_active_paths_array,
@@ -321,6 +336,7 @@ ccl_gpu_kernel_threads(GPU_PARALLEL_ACTIVE_INDEX_DEFAULT_BLOCK_SIZE)
num_indices,
ccl_gpu_kernel_lambda_pass);
}
+ccl_gpu_kernel_postfix
ccl_gpu_kernel_threads(GPU_PARALLEL_ACTIVE_INDEX_DEFAULT_BLOCK_SIZE)
ccl_gpu_kernel_signature(integrator_terminated_paths_array,
@@ -337,6 +353,7 @@ ccl_gpu_kernel_threads(GPU_PARALLEL_ACTIVE_INDEX_DEFAULT_BLOCK_SIZE)
num_indices,
ccl_gpu_kernel_lambda_pass);
}
+ccl_gpu_kernel_postfix
ccl_gpu_kernel_threads(GPU_PARALLEL_ACTIVE_INDEX_DEFAULT_BLOCK_SIZE)
ccl_gpu_kernel_signature(integrator_terminated_shadow_paths_array,
@@ -353,6 +370,7 @@ ccl_gpu_kernel_threads(GPU_PARALLEL_ACTIVE_INDEX_DEFAULT_BLOCK_SIZE)
num_indices,
ccl_gpu_kernel_lambda_pass);
}
+ccl_gpu_kernel_postfix
ccl_gpu_kernel_threads(GPU_PARALLEL_SORTED_INDEX_DEFAULT_BLOCK_SIZE)
ccl_gpu_kernel_signature(integrator_sorted_paths_array,
@@ -380,6 +398,7 @@ ccl_gpu_kernel_threads(GPU_PARALLEL_SORTED_INDEX_DEFAULT_BLOCK_SIZE)
key_prefix_sum,
ccl_gpu_kernel_lambda_pass);
}
+ccl_gpu_kernel_postfix
ccl_gpu_kernel_threads(GPU_PARALLEL_ACTIVE_INDEX_DEFAULT_BLOCK_SIZE)
ccl_gpu_kernel_signature(integrator_compact_paths_array,
@@ -399,6 +418,7 @@ ccl_gpu_kernel_threads(GPU_PARALLEL_ACTIVE_INDEX_DEFAULT_BLOCK_SIZE)
num_indices,
ccl_gpu_kernel_lambda_pass);
}
+ccl_gpu_kernel_postfix
ccl_gpu_kernel_threads(GPU_PARALLEL_SORTED_INDEX_DEFAULT_BLOCK_SIZE)
ccl_gpu_kernel_signature(integrator_compact_states,
@@ -416,6 +436,7 @@ ccl_gpu_kernel_threads(GPU_PARALLEL_SORTED_INDEX_DEFAULT_BLOCK_SIZE)
ccl_gpu_kernel_call(integrator_state_move(NULL, to_state, from_state));
}
}
+ccl_gpu_kernel_postfix
ccl_gpu_kernel_threads(GPU_PARALLEL_ACTIVE_INDEX_DEFAULT_BLOCK_SIZE)
ccl_gpu_kernel_signature(integrator_compact_shadow_paths_array,
@@ -435,6 +456,7 @@ ccl_gpu_kernel_threads(GPU_PARALLEL_ACTIVE_INDEX_DEFAULT_BLOCK_SIZE)
num_indices,
ccl_gpu_kernel_lambda_pass);
}
+ccl_gpu_kernel_postfix
ccl_gpu_kernel_threads(GPU_PARALLEL_SORTED_INDEX_DEFAULT_BLOCK_SIZE)
ccl_gpu_kernel_signature(integrator_compact_shadow_states,
@@ -452,12 +474,14 @@ ccl_gpu_kernel_threads(GPU_PARALLEL_SORTED_INDEX_DEFAULT_BLOCK_SIZE)
ccl_gpu_kernel_call(integrator_shadow_state_move(NULL, to_state, from_state));
}
}
+ccl_gpu_kernel_postfix
ccl_gpu_kernel_threads(GPU_PARALLEL_PREFIX_SUM_DEFAULT_BLOCK_SIZE) ccl_gpu_kernel_signature(
prefix_sum, ccl_global int *counter, ccl_global int *prefix_sum, int num_values)
{
gpu_parallel_prefix_sum(ccl_gpu_global_id_x(), counter, prefix_sum, num_values);
}
+ccl_gpu_kernel_postfix
/* --------------------------------------------------------------------
* Adaptive sampling.
@@ -494,6 +518,7 @@ ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
atomic_fetch_and_add_uint32(num_active_pixels, popcount(num_active_pixels_mask));
}
}
+ccl_gpu_kernel_postfix
ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
ccl_gpu_kernel_signature(adaptive_sampling_filter_x,
@@ -512,6 +537,7 @@ ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
kernel_adaptive_sampling_filter_x(NULL, render_buffer, sy + y, sx, sw, offset, stride));
}
}
+ccl_gpu_kernel_postfix
ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
ccl_gpu_kernel_signature(adaptive_sampling_filter_y,
@@ -530,6 +556,7 @@ ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
kernel_adaptive_sampling_filter_y(NULL, render_buffer, sx + x, sy, sh, offset, stride));
}
}
+ccl_gpu_kernel_postfix
/* --------------------------------------------------------------------
* Cryptomatte.
@@ -546,6 +573,7 @@ ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
ccl_gpu_kernel_call(kernel_cryptomatte_post(nullptr, render_buffer, pixel_index));
}
}
+ccl_gpu_kernel_postfix
/* --------------------------------------------------------------------
* Film.
@@ -627,6 +655,7 @@ ccl_device_inline void kernel_gpu_film_convert_half_write(ccl_global uchar4 *rgb
\
FILM_GET_PASS_PIXEL_F32(variant, input_channel_count); \
} \
+ ccl_gpu_kernel_postfix \
\
ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS) \
ccl_gpu_kernel_signature(film_convert_##variant##_half_rgba, \
@@ -666,7 +695,8 @@ ccl_device_inline void kernel_gpu_film_convert_half_write(ccl_global uchar4 *rgb
const half4 half_pixel = float4_to_half4_display( \
make_float4(pixel[0], pixel[1], pixel[2], pixel[3])); \
kernel_gpu_film_convert_half_write(rgba, rgba_offset, rgba_stride, x, y, half_pixel); \
- }
+ } \
+ ccl_gpu_kernel_postfix
/* 1 channel inputs */
KERNEL_FILM_CONVERT_VARIANT(depth, 1)
@@ -706,6 +736,7 @@ ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
ccl_gpu_kernel_call(kernel_displace_evaluate(NULL, input, output, offset + i));
}
}
+ccl_gpu_kernel_postfix
/* Background */
@@ -721,6 +752,7 @@ ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
ccl_gpu_kernel_call(kernel_background_evaluate(NULL, input, output, offset + i));
}
}
+ccl_gpu_kernel_postfix
/* Curve Shadow Transparency */
@@ -737,6 +769,7 @@ ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
kernel_curve_shadow_transparency_evaluate(NULL, input, output, offset + i));
}
}
+ccl_gpu_kernel_postfix
/* --------------------------------------------------------------------
* Denoising.
@@ -770,6 +803,7 @@ ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
color_out[1] = clamp(color_out[1], 0.0f, 10000.0f);
color_out[2] = clamp(color_out[2], 0.0f, 10000.0f);
}
+ccl_gpu_kernel_postfix
ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
ccl_gpu_kernel_signature(filter_guiding_preprocess,
@@ -849,6 +883,7 @@ ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
flow_out[1] = -motion_in[1] * pixel_scale;
}
}
+ccl_gpu_kernel_postfix
ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
ccl_gpu_kernel_signature(filter_guiding_set_fake_albedo,
@@ -877,6 +912,7 @@ ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
albedo_out[1] = 0.5f;
albedo_out[2] = 0.5f;
}
+ccl_gpu_kernel_postfix
ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
ccl_gpu_kernel_signature(filter_color_postprocess,
@@ -936,6 +972,7 @@ ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
denoised_pixel[3] = 0;
}
}
+ccl_gpu_kernel_postfix
/* --------------------------------------------------------------------
* Shadow catcher.
@@ -961,3 +998,4 @@ ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
atomic_fetch_and_add_uint32(num_possible_splits, popcount(can_split_mask));
}
}
+ccl_gpu_kernel_postfix
diff --git a/intern/cycles/kernel/device/hip/compat.h b/intern/cycles/kernel/device/hip/compat.h
index 29fbc119cd1..9c93d87fd87 100644
--- a/intern/cycles/kernel/device/hip/compat.h
+++ b/intern/cycles/kernel/device/hip/compat.h
@@ -73,10 +73,11 @@ typedef unsigned long long uint64_t;
#define ccl_gpu_ballot(predicate) __ballot(predicate)
/* GPU texture objects */
-typedef hipTextureObject_t ccl_gpu_tex_object;
+typedef hipTextureObject_t ccl_gpu_tex_object_2D;
+typedef hipTextureObject_t ccl_gpu_tex_object_3D;
template<typename T>
-ccl_device_forceinline T ccl_gpu_tex_object_read_2D(const ccl_gpu_tex_object texobj,
+ccl_device_forceinline T ccl_gpu_tex_object_read_2D(const ccl_gpu_tex_object_2D texobj,
const float x,
const float y)
{
@@ -84,7 +85,7 @@ ccl_device_forceinline T ccl_gpu_tex_object_read_2D(const ccl_gpu_tex_object tex
}
template<typename T>
-ccl_device_forceinline T ccl_gpu_tex_object_read_3D(const ccl_gpu_tex_object texobj,
+ccl_device_forceinline T ccl_gpu_tex_object_read_3D(const ccl_gpu_tex_object_3D texobj,
const float x,
const float y,
const float z)
diff --git a/intern/cycles/kernel/device/hip/config.h b/intern/cycles/kernel/device/hip/config.h
index a5a5924d5e0..c7e7306d628 100644
--- a/intern/cycles/kernel/device/hip/config.h
+++ b/intern/cycles/kernel/device/hip/config.h
@@ -31,6 +31,7 @@
extern "C" __global__ void __launch_bounds__(block_num_threads)
#define ccl_gpu_kernel_signature(name, ...) kernel_gpu_##name(__VA_ARGS__)
+#define ccl_gpu_kernel_postfix
#define ccl_gpu_kernel_call(x) x
diff --git a/intern/cycles/kernel/device/metal/compat.h b/intern/cycles/kernel/device/metal/compat.h
index c12987c0a91..4e309f16c08 100644
--- a/intern/cycles/kernel/device/metal/compat.h
+++ b/intern/cycles/kernel/device/metal/compat.h
@@ -132,6 +132,7 @@ void kernel_gpu_##name::run(thread MetalKernelContext& context, \
uint simd_group_index, \
uint num_simd_groups) ccl_global const
+#define ccl_gpu_kernel_postfix
#define ccl_gpu_kernel_call(x) context.x
/* define a function object where "func" is the lambda body, and additional parameters are used to specify captured state */
diff --git a/intern/cycles/kernel/device/metal/context_begin.h b/intern/cycles/kernel/device/metal/context_begin.h
index 4c9d6b6e405..99cb1e3826e 100644
--- a/intern/cycles/kernel/device/metal/context_begin.h
+++ b/intern/cycles/kernel/device/metal/context_begin.h
@@ -19,17 +19,18 @@ class MetalKernelContext {
{}
/* texture fetch adapter functions */
- typedef uint64_t ccl_gpu_tex_object;
+ typedef uint64_t ccl_gpu_tex_object_2D;
+ typedef uint64_t ccl_gpu_tex_object_3D;
template<typename T>
inline __attribute__((__always_inline__))
- T ccl_gpu_tex_object_read_2D(ccl_gpu_tex_object tex, float x, float y) const {
+ T ccl_gpu_tex_object_read_2D(ccl_gpu_tex_object_2D tex, float x, float y) const {
kernel_assert(0);
return 0;
}
template<typename T>
inline __attribute__((__always_inline__))
- T ccl_gpu_tex_object_read_3D(ccl_gpu_tex_object tex, float x, float y, float z) const {
+ T ccl_gpu_tex_object_read_3D(ccl_gpu_tex_object_3D tex, float x, float y, float z) const {
kernel_assert(0);
return 0;
}
@@ -37,14 +38,14 @@ class MetalKernelContext {
// texture2d
template<>
inline __attribute__((__always_inline__))
- float4 ccl_gpu_tex_object_read_2D(ccl_gpu_tex_object tex, float x, float y) const {
+ float4 ccl_gpu_tex_object_read_2D(ccl_gpu_tex_object_2D tex, float x, float y) const {
const uint tid(tex);
const uint sid(tex >> 32);
return metal_ancillaries->textures_2d[tid].tex.sample(metal_samplers[sid], float2(x, y));
}
template<>
inline __attribute__((__always_inline__))
- float ccl_gpu_tex_object_read_2D(ccl_gpu_tex_object tex, float x, float y) const {
+ float ccl_gpu_tex_object_read_2D(ccl_gpu_tex_object_2D tex, float x, float y) const {
const uint tid(tex);
const uint sid(tex >> 32);
return metal_ancillaries->textures_2d[tid].tex.sample(metal_samplers[sid], float2(x, y)).x;
@@ -53,14 +54,14 @@ class MetalKernelContext {
// texture3d
template<>
inline __attribute__((__always_inline__))
- float4 ccl_gpu_tex_object_read_3D(ccl_gpu_tex_object tex, float x, float y, float z) const {
+ float4 ccl_gpu_tex_object_read_3D(ccl_gpu_tex_object_3D tex, float x, float y, float z) const {
const uint tid(tex);
const uint sid(tex >> 32);
return metal_ancillaries->textures_3d[tid].tex.sample(metal_samplers[sid], float3(x, y, z));
}
template<>
inline __attribute__((__always_inline__))
- float ccl_gpu_tex_object_read_3D(ccl_gpu_tex_object tex, float x, float y, float z) const {
+ float ccl_gpu_tex_object_read_3D(ccl_gpu_tex_object_3D tex, float x, float y, float z) const {
const uint tid(tex);
const uint sid(tex >> 32);
return metal_ancillaries->textures_3d[tid].tex.sample(metal_samplers[sid], float3(x, y, z)).x;
diff --git a/intern/cycles/kernel/device/optix/compat.h b/intern/cycles/kernel/device/optix/compat.h
index ae7a0309e51..aa4a6321a8b 100644
--- a/intern/cycles/kernel/device/optix/compat.h
+++ b/intern/cycles/kernel/device/optix/compat.h
@@ -78,10 +78,11 @@ typedef unsigned long long uint64_t;
/* GPU texture objects */
typedef unsigned long long CUtexObject;
-typedef CUtexObject ccl_gpu_tex_object;
+typedef CUtexObject ccl_gpu_tex_object_2D;
+typedef CUtexObject ccl_gpu_tex_object_3D;
template<typename T>
-ccl_device_forceinline T ccl_gpu_tex_object_read_2D(const ccl_gpu_tex_object texobj,
+ccl_device_forceinline T ccl_gpu_tex_object_read_2D(const ccl_gpu_tex_object_2D texobj,
const float x,
const float y)
{
@@ -89,7 +90,7 @@ ccl_device_forceinline T ccl_gpu_tex_object_read_2D(const ccl_gpu_tex_object tex
}
template<typename T>
-ccl_device_forceinline T ccl_gpu_tex_object_read_3D(const ccl_gpu_tex_object texobj,
+ccl_device_forceinline T ccl_gpu_tex_object_read_3D(const ccl_gpu_tex_object_3D texobj,
const float x,
const float y,
const float z)
diff --git a/intern/cycles/kernel/film/accumulate.h b/intern/cycles/kernel/film/accumulate.h
index d6a385a4bff..e10acfd7eb5 100644
--- a/intern/cycles/kernel/film/accumulate.h
+++ b/intern/cycles/kernel/film/accumulate.h
@@ -320,12 +320,13 @@ ccl_device_inline void kernel_accum_combined_transparent_pass(KernelGlobals kg,
}
/* Write background or emission to appropriate pass. */
-ccl_device_inline void kernel_accum_emission_or_background_pass(KernelGlobals kg,
- ConstIntegratorState state,
- float3 contribution,
- ccl_global float *ccl_restrict
- buffer,
- const int pass)
+ccl_device_inline void kernel_accum_emission_or_background_pass(
+ KernelGlobals kg,
+ ConstIntegratorState state,
+ float3 contribution,
+ ccl_global float *ccl_restrict buffer,
+ const int pass,
+ const int lightgroup = LIGHTGROUP_NONE)
{
if (!(kernel_data.film.light_pass_flag & PASS_ANY)) {
return;
@@ -347,6 +348,11 @@ ccl_device_inline void kernel_accum_emission_or_background_pass(KernelGlobals kg
}
# endif /* __DENOISING_FEATURES__ */
+ if (lightgroup != LIGHTGROUP_NONE && kernel_data.film.pass_lightgroup != PASS_UNUSED) {
+ kernel_write_pass_float3(buffer + kernel_data.film.pass_lightgroup + 3 * lightgroup,
+ contribution);
+ }
+
if (!(path_flag & PATH_RAY_ANY_PASS)) {
/* Directly visible, write to emission or background pass. */
pass_offset = pass;
@@ -449,6 +455,13 @@ ccl_device_inline void kernel_accum_light(KernelGlobals kg,
return;
}
+ /* Write lightgroup pass. LIGHTGROUP_NONE is ~0 so decode from unsigned to signed */
+ const int lightgroup = (int)(INTEGRATOR_STATE(state, shadow_path, lightgroup)) - 1;
+ if (lightgroup != LIGHTGROUP_NONE && kernel_data.film.pass_lightgroup != PASS_UNUSED) {
+ kernel_write_pass_float3(buffer + kernel_data.film.pass_lightgroup + 3 * lightgroup,
+ contribution);
+ }
+
if (kernel_data.kernel_features & KERNEL_FEATURE_LIGHT_PASSES) {
int pass_offset = PASS_UNUSED;
@@ -566,15 +579,20 @@ ccl_device_inline void kernel_accum_background(KernelGlobals kg,
kernel_accum_combined_transparent_pass(
kg, path_flag, sample, contribution, transparent, buffer);
}
- kernel_accum_emission_or_background_pass(
- kg, state, contribution, buffer, kernel_data.film.pass_background);
+ kernel_accum_emission_or_background_pass(kg,
+ state,
+ contribution,
+ buffer,
+ kernel_data.film.pass_background,
+ kernel_data.background.lightgroup);
}
/* Write emission to render buffer. */
ccl_device_inline void kernel_accum_emission(KernelGlobals kg,
ConstIntegratorState state,
const float3 L,
- ccl_global float *ccl_restrict render_buffer)
+ ccl_global float *ccl_restrict render_buffer,
+ const int lightgroup = LIGHTGROUP_NONE)
{
float3 contribution = L;
kernel_accum_clamp(kg, &contribution, INTEGRATOR_STATE(state, path, bounce) - 1);
@@ -585,7 +603,7 @@ ccl_device_inline void kernel_accum_emission(KernelGlobals kg,
kernel_accum_combined_pass(kg, path_flag, sample, contribution, buffer);
kernel_accum_emission_or_background_pass(
- kg, state, contribution, buffer, kernel_data.film.pass_emission);
+ kg, state, contribution, buffer, kernel_data.film.pass_emission, lightgroup);
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/geom/object.h b/intern/cycles/kernel/geom/object.h
index 86c57c84b47..3faab7fa905 100644
--- a/intern/cycles/kernel/geom/object.h
+++ b/intern/cycles/kernel/geom/object.h
@@ -283,6 +283,26 @@ ccl_device_inline float object_pass_id(KernelGlobals kg, int object)
return kernel_tex_fetch(__objects, object).pass_id;
}
+/* Lightgroup of lamp */
+
+ccl_device_inline int lamp_lightgroup(KernelGlobals kg, int lamp)
+{
+ if (lamp == LAMP_NONE)
+ return LIGHTGROUP_NONE;
+
+ return kernel_tex_fetch(__lights, lamp).lightgroup;
+}
+
+/* Lightgroup of object */
+
+ccl_device_inline int object_lightgroup(KernelGlobals kg, int object)
+{
+ if (object == OBJECT_NONE)
+ return LIGHTGROUP_NONE;
+
+ return kernel_tex_fetch(__objects, object).lightgroup;
+}
+
/* Per lamp random number for shader variation */
ccl_device_inline float lamp_random_number(KernelGlobals kg, int lamp)
diff --git a/intern/cycles/kernel/integrator/init_from_bake.h b/intern/cycles/kernel/integrator/init_from_bake.h
index b84059d6676..d6047bd2288 100644
--- a/intern/cycles/kernel/integrator/init_from_bake.h
+++ b/intern/cycles/kernel/integrator/init_from_bake.h
@@ -230,7 +230,11 @@ ccl_device bool integrator_init_from_bake(KernelGlobals kg,
/* Setup next kernel to execute. */
const int shader_index = shader & SHADER_MASK;
const int shader_flags = kernel_tex_fetch(__shaders, shader_index).flags;
- if (shader_flags & SD_HAS_RAYTRACE) {
+ const bool use_caustics = kernel_data.integrator.use_caustics &&
+ (object_flag & SD_OBJECT_CAUSTICS);
+ const bool use_raytrace_kernel = (shader_flags & SD_HAS_RAYTRACE) || use_caustics;
+
+ if (use_raytrace_kernel) {
INTEGRATOR_PATH_INIT_SORTED(DEVICE_KERNEL_INTEGRATOR_SHADE_SURFACE_RAYTRACE, shader_index);
}
else {
diff --git a/intern/cycles/kernel/integrator/intersect_closest.h b/intern/cycles/kernel/integrator/intersect_closest.h
index 9fcbf89c579..b8ce625c11b 100644
--- a/intern/cycles/kernel/integrator/intersect_closest.h
+++ b/intern/cycles/kernel/integrator/intersect_closest.h
@@ -123,7 +123,9 @@ ccl_device_forceinline void integrator_split_shadow_catcher(
/* Continue with shading shadow catcher surface. */
const int shader = intersection_get_shader(kg, isect);
const int flags = kernel_tex_fetch(__shaders, shader).flags;
- const bool use_raytrace_kernel = (flags & SD_HAS_RAYTRACE);
+ const bool use_caustics = kernel_data.integrator.use_caustics &&
+ (object_flags & SD_OBJECT_CAUSTICS);
+ const bool use_raytrace_kernel = (flags & SD_HAS_RAYTRACE) || use_caustics;
if (use_raytrace_kernel) {
INTEGRATOR_PATH_INIT_SORTED(DEVICE_KERNEL_INTEGRATOR_SHADE_SURFACE_RAYTRACE, shader);
@@ -145,7 +147,10 @@ ccl_device_forceinline void integrator_intersect_next_kernel_after_shadow_catche
const int shader = intersection_get_shader(kg, &isect);
const int flags = kernel_tex_fetch(__shaders, shader).flags;
- const bool use_raytrace_kernel = (flags & SD_HAS_RAYTRACE);
+ const int object_flags = intersection_get_object_flags(kg, &isect);
+ const bool use_caustics = kernel_data.integrator.use_caustics &&
+ (object_flags & SD_OBJECT_CAUSTICS);
+ const bool use_raytrace_kernel = (flags & SD_HAS_RAYTRACE) || use_caustics;
if (use_raytrace_kernel) {
INTEGRATOR_PATH_NEXT_SORTED(
@@ -214,7 +219,10 @@ ccl_device_forceinline void integrator_intersect_next_kernel(
const int flags = kernel_tex_fetch(__shaders, shader).flags;
if (!integrator_intersect_terminate(kg, state, flags)) {
- const bool use_raytrace_kernel = (flags & SD_HAS_RAYTRACE);
+ const int object_flags = intersection_get_object_flags(kg, isect);
+ const bool use_caustics = kernel_data.integrator.use_caustics &&
+ (object_flags & SD_OBJECT_CAUSTICS);
+ const bool use_raytrace_kernel = (flags & SD_HAS_RAYTRACE) || use_caustics;
if (use_raytrace_kernel) {
INTEGRATOR_PATH_NEXT_SORTED(
current_kernel, DEVICE_KERNEL_INTEGRATOR_SHADE_SURFACE_RAYTRACE, shader);
@@ -261,7 +269,10 @@ ccl_device_forceinline void integrator_intersect_next_kernel_after_volume(
/* Hit a surface, continue with surface kernel unless terminated. */
const int shader = intersection_get_shader(kg, isect);
const int flags = kernel_tex_fetch(__shaders, shader).flags;
- const bool use_raytrace_kernel = (flags & SD_HAS_RAYTRACE);
+ const int object_flags = intersection_get_object_flags(kg, isect);
+ const bool use_caustics = kernel_data.integrator.use_caustics &&
+ (object_flags & SD_OBJECT_CAUSTICS);
+ const bool use_raytrace_kernel = (flags & SD_HAS_RAYTRACE) || use_caustics;
if (use_raytrace_kernel) {
INTEGRATOR_PATH_NEXT_SORTED(
@@ -328,12 +339,37 @@ ccl_device void integrator_intersect_closest(KernelGlobals kg,
isect.prim = PRIM_NONE;
}
+ /* Setup mnee flag to signal last intersection with a caster */
+ const uint32_t path_flag = INTEGRATOR_STATE(state, path, flag);
+
+#ifdef __MNEE__
+ /* Path culling logic for MNEE (removes fireflies at the cost of bias) */
+ if (kernel_data.integrator.use_caustics) {
+ /* The following firefly removal mechanism works by culling light connections when
+ * a ray comes from a caustic caster directly after bouncing off a different caustic
+ * receiver */
+ bool from_caustic_caster = false;
+ bool from_caustic_receiver = false;
+ if (!(path_flag & PATH_RAY_CAMERA) && last_isect_object != OBJECT_NONE) {
+ const int object_flags = kernel_tex_fetch(__object_flag, last_isect_object);
+ from_caustic_receiver = (object_flags & SD_OBJECT_CAUSTICS_RECEIVER);
+ from_caustic_caster = (object_flags & SD_OBJECT_CAUSTICS_CASTER);
+ }
+
+ bool has_receiver_ancestor = INTEGRATOR_STATE(state, path, mnee) & PATH_MNEE_RECEIVER_ANCESTOR;
+ INTEGRATOR_STATE_WRITE(state, path, mnee) &= ~PATH_MNEE_CULL_LIGHT_CONNECTION;
+ if (from_caustic_caster && has_receiver_ancestor)
+ INTEGRATOR_STATE_WRITE(state, path, mnee) |= PATH_MNEE_CULL_LIGHT_CONNECTION;
+ if (from_caustic_receiver)
+ INTEGRATOR_STATE_WRITE(state, path, mnee) |= PATH_MNEE_RECEIVER_ANCESTOR;
+ }
+#endif /* __MNEE__ */
+
/* Light intersection for MIS. */
if (kernel_data.integrator.use_lamp_mis) {
/* NOTE: if we make lights visible to camera rays, we'll need to initialize
* these in the path_state_init. */
const int last_type = INTEGRATOR_STATE(state, isect, type);
- const uint32_t path_flag = INTEGRATOR_STATE(state, path, flag);
hit = lights_intersect(
kg, state, &ray, &isect, last_isect_prim, last_isect_object, last_type, path_flag) ||
hit;
diff --git a/intern/cycles/kernel/integrator/mnee.h b/intern/cycles/kernel/integrator/mnee.h
new file mode 100644
index 00000000000..af2032c9b99
--- /dev/null
+++ b/intern/cycles/kernel/integrator/mnee.h
@@ -0,0 +1,1150 @@
+/* SPDX-License-Identifier: Apache-2.0
+ * Copyright 2011-2022 Blender Foundation */
+
+#ifdef __MNEE__
+
+# include "kernel/light/sample.h"
+
+/*
+ * Manifold Next Event Estimation
+ *
+ * This code adds manifold next event estimation through refractive surface(s) as a new sampling
+ * technique for direct lighting, i.e. finding the point on the refractive surface(s) along the
+ * path to a light sample, which satisfies fermat's principle for a given microfacet normal and
+ * the path's end points. This technique involves walking on the "specular manifold" using a pseudo
+ * newton solver. Such a manifold is defined by the specular constraint matrix from the manifold
+ * exploration framework [2]. For each refractive interface, this constraint is defined by
+ * enforcing that the generalized half-vector projection onto the interface local tangent plane is
+ * null. The newton solver guides the walk by linearizing the manifold locally before reprojecting
+ * the linear solution onto the refractive surface. See paper [1] for more details about
+ * the technique itself and [3] for the half-vector light transport formulation, from which it is
+ * derived.
+ *
+ * [1] Manifold Next Event Estimation
+ * Johannes Hanika, Marc Droske, and Luca Fascione. 2015.
+ * Comput. Graph. Forum 34, 4 (July 2015), 87–97.
+ * https://jo.dreggn.org/home/2015_mnee.pdf
+ *
+ * [2] Manifold exploration: a Markov Chain Monte Carlo technique for rendering scenes with
+ * difficult specular transport Wenzel Jakob and Steve Marschner. 2012. ACM Trans. Graph. 31, 4,
+ * Article 58 (July 2012), 13 pages.
+ * https://www.cs.cornell.edu/projects/manifolds-sg12/
+ *
+ * [3] The Natural-Constraint Representation of the Path Space for Efficient Light Transport
+ * Simulation Anton S. Kaplanyan, Johannes Hanika, and Carsten Dachsbacher. 2014. ACM Trans. Graph.
+ * 33, 4, Article 102 (July 2014), 13 pages.
+ * https://cg.ivd.kit.edu/english/HSLT.php
+ */
+
+# define MNEE_MAX_ITERATIONS 50
+# define MNEE_MAX_INTERSECTION_COUNT 10
+# define MNEE_SOLVER_THRESHOLD 0.001f
+# define MNEE_MAX_CAUSTIC_CASTERS 6
+# define MNEE_MIN_DISTANCE 0.001f
+# define MNEE_MIN_DETERMINANT 0.0001f
+# define MNEE_PROJECTION_DISTANCE_MULTIPLIER 2.f
+
+CCL_NAMESPACE_BEGIN
+
+/* Manifold struct containing the local differential geometry quantity */
+typedef ccl_private struct ManifoldVertex {
+ /* Position and partials */
+ float3 p;
+ float3 dp_du;
+ float3 dp_dv;
+
+ /* Normal and partials */
+ float3 n;
+ float3 ng;
+ float3 dn_du;
+ float3 dn_dv;
+
+ /* geometric info */
+ float2 uv;
+ int object;
+ int prim;
+ int shader;
+
+ /* closure info */
+ float eta;
+ ccl_private ShaderClosure *bsdf;
+ float2 n_offset;
+
+ /* constraint and its derivative matrices */
+ float2 constraint;
+ float4 a;
+ float4 b;
+ float4 c;
+} ManifoldVertex;
+
+/* Multiplication of a 2x2 matrix encoded in a row-major order float4 by a vector */
+ccl_device_inline float2 mat22_mult(const float4 a, const float2 b)
+{
+ return make_float2(a.x * b.x + a.y * b.y, a.z * b.x + a.w * b.y);
+}
+
+/* Multiplication of 2x2 matrices encoded in a row-major order float4 */
+ccl_device_inline float4 mat22_mult(const float4 a, const float4 b)
+{
+ return make_float4(
+ a.x * b.x + a.y * b.z, a.x * b.y + a.y * b.w, a.z * b.x + a.w * b.z, a.z * b.y + a.w * b.w);
+}
+
+/* Determinant of a 2x2 matrix encoded in a row-major order float4 */
+ccl_device_inline float mat22_determinant(const float4 m)
+{
+ return m.x * m.w - m.y * m.z;
+}
+
+/* Inverse of a 2x2 matrix encoded in a row-major order float4 */
+ccl_device_inline float mat22_inverse(const float4 m, ccl_private float4& m_inverse)
+{
+ float det = mat22_determinant(m);
+ if (fabsf(det) < MNEE_MIN_DETERMINANT)
+ return 0.f;
+ m_inverse = make_float4(m.w, -m.y, -m.z, m.x) / det;
+ return det;
+}
+
+/* Update light sample */
+ccl_device_forceinline void mnee_update_light_sample(KernelGlobals kg,
+ const float3 P,
+ ccl_private LightSample *ls)
+{
+ /* correct light sample position/direction and pdf
+ * NOTE: preserve pdf in area measure */
+ const ccl_global KernelLight *klight = &kernel_tex_fetch(__lights, ls->lamp);
+
+ if (ls->type == LIGHT_POINT || ls->type == LIGHT_SPOT) {
+ ls->D = normalize_len(ls->P - P, &ls->t);
+ ls->Ng = -ls->D;
+
+ float2 uv = map_to_sphere(ls->Ng);
+ ls->u = uv.x;
+ ls->v = uv.y;
+
+ float invarea = klight->spot.invarea;
+ ls->eval_fac = (0.25f * M_1_PI_F) * invarea;
+ ls->pdf = invarea;
+
+ if (ls->type == LIGHT_SPOT) {
+ /* spot light attenuation */
+ float3 dir = make_float3(klight->spot.dir[0], klight->spot.dir[1], klight->spot.dir[2]);
+ ls->eval_fac *= spot_light_attenuation(
+ dir, klight->spot.spot_angle, klight->spot.spot_smooth, ls->Ng);
+ }
+ }
+ else if (ls->type == LIGHT_AREA) {
+ ls->D = normalize_len(ls->P - P, &ls->t);
+ ls->pdf = fabsf(klight->area.invarea);
+ }
+}
+
+/* Compute orthonormal basis
+ * https://graphics.pixar.com/library/OrthonormalB/paper.pdf */
+ccl_device_forceinline void mnee_make_orthonormals(const float3 n,
+ ccl_private float3 *dp_du,
+ ccl_private float3 *dp_dv)
+{
+ if (n.z < 0.0f) {
+ const float a = 1.0f / (1.0f - n.z);
+ const float b = n.x * n.y * a;
+ *dp_du = make_float3(1.0f - n.x * n.x * a, -b, n.x);
+ *dp_dv = make_float3(b, n.y * n.y * a - 1.0f, -n.y);
+ }
+ else {
+ const float a = 1.0f / (1.0f + n.z);
+ const float b = -n.x * n.y * a;
+ *dp_du = make_float3(1.0f - n.x * n.x * a, b, -n.x);
+ *dp_dv = make_float3(b, 1.0f - n.y * n.y * a, -n.y);
+ }
+}
+
+/* Manifold vertex setup from ray and intersection data */
+ccl_device_forceinline void mnee_setup_manifold_vertex(KernelGlobals kg,
+ ccl_private ManifoldVertex *vtx,
+ ccl_private ShaderClosure *bsdf,
+ const float eta,
+ const float2 n_offset,
+ ccl_private const Ray *ray,
+ ccl_private const Intersection *isect,
+ ccl_private ShaderData *sd_vtx)
+{
+ sd_vtx->object = (isect->object == OBJECT_NONE) ? kernel_tex_fetch(__prim_object, isect->prim) :
+ isect->object;
+
+ sd_vtx->type = isect->type;
+ sd_vtx->flag = 0;
+ sd_vtx->object_flag = kernel_tex_fetch(__object_flag, sd_vtx->object);
+
+ /* matrices and time */
+ shader_setup_object_transforms(kg, sd_vtx, ray->time);
+ sd_vtx->time = ray->time;
+
+ sd_vtx->prim = isect->prim;
+ sd_vtx->ray_length = isect->t;
+
+ sd_vtx->u = isect->u;
+ sd_vtx->v = isect->v;
+
+ sd_vtx->shader = kernel_tex_fetch(__tri_shader, sd_vtx->prim);
+
+ float3 verts[3];
+ float3 normals[3];
+ uint4 tri_vindex = kernel_tex_fetch(__tri_vindex, sd_vtx->prim);
+
+ if (sd_vtx->type & PRIMITIVE_TRIANGLE) {
+ /* Static triangle. */
+
+ /* Load triangle vertices. */
+ verts[0] = kernel_tex_fetch(__tri_verts, tri_vindex.w + 0);
+ verts[1] = kernel_tex_fetch(__tri_verts, tri_vindex.w + 1);
+ verts[2] = kernel_tex_fetch(__tri_verts, tri_vindex.w + 2);
+
+ /* Vectors. */
+ sd_vtx->P = triangle_point_from_uv(kg, sd_vtx, isect->object, isect->prim, isect->u, isect->v);
+
+ /* Smooth normal. */
+ if (sd_vtx->shader & SHADER_SMOOTH_NORMAL) {
+ /* Load triangle vertices. */
+ normals[0] = kernel_tex_fetch(__tri_vnormal, tri_vindex.x);
+ normals[1] = kernel_tex_fetch(__tri_vnormal, tri_vindex.y);
+ normals[2] = kernel_tex_fetch(__tri_vnormal, tri_vindex.z);
+ }
+ }
+ else { /* if (sd_vtx->type & PRIMITIVE_MOTION_TRIANGLE) */
+ /* Motion triangle. */
+
+ /* Get motion info. */
+ int numsteps, numverts;
+ object_motion_info(kg, sd_vtx->object, &numsteps, &numverts, NULL);
+
+ /* Figure out which steps we need to fetch and their interpolation factor. */
+ int maxstep = numsteps * 2;
+ int step = min((int)(sd_vtx->time * maxstep), maxstep - 1);
+ float t = sd_vtx->time * maxstep - step;
+
+ /* Find attribute. */
+ int offset = intersection_find_attribute(kg, sd_vtx->object, ATTR_STD_MOTION_VERTEX_POSITION);
+ kernel_assert(offset != ATTR_STD_NOT_FOUND);
+
+ /* Fetch vertex coordinates. */
+ float3 next_verts[3];
+ uint4 tri_vindex = kernel_tex_fetch(__tri_vindex, sd_vtx->prim);
+ motion_triangle_verts_for_step(kg, tri_vindex, offset, numverts, numsteps, step, verts);
+ motion_triangle_verts_for_step(
+ kg, tri_vindex, offset, numverts, numsteps, step + 1, next_verts);
+
+ /* Interpolate between steps. */
+ verts[0] = (1.0f - t) * verts[0] + t * next_verts[0];
+ verts[1] = (1.0f - t) * verts[1] + t * next_verts[1];
+ verts[2] = (1.0f - t) * verts[2] + t * next_verts[2];
+
+ /* Compute refined position. */
+ sd_vtx->P = motion_triangle_point_from_uv(
+ kg, sd_vtx, isect->object, isect->prim, isect->u, isect->v, verts);
+
+ /* Compute smooth normal. */
+ if (sd_vtx->shader & SHADER_SMOOTH_NORMAL) {
+ /* Find attribute. */
+ int offset = intersection_find_attribute(kg, sd_vtx->object, ATTR_STD_MOTION_VERTEX_NORMAL);
+ kernel_assert(offset != ATTR_STD_NOT_FOUND);
+
+ /* Fetch vertex coordinates. */
+ float3 next_normals[3];
+ motion_triangle_normals_for_step(kg, tri_vindex, offset, numverts, numsteps, step, normals);
+ motion_triangle_normals_for_step(
+ kg, tri_vindex, offset, numverts, numsteps, step + 1, next_normals);
+
+ /* Interpolate between steps. */
+ normals[0] = (1.0f - t) * normals[0] + t * next_normals[0];
+ normals[1] = (1.0f - t) * normals[1] + t * next_normals[1];
+ normals[2] = (1.0f - t) * normals[2] + t * next_normals[2];
+ }
+ }
+
+ /* manifold vertex position */
+ vtx->p = sd_vtx->P;
+
+ if (!(sd_vtx->object_flag & SD_OBJECT_TRANSFORM_APPLIED)) {
+ /* Instance transform. */
+ object_position_transform_auto(kg, sd_vtx, &verts[0]);
+ object_position_transform_auto(kg, sd_vtx, &verts[1]);
+ object_position_transform_auto(kg, sd_vtx, &verts[2]);
+ object_normal_transform_auto(kg, sd_vtx, &normals[0]);
+ object_normal_transform_auto(kg, sd_vtx, &normals[1]);
+ object_normal_transform_auto(kg, sd_vtx, &normals[2]);
+ }
+
+ /* Tangent space (position derivatives) wrt barycentric (u, v). */
+ vtx->dp_du = verts[0] - verts[2];
+ vtx->dp_dv = verts[1] - verts[2];
+
+ /* Geometric normal. */
+ vtx->ng = normalize(cross(vtx->dp_du, vtx->dp_dv));
+ if (sd_vtx->object_flag & SD_OBJECT_NEGATIVE_SCALE_APPLIED)
+ vtx->ng = -vtx->ng;
+
+ /* Shading normal. */
+ if (!(sd_vtx->shader & SHADER_SMOOTH_NORMAL)) {
+ vtx->n = vtx->ng;
+ vtx->dn_du = vtx->dn_dv = zero_float3();
+ }
+ else {
+ /* Interpolate normals between vertices. */
+ float n_len;
+ vtx->n = normalize_len(normals[0] * sd_vtx->u + normals[1] * sd_vtx->v +
+ normals[2] * (1.0f - sd_vtx->u - sd_vtx->v),
+ &n_len);
+
+ /* Shading normal derivatives wrt barycentric (u, v)
+ * we calculate the derivative of n = |u*n0 + v*n1 + (1-u-v)*n2| using:
+ * d/du [f(u)/|f(u)|] = [d/du f(u)]/|f(u)| - f(u)/|f(u)|^3 <f(u), d/du f(u)>. */
+ const float inv_n_len = 1.f / n_len;
+ vtx->dn_du = inv_n_len * (normals[0] - normals[2]);
+ vtx->dn_dv = inv_n_len * (normals[1] - normals[2]);
+ vtx->dn_du -= vtx->n * dot(vtx->n, vtx->dn_du);
+ vtx->dn_dv -= vtx->n * dot(vtx->n, vtx->dn_dv);
+ }
+
+ /* dp_du and dp_dv need to be continuous across triangles for the h normal
+ * offset to yield a consistent halfvector while walking on the manifold.
+ * It's usually best to rely on the mesh uv layout, which is assumed to be
+ * continuous across the mesh. */
+ float2 duv0, duv1;
+ bool found_uv = false;
+ AttributeDescriptor uv_desc = find_attribute(kg, sd_vtx, ATTR_STD_GENERATED);
+ if (uv_desc.offset != ATTR_STD_NOT_FOUND) {
+ float3 uvs[3];
+ uvs[0] = kernel_tex_fetch(__attributes_float3, uv_desc.offset + tri_vindex.x);
+ uvs[1] = kernel_tex_fetch(__attributes_float3, uv_desc.offset + tri_vindex.y);
+ uvs[2] = kernel_tex_fetch(__attributes_float3, uv_desc.offset + tri_vindex.z);
+ duv0 = make_float2(uvs[0].x - uvs[2].x, uvs[0].y - uvs[2].y);
+ duv1 = make_float2(uvs[1].x - uvs[2].x, uvs[1].y - uvs[2].y);
+ found_uv = true;
+ }
+ else {
+ uv_desc = find_attribute(kg, sd_vtx, ATTR_STD_UV);
+ if (uv_desc.offset != ATTR_STD_NOT_FOUND) {
+ float2 uvs[3];
+ uvs[0] = kernel_tex_fetch(__attributes_float2, uv_desc.offset + tri_vindex.x);
+ uvs[1] = kernel_tex_fetch(__attributes_float2, uv_desc.offset + tri_vindex.y);
+ uvs[2] = kernel_tex_fetch(__attributes_float2, uv_desc.offset + tri_vindex.z);
+ duv0 = make_float2(uvs[0].x - uvs[2].x, uvs[0].y - uvs[2].y);
+ duv1 = make_float2(uvs[1].x - uvs[2].x, uvs[1].y - uvs[2].y);
+ found_uv = true;
+ }
+ }
+ if (found_uv) {
+ const float det = duv0.x * duv1.y - duv0.y * duv1.x;
+ if (det != 0.f) {
+ const float inv_det = 1.f / det;
+
+ /* Tangent space (position derivatives) wrt texture (u, v). */
+ const float3 dp_du = vtx->dp_du;
+ const float3 dp_dv = vtx->dp_dv;
+ vtx->dp_du = (duv1.y * dp_du - duv0.y * dp_dv) * inv_det;
+ vtx->dp_dv = (-duv1.x * dp_du + duv0.x * dp_dv) * inv_det;
+
+ /* Shading normal derivatives wrt texture (u, v). */
+ const float3 dn_du = vtx->dn_du;
+ const float3 dn_dv = vtx->dn_dv;
+ vtx->dn_du = (duv1.y * dn_du - duv0.y * dn_dv) * inv_det;
+ vtx->dn_dv = (-duv1.x * dn_du + duv0.x * dn_dv) * inv_det;
+ }
+ }
+
+ /* Orthonormalize (dp_du,dp_dv) using a linear transformation, which
+ * we use on (dn_du,dn_dv) as well so the new (u,v) are consistent. */
+ const float inv_len_dp_du = 1.f / len(vtx->dp_du);
+ vtx->dp_du *= inv_len_dp_du;
+ vtx->dn_du *= inv_len_dp_du;
+ const float dpdu_dot_dpdv = dot(vtx->dp_du, vtx->dp_dv);
+ const float3 dp_dv = vtx->dp_dv - dpdu_dot_dpdv * vtx->dp_du;
+ const float3 dn_dv = vtx->dn_dv - dpdu_dot_dpdv * vtx->dn_du;
+ const float inv_len_dp_dv = 1.f / len(dp_dv);
+ vtx->dp_dv = dp_dv * inv_len_dp_dv;
+ vtx->dn_dv = dn_dv * inv_len_dp_dv;
+
+ /* Initialize constraint and its derivates. */
+ vtx->a = vtx->c = zero_float4();
+ vtx->b = make_float4(1.f, 0.f, 0.f, 1.f);
+ vtx->constraint = zero_float2();
+ vtx->n_offset = n_offset;
+
+ /* Closure information. */
+ vtx->bsdf = bsdf;
+ vtx->eta = eta;
+
+ /* Geometric information. */
+ vtx->uv = make_float2(isect->u, isect->v);
+ vtx->object = sd_vtx->object;
+ vtx->prim = sd_vtx->prim;
+ vtx->shader = sd_vtx->shader;
+}
+
+/* Compute constraint derivatives. */
+ccl_device_forceinline bool mnee_compute_constraint_derivatives(
+ int vertex_count,
+ ccl_private ManifoldVertex *vertices,
+ ccl_private const float3 &surface_sample_pos,
+ const bool light_fixed_direction,
+ const float3 light_sample)
+{
+ for (int vi = 0; vi < vertex_count; vi++) {
+ ccl_private ManifoldVertex &v = vertices[vi];
+
+ /* Direction toward surface sample. */
+ float3 wi = (vi == 0) ? surface_sample_pos - v.p : vertices[vi - 1].p - v.p;
+ float ili = len(wi);
+ if (ili < MNEE_MIN_DISTANCE)
+ return false;
+ ili = 1.f / ili;
+ wi *= ili;
+
+ /* Direction toward light sample. */
+ float3 wo = (vi == vertex_count - 1) ?
+ (light_fixed_direction ? light_sample : light_sample - v.p) :
+ vertices[vi + 1].p - v.p;
+ float ilo = len(wo);
+ if (ilo < MNEE_MIN_DISTANCE)
+ return false;
+ ilo = 1.f / ilo;
+ wo *= ilo;
+
+ /* Invert ior if coming from inside. */
+ float eta = v.eta;
+ if (dot(wi, v.ng) < .0f)
+ eta = 1.f / eta;
+
+ /* Half vector. */
+ float3 H = -(wi + eta * wo);
+ float ilh = 1.f / len(H);
+ H *= ilh;
+
+ ilo *= eta * ilh;
+ ili *= ilh;
+
+ /* Local shading frame. */
+ float dp_du_dot_n = dot(v.dp_du, v.n);
+ float3 s = v.dp_du - dp_du_dot_n * v.n;
+ float inv_len_s = 1.f / len(s);
+ s *= inv_len_s;
+ float3 t = cross(v.n, s);
+
+ float3 dH_du, dH_dv;
+
+ /* Constraint derivatives wrt previous vertex. */
+ if (vi > 0) {
+ ccl_private ManifoldVertex &v_prev = vertices[vi - 1];
+ dH_du = (v_prev.dp_du - wi * dot(wi, v_prev.dp_du)) * ili;
+ dH_dv = (v_prev.dp_dv - wi * dot(wi, v_prev.dp_dv)) * ili;
+ dH_du -= H * dot(dH_du, H);
+ dH_dv -= H * dot(dH_dv, H);
+ dH_du = -dH_du;
+ dH_dv = -dH_dv;
+
+ v.a = make_float4(dot(dH_du, s), dot(dH_dv, s), dot(dH_du, t), dot(dH_dv, t));
+ }
+
+ /* Constraint derivatives wrt current vertex. */
+ if (vi == vertex_count - 1 && light_fixed_direction) {
+ dH_du = ili * (-v.dp_du + wi * dot(wi, v.dp_du));
+ dH_dv = ili * (-v.dp_dv + wi * dot(wi, v.dp_dv));
+ }
+ else {
+ dH_du = -v.dp_du * (ili + ilo) + wi * (dot(wi, v.dp_du) * ili) +
+ wo * (dot(wo, v.dp_du) * ilo);
+ dH_dv = -v.dp_dv * (ili + ilo) + wi * (dot(wi, v.dp_dv) * ili) +
+ wo * (dot(wo, v.dp_dv) * ilo);
+ }
+ dH_du -= H * dot(dH_du, H);
+ dH_dv -= H * dot(dH_dv, H);
+ dH_du = -dH_du;
+ dH_dv = -dH_dv;
+
+ float3 ds_du = -inv_len_s * (dot(v.dp_du, v.dn_du) * v.n + dp_du_dot_n * v.dn_du);
+ float3 ds_dv = -inv_len_s * (dot(v.dp_du, v.dn_dv) * v.n + dp_du_dot_n * v.dn_dv);
+ ds_du -= s * dot(s, ds_du);
+ ds_dv -= s * dot(s, ds_dv);
+ float3 dt_du = cross(v.dn_du, s) + cross(v.n, ds_du);
+ float3 dt_dv = cross(v.dn_dv, s) + cross(v.n, ds_dv);
+
+ v.b = make_float4(dot(dH_du, s) + dot(H, ds_du),
+ dot(dH_dv, s) + dot(H, ds_dv),
+ dot(dH_du, t) + dot(H, dt_du),
+ dot(dH_dv, t) + dot(H, dt_dv));
+
+ /* Constraint derivatives wrt next vertex. */
+ if (vi < vertex_count - 1) {
+ ccl_private ManifoldVertex &v_next = vertices[vi + 1];
+ dH_du = (v_next.dp_du - wo * dot(wo, v_next.dp_du)) * ilo;
+ dH_dv = (v_next.dp_dv - wo * dot(wo, v_next.dp_dv)) * ilo;
+ dH_du -= H * dot(dH_du, H);
+ dH_dv -= H * dot(dH_dv, H);
+ dH_du = -dH_du;
+ dH_dv = -dH_dv;
+
+ v.c = make_float4(dot(dH_du, s), dot(dH_dv, s), dot(dH_du, t), dot(dH_dv, t));
+ }
+
+ /* Constraint vector wrt. the local shading frame. */
+ v.constraint = make_float2(dot(s, H), dot(t, H)) - v.n_offset;
+ }
+ return true;
+}
+
+/* Invert (block) constraint derivative matrix and solve linear system so we can map dh back to dx:
+ * dh / dx = A
+ * dx = inverse(A) x dh
+ * to use for specular specular manifold walk
+ * (See for example http://faculty.washington.edu/finlayso/ebook/algebraic/advanced/LUtri.htm
+ * for block tridiagonal matrix based linear system solve) */
+ccl_device_forceinline bool mnee_solve_matrix_h_to_x(int vertex_count,
+ ccl_private ManifoldVertex *vertices,
+ ccl_private float2 *dx)
+{
+ float4 Li[MNEE_MAX_CAUSTIC_CASTERS];
+ float2 C[MNEE_MAX_CAUSTIC_CASTERS];
+
+ /* Block tridiagonal LU factorization. */
+ float4 Lk = vertices[0].b;
+ if (mat22_inverse(Lk, Li[0]) == 0.f)
+ return false;
+
+ C[0] = vertices[0].constraint;
+
+ for (int k = 1; k < vertex_count; k++) {
+ float4 A = mat22_mult(vertices[k].a, Li[k - 1]);
+
+ Lk = vertices[k].b - mat22_mult(A, vertices[k - 1].c);
+ if (mat22_inverse(Lk, Li[k]) == 0.f)
+ return false;
+
+ C[k] = vertices[k].constraint - mat22_mult(A, C[k - 1]);
+ }
+
+ dx[vertex_count - 1] = mat22_mult(Li[vertex_count - 1], C[vertex_count - 1]);
+ for (int k = vertex_count - 2; k > -1; k--)
+ dx[k] = mat22_mult(Li[k], C[k] - mat22_mult(vertices[k].c, dx[k + 1]));
+
+ return true;
+}
+
+/* Newton solver to walk on specular manifold. */
+ccl_device_forceinline bool mnee_newton_solver(KernelGlobals kg,
+ ccl_private const ShaderData *sd,
+ ccl_private ShaderData *sd_vtx,
+ ccl_private const LightSample *ls,
+ int vertex_count,
+ ccl_private ManifoldVertex *vertices)
+{
+ float2 dx[MNEE_MAX_CAUSTIC_CASTERS];
+ ManifoldVertex tentative[MNEE_MAX_CAUSTIC_CASTERS];
+
+ Ray projection_ray;
+ projection_ray.self.light_object = OBJECT_NONE;
+ projection_ray.self.light_prim = PRIM_NONE;
+ projection_ray.dP = differential_make_compact(sd->dP);
+ projection_ray.dD = differential_zero_compact();
+ projection_ray.time = sd->time;
+ Intersection projection_isect;
+
+ const bool light_fixed_direction = (ls->t == FLT_MAX);
+ const float3 light_sample = light_fixed_direction ? ls->D : ls->P;
+
+ /* We start gently, potentially ramping up to beta = 1, since target configurations
+ * far from the seed path can send the proposed solution further than the linearized
+ * local differential geometric quantities are meant for (especially dn/du and dn/dv). */
+ float beta = .1f;
+ bool reduce_stepsize = false;
+ bool resolve_constraint = true;
+ for (int iteration = 0; iteration < MNEE_MAX_ITERATIONS; iteration++) {
+ if (resolve_constraint) {
+ /* Calculate constraintand its derivatives for vertices. */
+ if (!mnee_compute_constraint_derivatives(
+ vertex_count, vertices, sd->P, light_fixed_direction, light_sample))
+ return false;
+
+ /* Calculate constraint norm. */
+ float constraint_norm = 0.f;
+ for (int vi = 0; vi < vertex_count; vi++)
+ constraint_norm = fmaxf(constraint_norm, len(vertices[vi].constraint));
+
+ /* Return if solve successful. */
+ if (constraint_norm < MNEE_SOLVER_THRESHOLD)
+ return true;
+
+ /* Invert derivative matrix. */
+ if (!mnee_solve_matrix_h_to_x(vertex_count, vertices, dx))
+ return false;
+ }
+
+ /* Construct tentative new vertices and project back onto surface. */
+ for (int vi = 0; vi < vertex_count; vi++) {
+ ccl_private ManifoldVertex &mv = vertices[vi];
+
+ /* Tentative new position on linearized manifold (tangent plane). */
+ float3 tentative_p = mv.p - beta * (dx[vi].x * mv.dp_du + dx[vi].y * mv.dp_dv);
+
+ /* For certain configs, the first solve ends up below the receiver. */
+ if (vi == 0) {
+ const float3 wo = tentative_p - sd->P;
+ if (dot(sd->Ng, wo) <= 0.f) {
+ /* Change direction for the 1st interface. */
+ tentative_p = mv.p + beta * (dx[vi].x * mv.dp_du + dx[vi].y * mv.dp_dv);
+ }
+ }
+
+ /* Project tentative point from tangent plane back to surface
+ * we ignore all other intersections since this tentative path could lead
+ * valid to a valid path even if occluded. */
+ if (vi == 0) {
+ projection_ray.self.object = sd->object;
+ projection_ray.self.prim = sd->prim;
+ projection_ray.P = sd->P;
+ }
+ else {
+ ccl_private const ManifoldVertex &pv = vertices[vi - 1];
+ projection_ray.self.object = pv.object;
+ projection_ray.self.prim = pv.prim;
+ projection_ray.P = pv.p;
+ }
+ projection_ray.D = normalize_len(tentative_p - projection_ray.P, &projection_ray.t);
+ projection_ray.t *= MNEE_PROJECTION_DISTANCE_MULTIPLIER;
+
+ bool projection_success = false;
+ for (int isect_count = 0; isect_count < MNEE_MAX_INTERSECTION_COUNT; isect_count++) {
+ bool hit = scene_intersect(kg, &projection_ray, PATH_RAY_TRANSMIT, &projection_isect);
+ if (!hit)
+ break;
+
+ int hit_object = (projection_isect.object == OBJECT_NONE) ?
+ kernel_tex_fetch(__prim_object, projection_isect.prim) :
+ projection_isect.object;
+
+ if (hit_object == mv.object) {
+ projection_success = true;
+ break;
+ }
+
+ projection_ray.self.object = projection_isect.object;
+ projection_ray.self.prim = projection_isect.prim;
+ projection_ray.P += projection_isect.t * projection_ray.D;
+ projection_ray.t -= projection_isect.t;
+ }
+ if (!projection_success) {
+ reduce_stepsize = true;
+ break;
+ }
+
+ /* Setup corrected manifold vertex. */
+ mnee_setup_manifold_vertex(kg,
+ &tentative[vi],
+ mv.bsdf,
+ mv.eta,
+ mv.n_offset,
+ &projection_ray,
+ &projection_isect,
+ sd_vtx);
+ }
+
+ /* Check that tentative path is still transmissive. */
+ if (!reduce_stepsize) {
+ for (int vi = 0; vi < vertex_count; vi++) {
+ ccl_private ManifoldVertex &tv = tentative[vi];
+
+ /* Direction toward surface sample. */
+ const float3 wi = (vi == 0 ? sd->P : tentative[vi - 1].p) - tv.p;
+ /* Direction toward light sample. */
+ const float3 wo = (vi == vertex_count - 1) ? light_fixed_direction ? ls->D : ls->P - tv.p :
+ tentative[vi + 1].p - tv.p;
+
+ if (dot(tv.n, wi) * dot(tv.n, wo) >= 0.f) {
+ reduce_stepsize = true;
+ break;
+ }
+ }
+ }
+
+ if (reduce_stepsize) {
+ /* Adjust step if can't land on right surface. */
+ reduce_stepsize = false;
+ resolve_constraint = false;
+ beta *= .5f;
+ continue;
+ }
+
+ /* Copy tentative vertices to main vertex list. */
+ for (int vi = 0; vi < vertex_count; vi++)
+ vertices[vi] = tentative[vi];
+
+ /* Increase the step to get back to 1. */
+ resolve_constraint = true;
+ beta = min(1.f, 2.f * beta);
+ }
+
+ return false;
+}
+
+/* Sample bsdf in half-vector measure. */
+ccl_device_forceinline float2
+mnee_sample_bsdf_dh(ClosureType type, float alpha_x, float alpha_y, float sample_u, float sample_v)
+{
+ float alpha2;
+ float cos_phi, sin_phi;
+
+ if (alpha_x == alpha_y) {
+ float phi = sample_v * M_2PI_F;
+ fast_sincosf(phi, &sin_phi, &cos_phi);
+ alpha2 = alpha_x * alpha_x;
+ }
+ else {
+ float phi = atanf(alpha_y / alpha_x * tanf(M_2PI_F * sample_v + M_PI_2_F));
+ if (sample_v > .5f)
+ phi += M_PI_F;
+ fast_sincosf(phi, &sin_phi, &cos_phi);
+ float alpha_x2 = alpha_x * alpha_x;
+ float alpha_y2 = alpha_y * alpha_y;
+ alpha2 = 1.f / (cos_phi * cos_phi / alpha_x2 + sin_phi * sin_phi / alpha_y2);
+ }
+
+ /* Map sampled angles to micro-normal direction h. */
+ float tan2_theta = alpha2;
+ if (type == CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID) {
+ tan2_theta *= -logf(1.0f - sample_u);
+ }
+ else { /* if (type == CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID || type ==
+ CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_FRESNEL_ID) */
+ tan2_theta *= sample_u / (1.0f - sample_u);
+ }
+ float cos2_theta = 1.0f / (1.0f + tan2_theta);
+ float sin_theta = safe_sqrtf(1.0f - cos2_theta);
+ return make_float2(cos_phi * sin_theta, sin_phi * sin_theta);
+}
+
+/* Evaluate product term inside eq.6 at solution interface vi
+ * divided by corresponding sampled pdf:
+ * fr(vi)_do / pdf_dh(vi) x |do/dh| x |n.wo / n.h|
+ * We assume here that the pdf (in half-vector measure) is the same as
+ * the one calculation when sampling the microfacet normals from the
+ * specular chain above: this allows us to simplify the bsdf weight */
+ccl_device_forceinline float3 mnee_eval_bsdf_contribution(ccl_private ShaderClosure *closure,
+ float3 wi,
+ float3 wo)
+{
+ ccl_private MicrofacetBsdf *bsdf = (ccl_private MicrofacetBsdf *)closure;
+
+ float cosNO = dot(bsdf->N, wi);
+ float cosNI = dot(bsdf->N, wo);
+
+ float3 Ht = normalize(-(bsdf->ior * wo + wi));
+ float cosHO = dot(Ht, wi);
+
+ float alpha2 = bsdf->alpha_x * bsdf->alpha_y;
+ float cosThetaM = dot(bsdf->N, Ht);
+
+ float G;
+ if (bsdf->type == CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID) {
+ /* Eq. 26, 27: now calculate G1(i,m) and G1(o,m). */
+ G = bsdf_beckmann_G1(bsdf->alpha_x, cosNO) * bsdf_beckmann_G1(bsdf->alpha_x, cosNI);
+ }
+ else { /* if (type == CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID || type ==
+ CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_FRESNEL_ID) */
+ /* Eq. 34: now calculate G1(i,m) and G1(o,m). */
+ G = (2.f / (1.f + safe_sqrtf(1.f + alpha2 * (1.f - cosNO * cosNO) / (cosNO * cosNO)))) *
+ (2.f / (1.f + safe_sqrtf(1.f + alpha2 * (1.f - cosNI * cosNI) / (cosNI * cosNI))));
+ }
+
+ /*
+ * bsdf_do = (1 - F) * D_do * G * |h.wi| / (n.wi * n.wo)
+ * pdf_dh = D_dh * cosThetaM
+ * D_do = D_dh * |dh/do|
+ *
+ * contribution = bsdf_do * |do/dh| * |n.wo / n.h| / pdf_dh
+ * = (1 - F) * G * |h.wi / (n.wi * n.h^2)|
+ */
+ return bsdf->weight * G * fabsf(cosHO / (cosNO * sqr(cosThetaM)));
+}
+
+/* Compute transfer matrix determinant |T1| = |dx1/dxn| (and |dh/dx| in the process) */
+ccl_device_forceinline bool mnee_compute_transfer_matrix(ccl_private const ShaderData *sd,
+ ccl_private const LightSample *ls,
+ int vertex_count,
+ ccl_private ManifoldVertex *vertices,
+ ccl_private float *dx1_dxlight,
+ ccl_private float *dh_dx)
+{
+ /* Simplified block tridiagonal LU factorization. */
+ float4 Li;
+ float4 U[MNEE_MAX_CAUSTIC_CASTERS - 1];
+
+ float4 Lk = vertices[0].b;
+ float Lk_det = mat22_inverse(Lk, Li);
+ if (Lk_det == 0.f)
+ return false;
+
+ float det_dh_dx = Lk_det;
+
+ for (int k = 1; k < vertex_count; k++) {
+ U[k - 1] = mat22_mult(Li, vertices[k - 1].c);
+
+ Lk = vertices[k].b - mat22_mult(vertices[k].a, U[k - 1]);
+ Lk_det = mat22_inverse(Lk, Li);
+ if (Lk_det == 0.f)
+ return false;
+
+ det_dh_dx *= Lk_det;
+ }
+
+ /* Fill out constraint derivatives wrt light vertex param. */
+
+ /* Local shading frame at last free vertex. */
+ int mi = vertex_count - 1;
+ ccl_private const ManifoldVertex &m = vertices[mi];
+
+ float3 s = normalize(m.dp_du - dot(m.dp_du, m.n) * m.n);
+ float3 t = cross(m.n, s);
+
+ /* Local differential geometry. */
+ float3 dp_du, dp_dv;
+ mnee_make_orthonormals(ls->Ng, &dp_du, &dp_dv);
+
+ /* Direction toward surface sample. */
+ float3 wi = vertex_count == 1 ? sd->P - m.p : vertices[mi - 1].p - m.p;
+ float ili = 1.f / len(wi);
+ wi *= ili;
+
+ /* Invert ior if coming from inside. */
+ float eta = m.eta;
+ if (dot(wi, m.ng) < .0f)
+ eta = 1.f / eta;
+
+ float dxn_dwn;
+ float4 dc_dlight;
+
+ if (ls->t == FLT_MAX) {
+ /* Constant direction toward light sample. */
+ float3 wo = ls->D;
+
+ /* Half vector. */
+ float3 H = -(wi + eta * wo);
+ float ilh = 1.f / len(H);
+ H *= ilh;
+
+ float ilo = -eta * ilh;
+
+ float cos_theta = dot(wo, m.n);
+ float sin_theta = safe_sqrtf(1.f - sqr(cos_theta));
+ float cos_phi = dot(wo, s);
+ float sin_phi = safe_sqrtf(1.f - sqr(cos_phi));
+
+ /* Wo = (cos_phi * sin_theta) * s + (sin_phi * sin_theta) * t + cos_theta * n. */
+ float3 dH_dtheta = ilo * (cos_theta * (cos_phi * s + sin_phi * t) - sin_theta * m.n);
+ float3 dH_dphi = ilo * sin_theta * (-sin_phi * s + cos_phi * t);
+ dH_dtheta -= H * dot(dH_dtheta, H);
+ dH_dphi -= H * dot(dH_dphi, H);
+
+ /* constraint derivatives wrt light direction expressed
+ * in spherical coordinates (theta, phi). */
+ dc_dlight = make_float4(
+ dot(dH_dtheta, s), dot(dH_dphi, s), dot(dH_dtheta, t), dot(dH_dphi, t));
+
+ /* Jacobian to convert dtheta x dphi to dw measure. */
+ dxn_dwn = 1.f / fmaxf(MNEE_MIN_DISTANCE, fabsf(sin_theta));
+ }
+ else {
+ /* Direction toward light sample. */
+ float3 wo = ls->P - m.p;
+ float ilo = 1.f / len(wo);
+ wo *= ilo;
+
+ /* Half vector. */
+ float3 H = -(wi + eta * wo);
+ float ilh = 1.f / len(H);
+ H *= ilh;
+
+ ilo *= eta * ilh;
+
+ float3 dH_du = (dp_du - wo * dot(wo, dp_du)) * ilo;
+ float3 dH_dv = (dp_dv - wo * dot(wo, dp_dv)) * ilo;
+ dH_du -= H * dot(dH_du, H);
+ dH_dv -= H * dot(dH_dv, H);
+ dH_du = -dH_du;
+ dH_dv = -dH_dv;
+
+ dc_dlight = make_float4(dot(dH_du, s), dot(dH_dv, s), dot(dH_du, t), dot(dH_dv, t));
+
+ /* Neutral value since dc_dlight is already in the desired vertex area measure. */
+ dxn_dwn = 1.f;
+ }
+
+ /* Compute transfer matrix. */
+ float4 Tp = -mat22_mult(Li, dc_dlight);
+ for (int k = vertex_count - 2; k > -1; k--)
+ Tp = -mat22_mult(U[k], Tp);
+
+ *dx1_dxlight = fabsf(mat22_determinant(Tp)) * dxn_dwn;
+ *dh_dx = fabsf(det_dh_dx);
+ return true;
+}
+
+/* Calculate the path contribution. */
+ccl_device_forceinline bool mnee_path_contribution(KernelGlobals kg,
+ IntegratorState state,
+ ccl_private ShaderData *sd,
+ ccl_private ShaderData *sd_mnee,
+ ccl_private LightSample *ls,
+ int vertex_count,
+ ccl_private ManifoldVertex *vertices,
+ ccl_private BsdfEval *throughput)
+{
+ float wo_len;
+ float3 wo = normalize_len(vertices[0].p - sd->P, &wo_len);
+
+ /* Initialize throughput and evaluate receiver bsdf * |n.wo|. */
+ shader_bsdf_eval(kg, sd, wo, false, throughput, ls->shader);
+
+ /* Update light sample with new position / direct.ion
+ * and keep pdf in vertex area measure */
+ mnee_update_light_sample(kg, vertices[vertex_count - 1].p, ls);
+
+ /* Evaluate light sam.ple
+ * in case the light has a node-based shader:
+ * 1. sd_mnee will be used to store light data, which is why we need to do
+ * this evaluation here. sd_mnee needs to contain the solution's last
+ * interface data at the end of the call for the shadow ray setup to work.
+ * 2. ls needs to contain the last interface data for the light shader to
+ * evaluate properly */
+ float3 light_eval = light_sample_shader_eval(kg, state, sd_mnee, ls, sd->time);
+ bsdf_eval_mul3(throughput, light_eval / ls->pdf);
+
+ /* Generalized geometry term. */
+
+ float dh_dx;
+ float dx1_dxlight;
+ if (!mnee_compute_transfer_matrix(sd, ls, vertex_count, vertices, &dx1_dxlight, &dh_dx))
+ return false;
+
+ /* Receiver bsdf eval above already contains |n.wo|. */
+ const float dw0_dx1 = fabsf(dot(wo, vertices[0].n)) / sqr(wo_len);
+
+ const float G = dw0_dx1 * dx1_dxlight;
+ bsdf_eval_mul(throughput, G);
+
+ /* Specular reflectance. */
+
+ /* Probe ray / isect. */
+ Ray probe_ray;
+ probe_ray.self.light_object = ls->object;
+ probe_ray.self.light_prim = ls->prim;
+ probe_ray.dP = differential_make_compact(sd->dP);
+ probe_ray.dD = differential_zero_compact();
+ probe_ray.time = sd->time;
+ Intersection probe_isect;
+
+ probe_ray.self.object = sd->object;
+ probe_ray.self.prim = sd->prim;
+ probe_ray.P = sd->P;
+
+ float3 wi;
+ float wi_len;
+ for (int vi = 0; vi < vertex_count; vi++) {
+ ccl_private const ManifoldVertex &v = vertices[vi];
+
+ /* Check visiblity. */
+ probe_ray.D = normalize_len(v.p - probe_ray.P, &probe_ray.t);
+ if (scene_intersect(kg, &probe_ray, PATH_RAY_TRANSMIT, &probe_isect)) {
+ int hit_object = (probe_isect.object == OBJECT_NONE) ?
+ kernel_tex_fetch(__prim_object, probe_isect.prim) :
+ probe_isect.object;
+ /* Test whether the ray hit the appropriate object at its intended location. */
+ if (hit_object != v.object || fabsf(probe_ray.t - probe_isect.t) > MNEE_MIN_DISTANCE)
+ return false;
+ }
+ probe_ray.self.object = v.object;
+ probe_ray.self.prim = v.prim;
+ probe_ray.P = v.p;
+
+ /* Set view looking dir. */
+ wi = -wo;
+ wi_len = wo_len;
+
+ /* Setup shader data for vertex vi. */
+ shader_setup_from_sample(kg,
+ sd_mnee,
+ v.p,
+ v.n,
+ wi,
+ v.shader,
+ v.object,
+ v.prim,
+ v.uv.x,
+ v.uv.y,
+ wi_len,
+ sd->time,
+ false,
+ LAMP_NONE);
+
+ /* Evaluate shader nodes at solution vi. */
+ shader_eval_surface<KERNEL_FEATURE_NODE_MASK_SURFACE_SHADOW>(
+ kg, state, sd_mnee, NULL, PATH_RAY_DIFFUSE, true);
+
+ /* Set light looking dir. */
+ wo = (vi == vertex_count - 1) ? (ls->t == FLT_MAX ? ls->D : ls->P - v.p) :
+ vertices[vi + 1].p - v.p;
+ wo = normalize_len(wo, &wo_len);
+
+ /* Evaluate product term inside eq.6 at solution interface. vi
+ * divided by corresponding sampled pdf:
+ * fr(vi)_do / pdf_dh(vi) x |do/dh| x |n.wo / n.h| */
+ float3 bsdf_contribution = mnee_eval_bsdf_contribution(v.bsdf, wi, wo);
+ bsdf_eval_mul3(throughput, bsdf_contribution);
+ }
+
+ return true;
+}
+
+/* Manifold next event estimation path sampling. */
+ccl_device_forceinline bool kernel_path_mnee_sample(KernelGlobals kg,
+ IntegratorState state,
+ ccl_private ShaderData *sd,
+ ccl_private ShaderData *sd_mnee,
+ ccl_private const RNGState *rng_state,
+ ccl_private LightSample *ls,
+ ccl_private BsdfEval *throughput)
+{
+ /*
+ * 1. send seed ray from shading point to light sample position (or along sampled light
+ * direction), making sure it intersects a caustic caster at least once, ignoring all other
+ * intersections (the final path could be valid even though objects could occlude the light
+ * this seed point), building an array of manifold vertices.
+ */
+
+ /* Setup probe ray. */
+ Ray probe_ray;
+ probe_ray.self.object = sd->object;
+ probe_ray.self.prim = sd->prim;
+ probe_ray.self.light_object = ls->object;
+ probe_ray.self.light_prim = ls->prim;
+ probe_ray.P = sd->P;
+ if (ls->t == FLT_MAX) {
+ /* Distant / env light. */
+ probe_ray.D = ls->D;
+ probe_ray.t = ls->t;
+ }
+ else {
+ /* Other lights, avoid self-intersection. */
+ probe_ray.D = ls->P - probe_ray.P;
+ probe_ray.D = normalize_len(probe_ray.D, &probe_ray.t);
+ }
+ probe_ray.dP = differential_make_compact(sd->dP);
+ probe_ray.dD = differential_zero_compact();
+ probe_ray.time = sd->time;
+ Intersection probe_isect;
+
+ ManifoldVertex vertices[MNEE_MAX_CAUSTIC_CASTERS];
+
+ int vertex_count = 0;
+ for (int isect_count = 0; isect_count < MNEE_MAX_INTERSECTION_COUNT; isect_count++) {
+ bool hit = scene_intersect(kg, &probe_ray, PATH_RAY_TRANSMIT, &probe_isect);
+ if (!hit)
+ break;
+
+ const int object_flags = intersection_get_object_flags(kg, &probe_isect);
+ if (object_flags & SD_OBJECT_CAUSTICS_CASTER) {
+
+ /* Do we have enough slots. */
+ if (vertex_count >= MNEE_MAX_CAUSTIC_CASTERS)
+ return false;
+
+ ccl_private ManifoldVertex &mv = vertices[vertex_count++];
+
+ /* Setup shader data on caustic caster and evaluate context. */
+ shader_setup_from_ray(kg, sd_mnee, &probe_ray, &probe_isect);
+
+ /* Last bool argument is the MNEE flag (for TINY_MAX_CLOSURE cap in kernel_shader.h). */
+ shader_eval_surface<KERNEL_FEATURE_NODE_MASK_SURFACE_SHADOW>(
+ kg, state, sd_mnee, NULL, PATH_RAY_DIFFUSE, true);
+
+ /* get and sample refraction bsdf. */
+ bool found_transimissive_microfacet_bsdf = false;
+ for (int ci = 0; ci < sd_mnee->num_closure; ci++) {
+ ccl_private ShaderClosure *bsdf = &sd_mnee->closure[ci];
+ if (bsdf->type == CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID ||
+ bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID) {
+
+ found_transimissive_microfacet_bsdf = true;
+ ccl_private MicrofacetBsdf *microfacet_bsdf = (ccl_private MicrofacetBsdf *)bsdf;
+
+ /* Figure out appropriate index of refraction ratio. */
+ const float eta = (sd_mnee->flag & SD_BACKFACING) ? 1.0f / microfacet_bsdf->ior :
+ microfacet_bsdf->ior;
+
+ /* Sample transmissive microfacet bsdf. */
+ float bsdf_u, bsdf_v;
+ path_state_rng_2D(kg, rng_state, PRNG_BSDF_U, &bsdf_u, &bsdf_v);
+ float2 h = mnee_sample_bsdf_dh(
+ bsdf->type, microfacet_bsdf->alpha_x, microfacet_bsdf->alpha_y, bsdf_u, bsdf_v);
+
+ /* Setup differential geometry on vertex. */
+ mnee_setup_manifold_vertex(kg, &mv, bsdf, eta, h, &probe_ray, &probe_isect, sd_mnee);
+ break;
+ }
+ }
+ if (!found_transimissive_microfacet_bsdf)
+ return false;
+ }
+
+ probe_ray.self.object = probe_isect.object;
+ probe_ray.self.prim = probe_isect.prim;
+ probe_ray.P += probe_isect.t * probe_ray.D;
+ if (ls->t != FLT_MAX)
+ probe_ray.t -= probe_isect.t;
+ };
+
+ /* Mark the manifold walk invalid to keep mollification on by default. */
+ INTEGRATOR_STATE_WRITE(state, path, mnee) &= ~PATH_MNEE_VALID;
+
+ if (vertex_count == 0)
+ return false;
+
+ /* Check whether the transmission depth limit is reached before continuing. */
+ const int transmission_bounce = INTEGRATOR_STATE(state, path, transmission_bounce) +
+ vertex_count;
+ if (transmission_bounce >= kernel_data.integrator.max_transmission_bounce)
+ return false;
+
+ /* Check whether the diffuse depth limit is reached before continuing. */
+ const int diffuse_bounce = INTEGRATOR_STATE(state, path, diffuse_bounce) + 1;
+ if (diffuse_bounce >= kernel_data.integrator.max_diffuse_bounce)
+ return false;
+
+ /* Check whether the overall depth limit is reached before continuing. */
+ const int bounce = INTEGRATOR_STATE(state, path, bounce) + diffuse_bounce + transmission_bounce;
+ if (bounce >= kernel_data.integrator.max_bounce)
+ return false;
+
+ /* Mark the manifold walk valid to turn off mollification regardless of how successful the walk
+ * is: this is noticeable when another mnee is performed deeper in the path, for an internally
+ * reflected ray for example. If mollification was active for the reflection, a clear
+ * discontinuity is visible between direct and indirect contributions */
+ INTEGRATOR_STATE_WRITE(state, path, mnee) |= PATH_MNEE_VALID;
+
+ /* 2. Walk on the specular manifold to find vertices on the
+ * casters that satisfy snell's law for each interface
+ */
+ if (mnee_newton_solver(kg, sd, sd_mnee, ls, vertex_count, vertices)) {
+ /* 3. If a solution exists, calculate contribution of the corresponding path */
+ if (!mnee_path_contribution(kg, state, sd, sd_mnee, ls, vertex_count, vertices, throughput))
+ return false;
+
+ return true;
+ }
+
+ return false;
+}
+
+CCL_NAMESPACE_END
+
+#endif /* __MNEE__ */
diff --git a/intern/cycles/kernel/integrator/path_state.h b/intern/cycles/kernel/integrator/path_state.h
index e6bdf21499c..ec93ac6d46f 100644
--- a/intern/cycles/kernel/integrator/path_state.h
+++ b/intern/cycles/kernel/integrator/path_state.h
@@ -57,6 +57,10 @@ ccl_device_inline void path_state_init_integrator(KernelGlobals kg,
INTEGRATOR_STATE_WRITE(state, path, continuation_probability) = 1.0f;
INTEGRATOR_STATE_WRITE(state, path, throughput) = make_float3(1.0f, 1.0f, 1.0f);
+#ifdef __MNEE__
+ INTEGRATOR_STATE_WRITE(state, path, mnee) = 0;
+#endif
+
INTEGRATOR_STATE_WRITE(state, isect, object) = OBJECT_NONE;
INTEGRATOR_STATE_WRITE(state, isect, prim) = PRIM_NONE;
diff --git a/intern/cycles/kernel/integrator/shade_background.h b/intern/cycles/kernel/integrator/shade_background.h
index 69dc3dc772d..62b3ce1c15c 100644
--- a/intern/cycles/kernel/integrator/shade_background.h
+++ b/intern/cycles/kernel/integrator/shade_background.h
@@ -101,6 +101,22 @@ ccl_device_inline void integrate_background(KernelGlobals kg,
#endif
}
+#ifdef __MNEE__
+ if (INTEGRATOR_STATE(state, path, mnee) & PATH_MNEE_CULL_LIGHT_CONNECTION) {
+ if (kernel_data.background.use_mis) {
+ for (int lamp = 0; lamp < kernel_data.integrator.num_all_lights; lamp++) {
+ /* This path should have been resolved with mnee, it will
+ * generate a firefly for small lights since it is improbable. */
+ const ccl_global KernelLight *klight = &kernel_tex_fetch(__lights, lamp);
+ if (klight->type == LIGHT_BACKGROUND && klight->use_caustics) {
+ eval_background = false;
+ break;
+ }
+ }
+ }
+ }
+#endif /* __MNEE__ */
+
/* Evaluate background shader. */
float3 L = (eval_background) ? integrator_eval_background_shader(kg, state, render_buffer) :
zero_float3();
@@ -140,6 +156,16 @@ ccl_device_inline void integrate_distant_lights(KernelGlobals kg,
}
#endif
+#ifdef __MNEE__
+ if (INTEGRATOR_STATE(state, path, mnee) & PATH_MNEE_CULL_LIGHT_CONNECTION) {
+ /* This path should have been resolved with mnee, it will
+ * generate a firefly for small lights since it is improbable. */
+ const ccl_global KernelLight *klight = &kernel_tex_fetch(__lights, lamp);
+ if (klight->use_caustics)
+ return;
+ }
+#endif /* __MNEE__ */
+
/* Evaluate light shader. */
/* TODO: does aliasing like this break automatic SoA in CUDA? */
ShaderDataTinyStorage emission_sd_storage;
@@ -160,7 +186,8 @@ ccl_device_inline void integrate_distant_lights(KernelGlobals kg,
/* Write to render buffer. */
const float3 throughput = INTEGRATOR_STATE(state, path, throughput);
- kernel_accum_emission(kg, state, throughput * light_eval, render_buffer);
+ kernel_accum_emission(
+ kg, state, throughput * light_eval, render_buffer, kernel_data.background.lightgroup);
}
}
}
diff --git a/intern/cycles/kernel/integrator/shade_light.h b/intern/cycles/kernel/integrator/shade_light.h
index 4a519a76ed0..be926c78439 100644
--- a/intern/cycles/kernel/integrator/shade_light.h
+++ b/intern/cycles/kernel/integrator/shade_light.h
@@ -78,7 +78,7 @@ ccl_device_inline void integrate_light(KernelGlobals kg,
/* Write to render buffer. */
const float3 throughput = INTEGRATOR_STATE(state, path, throughput);
- kernel_accum_emission(kg, state, throughput * light_eval, render_buffer);
+ kernel_accum_emission(kg, state, throughput * light_eval, render_buffer, ls.group);
}
ccl_device void integrator_shade_light(KernelGlobals kg,
diff --git a/intern/cycles/kernel/integrator/shade_surface.h b/intern/cycles/kernel/integrator/shade_surface.h
index df9af6ca107..a9bf3b5b432 100644
--- a/intern/cycles/kernel/integrator/shade_surface.h
+++ b/intern/cycles/kernel/integrator/shade_surface.h
@@ -6,6 +6,8 @@
#include "kernel/film/accumulate.h"
#include "kernel/film/passes.h"
+#include "kernel/integrator/mnee.h"
+
#include "kernel/integrator/path_state.h"
#include "kernel/integrator/shader_eval.h"
#include "kernel/integrator/subsurface.h"
@@ -85,13 +87,15 @@ ccl_device_forceinline void integrate_surface_emission(KernelGlobals kg,
}
const float3 throughput = INTEGRATOR_STATE(state, path, throughput);
- kernel_accum_emission(kg, state, throughput * L, render_buffer);
+ kernel_accum_emission(
+ kg, state, throughput * L, render_buffer, object_lightgroup(kg, sd->object));
}
#endif /* __EMISSION__ */
#ifdef __EMISSION__
/* Path tracing: sample point on light and evaluate light shader, then
* queue shadow ray to be traced. */
+template<uint node_feature_mask>
ccl_device_forceinline void integrate_surface_direct_light(KernelGlobals kg,
IntegratorState state,
ccl_private ShaderData *sd,
@@ -124,34 +128,65 @@ ccl_device_forceinline void integrate_surface_direct_light(KernelGlobals kg,
* integrate_surface_bounce, evaluate the BSDF, and only then evaluate
* the light shader. This could also move to its own kernel, for
* non-constant light sources. */
- ShaderDataTinyStorage emission_sd_storage;
+ ShaderDataCausticsStorage emission_sd_storage;
ccl_private ShaderData *emission_sd = AS_SHADER_DATA(&emission_sd_storage);
- const float3 light_eval = light_sample_shader_eval(kg, state, emission_sd, &ls, sd->time);
- if (is_zero(light_eval)) {
- return;
- }
-
- /* Evaluate BSDF. */
- const bool is_transmission = shader_bsdf_is_transmission(sd, ls.D);
+ Ray ray ccl_optional_struct_init;
BsdfEval bsdf_eval ccl_optional_struct_init;
- const float bsdf_pdf = shader_bsdf_eval(kg, sd, ls.D, is_transmission, &bsdf_eval, ls.shader);
- bsdf_eval_mul3(&bsdf_eval, light_eval / ls.pdf);
+ const bool is_transmission = shader_bsdf_is_transmission(sd, ls.D);
- if (ls.shader & SHADER_USE_MIS) {
- const float mis_weight = light_sample_mis_weight_nee(kg, ls.pdf, bsdf_pdf);
- bsdf_eval_mul(&bsdf_eval, mis_weight);
+# ifdef __MNEE__
+ bool skip_nee = false;
+ IF_KERNEL_NODES_FEATURE(RAYTRACE)
+ {
+ if (ls.lamp != LAMP_NONE) {
+ /* Is this a caustic light? */
+ const bool use_caustics = kernel_tex_fetch(__lights, ls.lamp).use_caustics;
+ if (use_caustics) {
+ /* Are we on a caustic caster? */
+ if (is_transmission && (sd->object_flag & SD_OBJECT_CAUSTICS_CASTER))
+ return;
+
+ /* Are we on a caustic receiver? */
+ if (!is_transmission && (sd->object_flag & SD_OBJECT_CAUSTICS_RECEIVER))
+ skip_nee = kernel_path_mnee_sample(
+ kg, state, sd, emission_sd, rng_state, &ls, &bsdf_eval);
+ }
+ }
+ }
+ if (skip_nee) {
+ /* Create shadow ray after successful manifold walk:
+ * emission_sd contains the last interface intersection and
+ * the light sample ls has been updated */
+ light_sample_to_surface_shadow_ray(kg, emission_sd, &ls, &ray);
}
+ else
+# endif /* __MNEE__ */
+ {
+ const float3 light_eval = light_sample_shader_eval(kg, state, emission_sd, &ls, sd->time);
+ if (is_zero(light_eval)) {
+ return;
+ }
- /* Path termination. */
- const float terminate = path_state_rng_light_termination(kg, rng_state);
- if (light_sample_terminate(kg, &ls, &bsdf_eval, terminate)) {
- return;
+ /* Evaluate BSDF. */
+ const float bsdf_pdf = shader_bsdf_eval(kg, sd, ls.D, is_transmission, &bsdf_eval, ls.shader);
+ bsdf_eval_mul3(&bsdf_eval, light_eval / ls.pdf);
+
+ if (ls.shader & SHADER_USE_MIS) {
+ const float mis_weight = light_sample_mis_weight_nee(kg, ls.pdf, bsdf_pdf);
+ bsdf_eval_mul(&bsdf_eval, mis_weight);
+ }
+
+ /* Path termination. */
+ const float terminate = path_state_rng_light_termination(kg, rng_state);
+ if (light_sample_terminate(kg, &ls, &bsdf_eval, terminate)) {
+ return;
+ }
+
+ /* Create shadow ray. */
+ light_sample_to_surface_shadow_ray(kg, sd, &ls, &ray);
}
- /* Create shadow ray. */
- Ray ray ccl_optional_struct_init;
- light_sample_to_surface_shadow_ray(kg, sd, &ls, &ray);
const bool is_light = light_sample_is_light(&ls);
/* Branch off shadow kernel. */
@@ -224,6 +259,12 @@ ccl_device_forceinline void integrate_surface_direct_light(KernelGlobals kg,
if (kernel_data.kernel_features & KERNEL_FEATURE_SHADOW_PASS) {
INTEGRATOR_STATE_WRITE(shadow_state, shadow_path, unshadowed_throughput) = throughput;
}
+
+ /* Write Lightgroup, +1 as lightgroup is int but we need to encode into a uint8_t. */
+ INTEGRATOR_STATE_WRITE(
+ shadow_state, shadow_path, lightgroup) = (ls.type != LIGHT_BACKGROUND) ?
+ ls.group + 1 :
+ kernel_data.background.lightgroup + 1;
}
#endif
@@ -501,7 +542,7 @@ ccl_device bool integrate_surface(KernelGlobals kg,
/* Direct light. */
PROFILING_EVENT(PROFILING_SHADE_SURFACE_DIRECT_LIGHT);
- integrate_surface_direct_light(kg, state, &sd, &rng_state);
+ integrate_surface_direct_light<node_feature_mask>(kg, state, &sd, &rng_state);
#if defined(__AO__)
/* Ambient occlusion pass. */
diff --git a/intern/cycles/kernel/integrator/shade_volume.h b/intern/cycles/kernel/integrator/shade_volume.h
index acda4b8e9d1..4a5015946aa 100644
--- a/intern/cycles/kernel/integrator/shade_volume.h
+++ b/intern/cycles/kernel/integrator/shade_volume.h
@@ -653,7 +653,8 @@ ccl_device_forceinline void volume_integrate_heterogeneous(
/* Write accumulated emission. */
if (!is_zero(accum_emission)) {
- kernel_accum_emission(kg, state, accum_emission, render_buffer);
+ kernel_accum_emission(
+ kg, state, accum_emission, render_buffer, object_lightgroup(kg, sd->object));
}
# ifdef __DENOISING_FEATURES__
@@ -833,6 +834,12 @@ ccl_device_forceinline void integrate_volume_direct_light(
INTEGRATOR_STATE_WRITE(shadow_state, shadow_path, unshadowed_throughput) = throughput;
}
+ /* Write Lightgroup, +1 as lightgroup is int but we need to encode into a uint8_t. */
+ INTEGRATOR_STATE_WRITE(
+ shadow_state, shadow_path, lightgroup) = (ls->type != LIGHT_BACKGROUND) ?
+ ls->group + 1 :
+ kernel_data.background.lightgroup + 1;
+
integrator_state_copy_volume_stack_to_shadow(kg, shadow_state, state);
}
# endif
diff --git a/intern/cycles/kernel/integrator/shader_eval.h b/intern/cycles/kernel/integrator/shader_eval.h
index ce76f7a3a90..3066fb661a1 100644
--- a/intern/cycles/kernel/integrator/shader_eval.h
+++ b/intern/cycles/kernel/integrator/shader_eval.h
@@ -157,7 +157,11 @@ ccl_device_inline void shader_prepare_surface_closures(KernelGlobals kg,
*
* Blurring of bsdf after bounces, for rays that have a small likelihood
* of following this particular path (diffuse, rough glossy) */
- if (kernel_data.integrator.filter_glossy != FLT_MAX) {
+ if (kernel_data.integrator.filter_glossy != FLT_MAX
+#ifdef __MNEE__
+ && !(INTEGRATOR_STATE(state, path, mnee) & PATH_MNEE_VALID)
+#endif
+ ) {
float blur_pdf = kernel_data.integrator.filter_glossy *
INTEGRATOR_STATE(state, path, min_ray_pdf);
@@ -605,7 +609,8 @@ ccl_device void shader_eval_surface(KernelGlobals kg,
ConstIntegratorGenericState state,
ccl_private ShaderData *ccl_restrict sd,
ccl_global float *ccl_restrict buffer,
- uint32_t path_flag)
+ uint32_t path_flag,
+ bool use_caustics_storage = false)
{
/* If path is being terminated, we are tracing a shadow ray or evaluating
* emission, then we don't need to store closures. The emission and shadow
@@ -615,7 +620,7 @@ ccl_device void shader_eval_surface(KernelGlobals kg,
max_closures = 0;
}
else {
- max_closures = kernel_data.max_closures;
+ max_closures = use_caustics_storage ? CAUSTICS_MAX_CLOSURE : kernel_data.max_closures;
}
sd->num_closure = 0;
diff --git a/intern/cycles/kernel/integrator/shadow_state_template.h b/intern/cycles/kernel/integrator/shadow_state_template.h
index 9308df53e46..eaee65ada40 100644
--- a/intern/cycles/kernel/integrator/shadow_state_template.h
+++ b/intern/cycles/kernel/integrator/shadow_state_template.h
@@ -38,6 +38,8 @@ KERNEL_STRUCT_MEMBER(shadow_path, packed_float3, pass_diffuse_weight, KERNEL_FEA
KERNEL_STRUCT_MEMBER(shadow_path, packed_float3, pass_glossy_weight, KERNEL_FEATURE_LIGHT_PASSES)
/* Number of intersections found by ray-tracing. */
KERNEL_STRUCT_MEMBER(shadow_path, uint16_t, num_hits, KERNEL_FEATURE_PATH_TRACING)
+/* Light group. */
+KERNEL_STRUCT_MEMBER(shadow_path, uint8_t, lightgroup, KERNEL_FEATURE_PATH_TRACING)
KERNEL_STRUCT_END(shadow_path)
/********************************** Shadow Ray *******************************/
diff --git a/intern/cycles/kernel/integrator/state_template.h b/intern/cycles/kernel/integrator/state_template.h
index 6eac38b1af9..e7e6db037b0 100644
--- a/intern/cycles/kernel/integrator/state_template.h
+++ b/intern/cycles/kernel/integrator/state_template.h
@@ -34,6 +34,8 @@ KERNEL_STRUCT_MEMBER(path, uint32_t, rng_hash, KERNEL_FEATURE_PATH_TRACING)
KERNEL_STRUCT_MEMBER(path, uint16_t, rng_offset, KERNEL_FEATURE_PATH_TRACING)
/* enum PathRayFlag */
KERNEL_STRUCT_MEMBER(path, uint32_t, flag, KERNEL_FEATURE_PATH_TRACING)
+/* enum PathRayMNEE */
+KERNEL_STRUCT_MEMBER(path, uint8_t, mnee, KERNEL_FEATURE_PATH_TRACING)
/* Multiple importance sampling
* The PDF of BSDF sampling at the last scatter point, and distance to the
* last scatter point minus the last ray segment. This distance lets us
diff --git a/intern/cycles/kernel/integrator/subsurface.h b/intern/cycles/kernel/integrator/subsurface.h
index fa468e337c7..2391cc2356d 100644
--- a/intern/cycles/kernel/integrator/subsurface.h
+++ b/intern/cycles/kernel/integrator/subsurface.h
@@ -171,7 +171,12 @@ ccl_device_inline bool subsurface_scatter(KernelGlobals kg, IntegratorState stat
const int shader = intersection_get_shader(kg, &ss_isect.hits[0]);
const int shader_flags = kernel_tex_fetch(__shaders, shader).flags;
- if (shader_flags & SD_HAS_RAYTRACE) {
+ const int object_flags = intersection_get_object_flags(kg, &ss_isect.hits[0]);
+ const bool use_caustics = kernel_data.integrator.use_caustics &&
+ (object_flags & SD_OBJECT_CAUSTICS);
+ const bool use_raytrace_kernel = (shader_flags & SD_HAS_RAYTRACE) || use_caustics;
+
+ if (use_raytrace_kernel) {
INTEGRATOR_PATH_NEXT_SORTED(DEVICE_KERNEL_INTEGRATOR_INTERSECT_SUBSURFACE,
DEVICE_KERNEL_INTEGRATOR_SHADE_SURFACE_RAYTRACE,
shader);
diff --git a/intern/cycles/kernel/light/light.h b/intern/cycles/kernel/light/light.h
index b08b4ebc068..1df1615ed99 100644
--- a/intern/cycles/kernel/light/light.h
+++ b/intern/cycles/kernel/light/light.h
@@ -23,6 +23,7 @@ typedef struct LightSample {
int prim; /* primitive id for triangle/curve lights */
int shader; /* shader id */
int lamp; /* lamp id */
+ int group; /* lightgroup */
LightType type; /* type of light */
} LightSample;
@@ -52,6 +53,7 @@ ccl_device_inline bool light_sample(KernelGlobals kg,
ls->lamp = lamp;
ls->u = randu;
ls->v = randv;
+ ls->group = lamp_lightgroup(kg, lamp);
if (in_volume_segment && (type == LIGHT_DISTANT || type == LIGHT_BACKGROUND)) {
/* Distant lights in a volume get a dummy sample, position will not actually
@@ -246,6 +248,15 @@ ccl_device bool lights_intersect(KernelGlobals kg,
if (!(klight->shader_id & SHADER_USE_MIS)) {
continue;
}
+
+#ifdef __MNEE__
+ /* This path should have been resolved with mnee, it will
+ * generate a firefly for small lights since it is improbable. */
+ if ((INTEGRATOR_STATE(state, path, mnee) & PATH_MNEE_CULL_LIGHT_CONNECTION) &&
+ klight->use_caustics) {
+ continue;
+ }
+#endif
}
if (path_flag & PATH_RAY_SHADOW_CATCHER_PASS) {
@@ -404,6 +415,7 @@ ccl_device bool light_sample_from_distant_ray(KernelGlobals kg,
ls->P = -ray_D;
ls->Ng = -ray_D;
ls->D = ray_D;
+ ls->group = lamp_lightgroup(kg, lamp);
/* compute pdf */
float invarea = klight->distant.invarea;
@@ -432,13 +444,14 @@ ccl_device bool light_sample_from_intersection(KernelGlobals kg,
ls->t = isect->t;
ls->P = ray_P + ray_D * ls->t;
ls->D = ray_D;
+ ls->group = lamp_lightgroup(kg, lamp);
if (type == LIGHT_SPOT) {
const float3 center = make_float3(klight->co[0], klight->co[1], klight->co[2]);
const float3 dir = make_float3(klight->spot.dir[0], klight->spot.dir[1], klight->spot.dir[2]);
/* the normal of the oriented disk */
const float3 lightN = normalize(ray_P - center);
- /* we set the light normal to the outgoing direction to support texturing*/
+ /* We set the light normal to the outgoing direction to support texturing. */
ls->Ng = -ls->D;
float invarea = klight->spot.invarea;
@@ -467,7 +480,7 @@ ccl_device bool light_sample_from_intersection(KernelGlobals kg,
const float3 center = make_float3(klight->co[0], klight->co[1], klight->co[2]);
const float3 lighN = normalize(ray_P - center);
- /* we set the light normal to the outgoing direction to support texturing*/
+ /* We set the light normal to the outgoing direction to support texturing. */
ls->Ng = -ls->D;
float invarea = klight->spot.invarea;
@@ -697,6 +710,7 @@ ccl_device_forceinline void triangle_light_sample(KernelGlobals kg,
ls->lamp = LAMP_NONE;
ls->shader |= SHADER_USE_MIS;
ls->type = LIGHT_TRIANGLE;
+ ls->group = object_lightgroup(kg, object);
float distance_to_plane = fabsf(dot(N0, V[0] - P) / dot(N0, N0));
diff --git a/intern/cycles/kernel/svm/closure.h b/intern/cycles/kernel/svm/closure.h
index 68ddc2fa306..88b44cdbacf 100644
--- a/intern/cycles/kernel/svm/closure.h
+++ b/intern/cycles/kernel/svm/closure.h
@@ -395,8 +395,10 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg,
if (kernel_data.integrator.caustics_refractive || (path_flag & PATH_RAY_DIFFUSE) == 0)
# endif
{
+ /* This is to prevent mnee from receiving a null bsdf. */
+ float refraction_fresnel = fmaxf(0.0001f, 1.0f - fresnel);
ccl_private MicrofacetBsdf *bsdf = (ccl_private MicrofacetBsdf *)bsdf_alloc(
- sd, sizeof(MicrofacetBsdf), base_color * glass_weight * (1.0f - fresnel));
+ sd, sizeof(MicrofacetBsdf), base_color * glass_weight * refraction_fresnel);
if (bsdf) {
bsdf->N = N;
bsdf->T = make_float3(0.0f, 0.0f, 0.0f);
@@ -674,8 +676,10 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg,
if (kernel_data.integrator.caustics_refractive || (path_flag & PATH_RAY_DIFFUSE) == 0)
#endif
{
+ /* This is to prevent mnee from receiving a null bsdf. */
+ float refraction_fresnel = fmaxf(0.0001f, 1.0f - fresnel);
ccl_private MicrofacetBsdf *bsdf = (ccl_private MicrofacetBsdf *)bsdf_alloc(
- sd, sizeof(MicrofacetBsdf), weight * (1.0f - fresnel));
+ sd, sizeof(MicrofacetBsdf), weight * refraction_fresnel);
if (bsdf) {
bsdf->N = N;
diff --git a/intern/cycles/kernel/svm/sky.h b/intern/cycles/kernel/svm/sky.h
index 632a866830b..a72d4dd3ba7 100644
--- a/intern/cycles/kernel/svm/sky.h
+++ b/intern/cycles/kernel/svm/sky.h
@@ -113,24 +113,25 @@ ccl_device float3 sky_radiance_hosek(KernelGlobals kg,
/* Nishita improved sky model */
ccl_device float3 geographical_to_direction(float lat, float lon)
{
- return make_float3(cos(lat) * cos(lon), cos(lat) * sin(lon), sin(lat));
+ return make_float3(cosf(lat) * cosf(lon), cosf(lat) * sinf(lon), sinf(lat));
}
ccl_device float3 sky_radiance_nishita(KernelGlobals kg,
float3 dir,
+ float3 pixel_bottom,
+ float3 pixel_top,
ccl_private float *nishita_data,
uint texture_id)
{
/* definitions */
- float sun_elevation = nishita_data[6];
- float sun_rotation = nishita_data[7];
- float angular_diameter = nishita_data[8];
- float sun_intensity = nishita_data[9];
+ float sun_elevation = nishita_data[0];
+ float sun_rotation = nishita_data[1];
+ float angular_diameter = nishita_data[2];
+ float sun_intensity = nishita_data[3];
bool sun_disc = (angular_diameter >= 0.0f);
float3 xyz;
/* convert dir to spherical coordinates */
float2 direction = direction_to_spherical(dir);
-
/* render above the horizon */
if (dir.z >= 0.0f) {
/* definitions */
@@ -142,8 +143,6 @@ ccl_device float3 sky_radiance_nishita(KernelGlobals kg,
/* if ray inside sun disc render it, otherwise render sky */
if (sun_disc && sun_dir_angle < half_angular) {
/* get 2 pixels data */
- float3 pixel_bottom = make_float3(nishita_data[0], nishita_data[1], nishita_data[2]);
- float3 pixel_top = make_float3(nishita_data[3], nishita_data[4], nishita_data[5]);
float y;
/* sun interpolation */
@@ -292,27 +291,26 @@ ccl_device_noinline int svm_node_tex_sky(
/* Nishita */
else {
/* Define variables */
- float nishita_data[10];
+ float nishita_data[4];
float4 data = read_node_float(kg, &offset);
- nishita_data[0] = data.x;
- nishita_data[1] = data.y;
- nishita_data[2] = data.z;
- nishita_data[3] = data.w;
+ float3 pixel_bottom = make_float3(data.x, data.y, data.z);
+ float3 pixel_top;
+ pixel_top.x = data.w;
data = read_node_float(kg, &offset);
- nishita_data[4] = data.x;
- nishita_data[5] = data.y;
- nishita_data[6] = data.z;
- nishita_data[7] = data.w;
+ pixel_top.y = data.x;
+ pixel_top.z = data.y;
+ nishita_data[0] = data.z;
+ nishita_data[1] = data.w;
data = read_node_float(kg, &offset);
- nishita_data[8] = data.x;
- nishita_data[9] = data.y;
+ nishita_data[2] = data.x;
+ nishita_data[3] = data.y;
uint texture_id = __float_as_uint(data.z);
/* Compute Sky */
- f = sky_radiance_nishita(kg, dir, nishita_data, texture_id);
+ f = sky_radiance_nishita(kg, dir, pixel_bottom, pixel_top, nishita_data, texture_id);
}
stack_store_float3(stack, out_offset, f);
diff --git a/intern/cycles/kernel/types.h b/intern/cycles/kernel/types.h
index 07d4a95780b..9d9daaa0dda 100644
--- a/intern/cycles/kernel/types.h
+++ b/intern/cycles/kernel/types.h
@@ -46,6 +46,7 @@ CCL_NAMESPACE_BEGIN
#define LAMP_NONE (~0)
#define ID_NONE (0.0f)
#define PASS_UNUSED (~0)
+#define LIGHTGROUP_NONE (~0)
#define INTEGRATOR_SHADOW_ISECT_SIZE_CPU 1024U
#define INTEGRATOR_SHADOW_ISECT_SIZE_GPU 4U
@@ -102,6 +103,12 @@ CCL_NAMESPACE_BEGIN
# undef __BAKING__
#endif /* __KERNEL_GPU_RAYTRACING__ */
+/* MNEE currently causes "Compute function exceeds available temporary registers"
+ * on Metal, disabled for now. */
+#ifndef __KERNEL_METAL__
+# define __MNEE__
+#endif
+
/* Scene-based selective features compilation. */
#ifdef __KERNEL_FEATURES__
# if !(__KERNEL_FEATURES & KERNEL_FEATURE_CAMERA_MOTION)
@@ -293,6 +300,13 @@ enum PathRayFlag : uint32_t {
PATH_RAY_SHADOW_CATCHER_BACKGROUND = (1U << 31U),
};
+// 8bit enum, just in case we need to move more variables in it
+enum PathRayMNEE {
+ PATH_MNEE_VALID = (1U << 0U),
+ PATH_MNEE_RECEIVER_ANCESTOR = (1U << 1U),
+ PATH_MNEE_CULL_LIGHT_CONNECTION = (1U << 2U),
+};
+
/* Configure ray visibility bits for rays and objects respectively,
* to make shadow catchers work.
*
@@ -649,6 +663,17 @@ typedef struct AttributeDescriptor {
# define MAX_CLOSURE __MAX_CLOSURE__
#endif
+/* For manifold next event estimation, we need space to store and evaluate
+ * 2 closures (with extra data) on the refractive interfaces, in addition
+ * to keeping the full sd at the current shading point. We need 4 because a
+ * refractive bsdf is instanced with a companion reflection bsdf, even though
+ * we only need the refractive one, and each of them requires 2 slots. */
+#ifndef __CAUSTICS_MAX_CLOSURE__
+# define CAUSTICS_MAX_CLOSURE 4
+#else
+# define CAUSTICS_MAX_CLOSURE __CAUSTICS_MAX_CLOSURE__
+#endif
+
#ifndef __MAX_VOLUME_STACK_SIZE__
# define MAX_VOLUME_STACK_SIZE 32
#else
@@ -779,11 +804,18 @@ enum ShaderDataObjectFlag {
SD_OBJECT_SHADOW_CATCHER = (1 << 7),
/* object has volume attributes */
SD_OBJECT_HAS_VOLUME_ATTRIBUTES = (1 << 8),
+ /* object is caustics caster */
+ SD_OBJECT_CAUSTICS_CASTER = (1 << 9),
+ /* object is caustics receiver */
+ SD_OBJECT_CAUSTICS_RECEIVER = (1 << 10),
+
+ /* object is using caustics */
+ SD_OBJECT_CAUSTICS = (SD_OBJECT_CAUSTICS_CASTER | SD_OBJECT_CAUSTICS_RECEIVER),
SD_OBJECT_FLAGS = (SD_OBJECT_HOLDOUT_MASK | SD_OBJECT_MOTION | SD_OBJECT_TRANSFORM_APPLIED |
SD_OBJECT_NEGATIVE_SCALE_APPLIED | SD_OBJECT_HAS_VOLUME |
SD_OBJECT_INTERSECTS_VOLUME | SD_OBJECT_SHADOW_CATCHER |
- SD_OBJECT_HAS_VOLUME_ATTRIBUTES)
+ SD_OBJECT_HAS_VOLUME_ATTRIBUTES | SD_OBJECT_CAUSTICS)
};
typedef struct ccl_align(16) ShaderData
@@ -882,6 +914,15 @@ typedef struct ccl_align(16) ShaderDataTinyStorage
char pad[sizeof(ShaderData) - sizeof(ShaderClosure) * MAX_CLOSURE];
}
ShaderDataTinyStorage;
+
+/* ShaderDataCausticsStorage needs the same alignment as ShaderData, or else
+ * the pointer cast in AS_SHADER_DATA invokes undefined behavior. */
+typedef struct ccl_align(16) ShaderDataCausticsStorage
+{
+ char pad[sizeof(ShaderData) - sizeof(ShaderClosure) * (MAX_CLOSURE - CAUSTICS_MAX_CLOSURE)];
+}
+ShaderDataCausticsStorage;
+
#define AS_SHADER_DATA(shader_data_tiny_storage) \
((ccl_private ShaderData *)shader_data_tiny_storage)
@@ -1068,6 +1109,7 @@ typedef struct KernelFilm {
int pass_aov_color;
int pass_aov_value;
+ int pass_lightgroup;
/* XYZ to rendering color space transform. float4 instead of float3 to
* ensure consistent padding/alignment across devices. */
@@ -1152,8 +1194,10 @@ typedef struct KernelBackground {
int use_mis;
+ int lightgroup;
+
/* Padding */
- int pad1, pad2, pad3;
+ int pad1, pad2;
} KernelBackground;
static_assert_align(KernelBackground, 16);
@@ -1201,6 +1245,9 @@ typedef struct KernelIntegrator {
/* mis */
int use_lamp_mis;
+ /* caustics */
+ int use_caustics;
+
/* sampler */
int sampling_pattern;
@@ -1219,7 +1266,7 @@ typedef struct KernelIntegrator {
int direct_light_sampling_type;
/* padding */
- int pad1, pad2;
+ int pad1;
} KernelIntegrator;
static_assert_align(KernelIntegrator, 16);
@@ -1329,9 +1376,12 @@ typedef struct KernelObject {
float ao_distance;
+ int lightgroup;
+
uint visibility;
int primitive_type;
- int pad[2];
+
+ int pad1;
} KernelObject;
static_assert_align(KernelObject, 16);
@@ -1383,7 +1433,8 @@ typedef struct KernelLight {
float max_bounces;
float random;
float strength[3];
- float pad1, pad2;
+ int use_caustics;
+ int lightgroup;
Transform tfm;
Transform itfm;
union {
diff --git a/intern/cycles/scene/background.cpp b/intern/cycles/scene/background.cpp
index 1c3a9f9358d..bffc8895bfd 100644
--- a/intern/cycles/scene/background.cpp
+++ b/intern/cycles/scene/background.cpp
@@ -32,6 +32,8 @@ NODE_DEFINE(Background)
SOCKET_NODE(shader, "Shader", Shader::get_node_type());
+ SOCKET_STRING(lightgroup, "Light Group", ustring());
+
return type;
}
@@ -101,6 +103,15 @@ void Background::device_update(Device *device, DeviceScene *dscene, Scene *scene
kbackground->surface_shader |= SHADER_EXCLUDE_CAMERA;
}
+ /* Light group. */
+ auto it = scene->lightgroups.find(lightgroup);
+ if (it != scene->lightgroups.end()) {
+ kbackground->lightgroup = it->second;
+ }
+ else {
+ kbackground->lightgroup = LIGHTGROUP_NONE;
+ }
+
clear_modified();
}
diff --git a/intern/cycles/scene/background.h b/intern/cycles/scene/background.h
index bbffce6e30a..50b4368d708 100644
--- a/intern/cycles/scene/background.h
+++ b/intern/cycles/scene/background.h
@@ -30,6 +30,8 @@ class Background : public Node {
NODE_SOCKET_API(float, volume_step_size)
+ NODE_SOCKET_API(ustring, lightgroup)
+
Background();
~Background();
diff --git a/intern/cycles/scene/film.cpp b/intern/cycles/scene/film.cpp
index e17c839d60b..c3b126544c4 100644
--- a/intern/cycles/scene/film.cpp
+++ b/intern/cycles/scene/film.cpp
@@ -175,6 +175,7 @@ void Film::device_update(Device *device, DeviceScene *dscene, Scene *scene)
kfilm->pass_volume_direct = PASS_UNUSED;
kfilm->pass_volume_indirect = PASS_UNUSED;
kfilm->pass_shadow = PASS_UNUSED;
+ kfilm->pass_lightgroup = PASS_UNUSED;
/* Mark passes as unused so that the kernel knows the pass is inaccessible. */
kfilm->pass_denoising_normal = PASS_UNUSED;
@@ -189,6 +190,7 @@ void Film::device_update(Device *device, DeviceScene *dscene, Scene *scene)
bool have_cryptomatte = false;
bool have_aov_color = false;
bool have_aov_value = false;
+ bool have_lightgroup = false;
for (size_t i = 0; i < scene->passes.size(); i++) {
const Pass *pass = scene->passes[i];
@@ -223,6 +225,15 @@ void Film::device_update(Device *device, DeviceScene *dscene, Scene *scene)
assert(pass->get_type() <= PASS_CATEGORY_BAKE_END);
}
+ if (pass->get_lightgroup() != ustring()) {
+ if (!have_lightgroup) {
+ kfilm->pass_lightgroup = kfilm->pass_stride;
+ have_lightgroup = true;
+ }
+ kfilm->pass_stride += pass->get_info().num_components;
+ continue;
+ }
+
switch (pass->get_type()) {
case PASS_COMBINED:
kfilm->pass_combined = kfilm->pass_stride;
@@ -414,6 +425,26 @@ int Film::get_aov_offset(Scene *scene, string name, bool &is_color)
return -1;
}
+bool Film::update_lightgroups(Scene *scene)
+{
+ map<ustring, int> lightgroups;
+ int i = 0;
+ foreach (const Pass *pass, scene->passes) {
+ ustring lightgroup = pass->get_lightgroup();
+ if (!lightgroup.empty()) {
+ if (!lightgroups.count(lightgroup)) {
+ lightgroups[lightgroup] = i++;
+ }
+ }
+ }
+ if (scene->lightgroups != lightgroups) {
+ scene->lightgroups = lightgroups;
+ return true;
+ }
+
+ return false;
+}
+
void Film::update_passes(Scene *scene, bool add_sample_count_pass)
{
const Background *background = scene->background;
@@ -580,11 +611,19 @@ void Film::remove_auto_passes(Scene *scene)
static bool compare_pass_order(const Pass *a, const Pass *b)
{
+ /* On the highest level, sort by number of components.
+ * Within passes of the same component count, sort so that all non-lightgroup passes come first.
+ * Within that group, sort by type. */
const int num_components_a = a->get_info().num_components;
const int num_components_b = b->get_info().num_components;
if (num_components_a == num_components_b) {
- return (a->get_type() < b->get_type());
+ const int is_lightgroup_a = !a->get_lightgroup().empty();
+ const int is_lightgroup_b = !b->get_lightgroup().empty();
+ if (is_lightgroup_a == is_lightgroup_b) {
+ return (a->get_type() < b->get_type());
+ }
+ return is_lightgroup_b;
}
return num_components_a > num_components_b;
diff --git a/intern/cycles/scene/film.h b/intern/cycles/scene/film.h
index 43597b0fc79..f1e3237eb9e 100644
--- a/intern/cycles/scene/film.h
+++ b/intern/cycles/scene/film.h
@@ -68,6 +68,8 @@ class Film : public Node {
int get_aov_offset(Scene *scene, string name, bool &is_color);
+ bool update_lightgroups(Scene *scene);
+
/* Update passes so that they contain all passes required for the configured functionality.
*
* If `add_sample_count_pass` is true then the SAMPLE_COUNT pass is ensured to be added. */
diff --git a/intern/cycles/scene/light.cpp b/intern/cycles/scene/light.cpp
index 68779a3ce02..5e311d3051f 100644
--- a/intern/cycles/scene/light.cpp
+++ b/intern/cycles/scene/light.cpp
@@ -123,6 +123,7 @@ NODE_DEFINE(Light)
SOCKET_BOOLEAN(use_glossy, "Use Glossy", true);
SOCKET_BOOLEAN(use_transmission, "Use Transmission", true);
SOCKET_BOOLEAN(use_scatter, "Use Scatter", true);
+ SOCKET_BOOLEAN(use_caustics, "Shadow Caustics", false);
SOCKET_INT(max_bounces, "Max Bounces", 1024);
SOCKET_UINT(random_id, "Random ID", 0);
@@ -133,6 +134,8 @@ NODE_DEFINE(Light)
SOCKET_NODE(shader, "Shader", Shader::get_node_type());
+ SOCKET_STRING(lightgroup, "Light Group", ustring());
+
return type;
}
@@ -896,10 +899,19 @@ void LightManager::device_update_points(Device *, DeviceScene *dscene, Scene *sc
klights[light_index].max_bounces = max_bounces;
klights[light_index].random = random;
+ klights[light_index].use_caustics = light->use_caustics;
klights[light_index].tfm = light->tfm;
klights[light_index].itfm = transform_inverse(light->tfm);
+ auto it = scene->lightgroups.find(light->lightgroup);
+ if (it != scene->lightgroups.end()) {
+ klights[light_index].lightgroup = it->second;
+ }
+ else {
+ klights[light_index].lightgroup = LIGHTGROUP_NONE;
+ }
+
light_index++;
}
diff --git a/intern/cycles/scene/light.h b/intern/cycles/scene/light.h
index 3519b76cf51..5b852f210fc 100644
--- a/intern/cycles/scene/light.h
+++ b/intern/cycles/scene/light.h
@@ -61,6 +61,7 @@ class Light : public Node {
NODE_SOCKET_API(bool, use_glossy)
NODE_SOCKET_API(bool, use_transmission)
NODE_SOCKET_API(bool, use_scatter)
+ NODE_SOCKET_API(bool, use_caustics)
NODE_SOCKET_API(bool, is_shadow_catcher)
NODE_SOCKET_API(bool, is_portal)
@@ -70,6 +71,8 @@ class Light : public Node {
NODE_SOCKET_API(int, max_bounces)
NODE_SOCKET_API(uint, random_id)
+ NODE_SOCKET_API(ustring, lightgroup)
+
void tag_update(Scene *scene);
/* Check whether the light has contribution the scene. */
diff --git a/intern/cycles/scene/object.cpp b/intern/cycles/scene/object.cpp
index fda9a211e60..55d89fc3673 100644
--- a/intern/cycles/scene/object.cpp
+++ b/intern/cycles/scene/object.cpp
@@ -90,11 +90,16 @@ NODE_DEFINE(Object)
SOCKET_BOOLEAN(is_shadow_catcher, "Shadow Catcher", false);
+ SOCKET_BOOLEAN(is_caustics_caster, "Cast Shadow Caustics", false);
+ SOCKET_BOOLEAN(is_caustics_receiver, "Receive Shadow Caustics", false);
+
SOCKET_NODE(particle_system, "Particle System", ParticleSystem::get_node_type());
SOCKET_INT(particle_index, "Particle Index", 0);
SOCKET_FLOAT(ao_distance, "AO Distance", 0.0f);
+ SOCKET_STRING(lightgroup, "Light Group", ustring());
+
return type;
}
@@ -390,7 +395,8 @@ static float object_volume_density(const Transform &tfm, Geometry *geom)
void ObjectManager::device_update_object_transform(UpdateObjectTransformState *state,
Object *ob,
- bool update_all)
+ bool update_all,
+ const Scene *scene)
{
KernelObject &kobject = state->objects[ob->index];
Transform *object_motion_pass = state->object_motion_pass;
@@ -510,6 +516,14 @@ void ObjectManager::device_update_object_transform(UpdateObjectTransformState *s
kobject.visibility = ob->visibility_for_tracing();
kobject.primitive_type = geom->primitive_type();
+ /* Object shadow caustics flag */
+ if (ob->is_caustics_caster) {
+ flag |= SD_OBJECT_CAUSTICS_CASTER;
+ }
+ if (ob->is_caustics_receiver) {
+ flag |= SD_OBJECT_CAUSTICS_RECEIVER;
+ }
+
/* Object flag. */
if (ob->use_holdout) {
flag |= SD_OBJECT_HOLDOUT_MASK;
@@ -521,6 +535,15 @@ void ObjectManager::device_update_object_transform(UpdateObjectTransformState *s
if (geom->geometry_type == Geometry::HAIR) {
state->have_curves = true;
}
+
+ /* Light group. */
+ auto it = scene->lightgroups.find(ob->lightgroup);
+ if (it != scene->lightgroups.end()) {
+ kobject.lightgroup = it->second;
+ }
+ else {
+ kobject.lightgroup = LIGHTGROUP_NONE;
+ }
}
void ObjectManager::device_update_prim_offsets(Device *device, DeviceScene *dscene, Scene *scene)
@@ -607,7 +630,7 @@ void ObjectManager::device_update_transforms(DeviceScene *dscene, Scene *scene,
[&](const blocked_range<size_t> &r) {
for (size_t i = r.begin(); i != r.end(); i++) {
Object *ob = state.scene->objects[i];
- device_update_object_transform(&state, ob, update_all);
+ device_update_object_transform(&state, ob, update_all, scene);
}
});
diff --git a/intern/cycles/scene/object.h b/intern/cycles/scene/object.h
index 55689ccfa58..c41f1416180 100644
--- a/intern/cycles/scene/object.h
+++ b/intern/cycles/scene/object.h
@@ -55,6 +55,9 @@ class Object : public Node {
NODE_SOCKET_API(float, shadow_terminator_shading_offset)
NODE_SOCKET_API(float, shadow_terminator_geometry_offset)
+ NODE_SOCKET_API(bool, is_caustics_caster)
+ NODE_SOCKET_API(bool, is_caustics_receiver)
+
NODE_SOCKET_API(float3, dupli_generated)
NODE_SOCKET_API(float2, dupli_uv)
@@ -63,6 +66,8 @@ class Object : public Node {
NODE_SOCKET_API(float, ao_distance)
+ NODE_SOCKET_API(ustring, lightgroup)
+
/* Set during device update. */
bool intersects_volume;
@@ -166,7 +171,8 @@ class ObjectManager {
protected:
void device_update_object_transform(UpdateObjectTransformState *state,
Object *ob,
- bool update_all);
+ bool update_all,
+ const Scene *scene);
void device_update_object_transform_task(UpdateObjectTransformState *state);
bool device_update_object_transform_pop_work(UpdateObjectTransformState *state,
int *start_index,
diff --git a/intern/cycles/scene/pass.cpp b/intern/cycles/scene/pass.cpp
index 41730cb189d..5f5b19e710d 100644
--- a/intern/cycles/scene/pass.cpp
+++ b/intern/cycles/scene/pass.cpp
@@ -124,6 +124,7 @@ NODE_DEFINE(Pass)
SOCKET_ENUM(mode, "Mode", *pass_mode_enum, static_cast<int>(PassMode::DENOISED));
SOCKET_STRING(name, "Name", ustring());
SOCKET_BOOLEAN(include_albedo, "Include Albedo", false);
+ SOCKET_STRING(lightgroup, "Light Group", ustring());
return type;
}
@@ -134,7 +135,7 @@ Pass::Pass() : Node(get_node_type()), is_auto_(false)
PassInfo Pass::get_info() const
{
- return get_info(type, include_albedo);
+ return get_info(type, include_albedo, !lightgroup.empty());
}
bool Pass::is_written() const
@@ -142,7 +143,7 @@ bool Pass::is_written() const
return get_info().is_written;
}
-PassInfo Pass::get_info(const PassType type, const bool include_albedo)
+PassInfo Pass::get_info(const PassType type, const bool include_albedo, const bool is_lightgroup)
{
PassInfo pass_info;
@@ -157,9 +158,9 @@ PassInfo Pass::get_info(const PassType type, const bool include_albedo)
pass_info.num_components = 0;
break;
case PASS_COMBINED:
- pass_info.num_components = 4;
+ pass_info.num_components = is_lightgroup ? 3 : 4;
pass_info.use_exposure = true;
- pass_info.support_denoise = true;
+ pass_info.support_denoise = !is_lightgroup;
break;
case PASS_DEPTH:
pass_info.num_components = 1;
@@ -369,13 +370,16 @@ const Pass *Pass::find(const vector<Pass *> &passes, const string &name)
return nullptr;
}
-const Pass *Pass::find(const vector<Pass *> &passes, PassType type, PassMode mode)
+const Pass *Pass::find(const vector<Pass *> &passes,
+ PassType type,
+ PassMode mode,
+ const ustring &lightgroup)
{
for (const Pass *pass : passes) {
- if (pass->get_type() != type || pass->get_mode() != mode) {
+ if (pass->get_type() != type || pass->get_mode() != mode ||
+ pass->get_lightgroup() != lightgroup) {
continue;
}
-
return pass;
}
diff --git a/intern/cycles/scene/pass.h b/intern/cycles/scene/pass.h
index c12df007b5d..e0689eba688 100644
--- a/intern/cycles/scene/pass.h
+++ b/intern/cycles/scene/pass.h
@@ -53,6 +53,7 @@ class Pass : public Node {
NODE_SOCKET_API(PassMode, mode)
NODE_SOCKET_API(ustring, name)
NODE_SOCKET_API(bool, include_albedo)
+ NODE_SOCKET_API(ustring, lightgroup)
Pass();
@@ -72,7 +73,9 @@ class Pass : public Node {
static const NodeEnum *get_type_enum();
static const NodeEnum *get_mode_enum();
- static PassInfo get_info(PassType type, const bool include_albedo = false);
+ static PassInfo get_info(PassType type,
+ const bool include_albedo = false,
+ const bool is_lightgroup = false);
static bool contains(const vector<Pass *> &passes, PassType type);
@@ -80,7 +83,8 @@ class Pass : public Node {
static const Pass *find(const vector<Pass *> &passes, const string &name);
static const Pass *find(const vector<Pass *> &passes,
PassType type,
- PassMode mode = PassMode::NOISY);
+ PassMode mode = PassMode::NOISY,
+ const ustring &lightgroup = ustring());
/* Returns PASS_UNUSED if there is no corresponding pass. */
static int get_offset(const vector<Pass *> &passes, const Pass *pass);
diff --git a/intern/cycles/scene/scene.cpp b/intern/cycles/scene/scene.cpp
index 2199b2351d0..b6b53004816 100644
--- a/intern/cycles/scene/scene.cpp
+++ b/intern/cycles/scene/scene.cpp
@@ -251,6 +251,11 @@ void Scene::device_update(Device *device_, Progress &progress)
* - Lookup tables are done a second time to handle film tables
*/
+ if (film->update_lightgroups(this)) {
+ light_manager->tag_update(this, ccl::LightManager::LIGHT_MODIFIED);
+ object_manager->tag_update(this, ccl::ObjectManager::OBJECT_MODIFIED);
+ }
+
progress.set_status("Updating Shaders");
shader_manager->device_update(device, &dscene, this, progress);
@@ -489,7 +494,21 @@ void Scene::update_kernel_features()
if (use_motion && camera->use_motion()) {
kernel_features |= KERNEL_FEATURE_CAMERA_MOTION;
}
+
+ /* Figure out whether the scene will use shader raytrace we need at least
+ * one caustic light, one caustic caster and one caustic receiver to use
+ * and enable the mnee code path. */
+ bool has_caustics_receiver = false;
+ bool has_caustics_caster = false;
+ bool has_caustics_light = false;
+
foreach (Object *object, objects) {
+ if (object->get_is_caustics_caster()) {
+ has_caustics_caster = true;
+ }
+ else if (object->get_is_caustics_receiver()) {
+ has_caustics_receiver = true;
+ }
Geometry *geom = object->get_geometry();
if (use_motion) {
if (object->use_motion() || geom->get_use_motion_blur()) {
@@ -518,6 +537,18 @@ void Scene::update_kernel_features()
}
}
+ foreach (Light *light, lights) {
+ if (light->get_use_caustics()) {
+ has_caustics_light = true;
+ }
+ }
+
+ dscene.data.integrator.use_caustics = false;
+ if (has_caustics_caster && has_caustics_receiver && has_caustics_light) {
+ dscene.data.integrator.use_caustics = true;
+ kernel_features |= KERNEL_FEATURE_NODE_RAYTRACE;
+ }
+
if (bake_manager->get_baking()) {
kernel_features |= KERNEL_FEATURE_BAKING;
}
diff --git a/intern/cycles/scene/scene.h b/intern/cycles/scene/scene.h
index e1b36899302..9e3e8d61b80 100644
--- a/intern/cycles/scene/scene.h
+++ b/intern/cycles/scene/scene.h
@@ -197,6 +197,9 @@ class Scene : public NodeOwner {
/* Optional name. Is used for logging and reporting. */
string name;
+ /* Maps from Light group names to their pass ID. */
+ map<ustring, int> lightgroups;
+
/* data */
BVH *bvh;
Camera *camera;
diff --git a/intern/cycles/session/buffers.cpp b/intern/cycles/session/buffers.cpp
index f9893ed1e1c..3bbc205ca7a 100644
--- a/intern/cycles/session/buffers.cpp
+++ b/intern/cycles/session/buffers.cpp
@@ -49,6 +49,7 @@ NODE_DEFINE(BufferPass)
SOCKET_ENUM(mode, "Mode", *pass_mode_enum, static_cast<int>(PassMode::DENOISED));
SOCKET_STRING(name, "Name", ustring());
SOCKET_BOOLEAN(include_albedo, "Include Albedo", false);
+ SOCKET_STRING(lightgroup, "Light Group", ustring());
SOCKET_INT(offset, "Offset", -1);
@@ -64,13 +65,14 @@ BufferPass::BufferPass(const Pass *scene_pass)
type(scene_pass->get_type()),
mode(scene_pass->get_mode()),
name(scene_pass->get_name()),
- include_albedo(scene_pass->get_include_albedo())
+ include_albedo(scene_pass->get_include_albedo()),
+ lightgroup(scene_pass->get_lightgroup())
{
}
PassInfo BufferPass::get_info() const
{
- return Pass::get_info(type, include_albedo);
+ return Pass::get_info(type, include_albedo, !lightgroup.empty());
}
/* --------------------------------------------------------------------
diff --git a/intern/cycles/session/buffers.h b/intern/cycles/session/buffers.h
index 1c4ec81e427..a8278388a28 100644
--- a/intern/cycles/session/buffers.h
+++ b/intern/cycles/session/buffers.h
@@ -30,6 +30,7 @@ class BufferPass : public Node {
PassMode mode = PassMode::NOISY;
ustring name;
bool include_albedo = false;
+ ustring lightgroup;
int offset = -1;
@@ -49,7 +50,8 @@ class BufferPass : public Node {
inline bool operator==(const BufferPass &other) const
{
return type == other.type && mode == other.mode && name == other.name &&
- include_albedo == other.include_albedo && offset == other.offset;
+ include_albedo == other.include_albedo && lightgroup == other.lightgroup &&
+ offset == other.offset;
}
inline bool operator!=(const BufferPass &other) const
{
diff --git a/intern/cycles/util/debug.h b/intern/cycles/util/debug.h
index 23a055cf52f..3565fdea17f 100644
--- a/intern/cycles/util/debug.h
+++ b/intern/cycles/util/debug.h
@@ -87,7 +87,7 @@ class DebugFlags {
/* Reset flags to their defaults. */
void reset();
- /* Whether adaptive feature based runtime compile is enabled or not.*/
+ /* Whether adaptive feature based runtime compile is enabled or not. */
bool adaptive_compile;
};
@@ -110,7 +110,7 @@ class DebugFlags {
/* Reset flags to their defaults. */
void reset();
- /* Whether adaptive feature based runtime compile is enabled or not.*/
+ /* Whether adaptive feature based runtime compile is enabled or not. */
bool adaptive_compile;
};
diff --git a/intern/cycles/util/math_float2.h b/intern/cycles/util/math_float2.h
index d6b47052720..542dad93467 100644
--- a/intern/cycles/util/math_float2.h
+++ b/intern/cycles/util/math_float2.h
@@ -40,7 +40,7 @@ ccl_device_inline float average(const float2 &a);
ccl_device_inline float distance(const float2 &a, const float2 &b);
ccl_device_inline float dot(const float2 &a, const float2 &b);
ccl_device_inline float cross(const float2 &a, const float2 &b);
-ccl_device_inline float len(const float2 &a);
+ccl_device_inline float len(const float2 a);
ccl_device_inline float2 normalize(const float2 &a);
ccl_device_inline float2 normalize_len(const float2 &a, float *t);
ccl_device_inline float2 safe_normalize(const float2 &a);
@@ -187,11 +187,6 @@ ccl_device_inline float cross(const float2 &a, const float2 &b)
return (a.x * b.y - a.y * b.x);
}
-ccl_device_inline float len(const float2 &a)
-{
- return sqrtf(dot(a, a));
-}
-
ccl_device_inline float2 normalize(const float2 &a)
{
return a / len(a);
@@ -251,6 +246,11 @@ ccl_device_inline float2 floor(const float2 &a)
#endif /* !__KERNEL_METAL__ */
+ccl_device_inline float len(const float2 a)
+{
+ return sqrtf(dot(a, a));
+}
+
ccl_device_inline float2 safe_divide_float2_float(const float2 a, const float b)
{
return (b != 0.0f) ? a / b : zero_float2();
diff --git a/intern/cycles/util/texture.h b/intern/cycles/util/texture.h
index 33ff349704b..e8bb058a3c9 100644
--- a/intern/cycles/util/texture.h
+++ b/intern/cycles/util/texture.h
@@ -15,7 +15,7 @@ CCL_NAMESPACE_BEGIN
#define TEX_IMAGE_MISSING_A 1
/* Interpolation types for textures
- * cuda also use texture space to store other objects */
+ * CUDA also use texture space to store other objects. */
typedef enum InterpolationType {
INTERPOLATION_NONE = -1,
INTERPOLATION_LINEAR = 0,
diff --git a/intern/ghost/intern/GHOST_WindowViewCocoa.h b/intern/ghost/intern/GHOST_WindowViewCocoa.h
index 635c0052a3a..58c029620da 100644
--- a/intern/ghost/intern/GHOST_WindowViewCocoa.h
+++ b/intern/ghost/intern/GHOST_WindowViewCocoa.h
@@ -64,7 +64,7 @@
ime.event.target_end = -1;
/* Register a function to be executed when Input Method is changed using
- * 'Control + Space' or language-specific keys (such as 'Eisu / Kana' key for Japanese).*/
+ * 'Control + Space' or language-specific keys (such as 'Eisu / Kana' key for Japanese). */
NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
[center addObserver:self
selector:@selector(ImeDidChangeCallback:)
diff --git a/intern/rigidbody/RBI_api.h b/intern/rigidbody/RBI_api.h
index 4065240a704..791a4a6ac05 100644
--- a/intern/rigidbody/RBI_api.h
+++ b/intern/rigidbody/RBI_api.h
@@ -246,8 +246,8 @@ void RB_shape_trimesh_update(rbCollisionShape *shape,
float *vertices,
int num_verts,
int vert_stride,
- float min[3],
- float max[3]);
+ const float min[3],
+ const float max[3]);
/* ********************************** */
/* Constraints */
diff --git a/intern/rigidbody/rb_bullet_api.cpp b/intern/rigidbody/rb_bullet_api.cpp
index 88b146384e1..ac8026be41b 100644
--- a/intern/rigidbody/rb_bullet_api.cpp
+++ b/intern/rigidbody/rb_bullet_api.cpp
@@ -802,8 +802,8 @@ void RB_shape_trimesh_update(rbCollisionShape *shape,
float *vertices,
int num_verts,
int vert_stride,
- float min[3],
- float max[3])
+ const float min[3],
+ const float max[3])
{
if (shape->mesh == NULL || num_verts != shape->mesh->num_vertices) {
return;
diff --git a/release/datafiles/blender_icons.svg b/release/datafiles/blender_icons.svg
index 6de808a9386..6f0216176d7 100644
--- a/release/datafiles/blender_icons.svg
+++ b/release/datafiles/blender_icons.svg
@@ -7719,7 +7719,7 @@
<g
style="display:inline;fill:#ffffff;enable-background:new"
id="g13475"
- transform="translate(-20)">
+ transform="translate(-21)">
<path
sodipodi:nodetypes="ccccccccccccccccccccccccccccccccccccccccccccccccccccccc"
mask="none"
@@ -7741,7 +7741,7 @@
</g>
<g
style="display:inline;fill:#ffffff;enable-background:new"
- transform="matrix(-1,0,0,1,90,-231)"
+ transform="matrix(-1,0,0,1,89,-231)"
id="g12197">
<path
inkscape:connector-curvature="0"
@@ -8569,7 +8569,7 @@
<g
style="display:inline;fill:#ffffff;enable-background:new"
id="g12259"
- transform="matrix(0,-1,-1,0,313,-85.999995)"
+ transform="matrix(0,-1,-1,0,312,-85.999995)"
inkscape:export-filename="blender_icons.png"
inkscape:export-xdpi="96"
inkscape:export-ydpi="96">
@@ -8823,7 +8823,7 @@
<g
style="display:inline;fill:#ffffff;enable-background:new"
id="g12761"
- transform="translate(72.999998)"
+ transform="translate(71.999998)"
inkscape:export-filename="blender_icons.png"
inkscape:export-xdpi="96"
inkscape:export-ydpi="96">
@@ -10405,7 +10405,7 @@
sodipodi:nodetypes="sssss" />
</g>
<g
- transform="translate(0.97000661)"
+ transform="translate(-0.02999339)"
style="display:inline;fill:#ffffff;enable-background:new"
id="g14346">
<path
@@ -10995,7 +10995,7 @@
inkscape:connector-curvature="0" />
<g
style="display:inline;fill:#ffffff;enable-background:new"
- transform="translate(-188,168)"
+ transform="translate(-189,168)"
id="g21028">
<path
inkscape:connector-curvature="0"
@@ -11064,7 +11064,7 @@
<g
style="display:inline;fill:#ffffff;enable-background:new"
id="g19653"
- transform="translate(-626.99987,42.000005)">
+ transform="translate(-627.99987,42.000005)">
<path
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
d="m 143.13867,515.0332 c -0.49613,-0.0451 -1.03862,0.15972 -1.49219,0.61328 l -1.75,1.75 c -0.19519,0.19527 -0.19519,0.51177 0,0.70704 l 3,3 c 0.19527,0.19519 0.51177,0.19519 0.70704,0 l 1.75,-1.75 c 0.45356,-0.45357 0.65838,-0.99606 0.61328,-1.49219 -0.0451,-0.49613 -0.30436,-0.90592 -0.61328,-1.21485 l -1,-1 c -0.30893,-0.30892 -0.71872,-0.56817 -1.21485,-0.61328 z m -4.39648,3.7168 a 0.50005,0.50005 0 0 0 -0.34571,0.14648 l -0.25,0.25 a 0.50005,0.50005 0 0 0 0,0.70704 l 3,3 a 0.50005,0.50005 0 0 0 0.70704,0 l 0.25,-0.25 a 0.50005,0.50005 0 0 0 0,-0.70704 l -3,-3 A 0.50005,0.50005 0 0 0 138.74219,518.75 Z m -1.25196,2.24609 a 0.50005,0.50005 0 0 0 -0.34375,0.15039 l -4.25,4.25 c -0.83838,0.83839 -1.06879,1.7573 -0.80273,2.4668 C 132.35981,528.57278 133.04167,529 133.75,529 H 138 c 1.00042,0 2,-0.79793 2,-2 v -3.5 a 0.50005,0.50005 0 1 0 -1,0 v 3.5 c 0,0.66505 -0.50442,1 -1,1 h -4.25 c -0.29167,0 -0.60981,-0.19778 -0.71875,-0.48828 -0.10894,-0.2905 -0.0893,-0.74659 0.57227,-1.4082 l 4.25,-4.25 a 0.50005,0.50005 0 0 0 -0.36329,-0.85743 z"
@@ -11396,7 +11396,7 @@
<g
style="display:inline;fill:#ffffff;enable-background:new"
id="g22292"
- transform="translate(-87.000002,-170)">
+ transform="translate(-88.000002,-170)">
<g
transform="translate(20,10)"
id="g22287"
@@ -12431,11 +12431,6 @@
id="path24010-2"
inkscape:connector-curvature="0" />
</g>
- <path
- style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:0.6;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
- d="m 310.57031,473.01758 c -0.79787,-0.038 -1.57177,0.27684 -2.16015,0.86523 l -1.48633,1.48828 c -0.61577,0.57533 -0.93433,1.35407 -0.89258,2.1543 a 0.50005,0.50005 0 1 0 0.99805,-0.0508 c -0.0269,-0.51495 0.15566,-0.98016 0.57617,-1.37305 a 0.50005,0.50005 0 0 0 0.0117,-0.0117 l 1.5,-1.5 c 0.41161,-0.41161 0.88966,-0.59872 1.40429,-0.57422 0.51464,0.0245 1.08439,0.26993 1.63868,0.82422 0.55479,0.5548 0.80954,1.13546 0.83789,1.65235 0.0283,0.51688 -0.15241,0.9848 -0.57422,1.3789 a 0.50005,0.50005 0 0 0 -0.0137,0.0117 l -1.5,1.5 c -0.41213,0.41213 -0.87694,0.60352 -1.39649,0.60352 a 0.50005,0.50005 0 1 0 0,1 c 0.78067,0 1.52491,-0.31788 2.10352,-0.89649 l 1.48828,-1.48828 c 0.61768,-0.57711 0.9366,-1.36125 0.89258,-2.16406 -0.044,-0.80281 -0.43566,-1.60948 -1.13086,-2.30469 -0.69571,-0.69571 -1.49901,-1.07724 -2.29688,-1.11523 z m -1.08008,3.97851 a 0.50005,0.50005 0 0 0 -0.34375,0.15039 l -5,5 a 0.50005,0.50005 0 1 0 0.70704,0.70704 l 5,-5 a 0.50005,0.50005 0 0 0 -0.36329,-0.85743 z m -4.92968,2.02149 c -0.80753,-0.0482 -1.5954,0.26944 -2.17578,0.89062 l -1.48829,1.48828 c -0.58838,0.58839 -0.90322,1.36034 -0.86523,2.15821 0.038,0.79787 0.41952,1.60311 1.11523,2.29883 0.69521,0.6952 1.50384,1.08487 2.30664,1.1289 0.80281,0.044 1.585,-0.27294 2.16211,-0.89062 l 1.48829,-1.48828 C 307.68213,484.0249 308,483.28067 308,482.5 a 0.50005,0.50005 0 1 0 -1,0 c 0,0.51955 -0.19139,0.98436 -0.60352,1.39648 l -1.5,1.5 a 0.50005,0.50005 0 0 0 -0.0117,0.0117 c -0.39411,0.42182 -0.86007,0.60452 -1.37696,0.57618 -0.51688,-0.0283 -1.0995,-0.2831 -1.65429,-0.8379 -0.55429,-0.55428 -0.79776,-1.12404 -0.82227,-1.63867 -0.0245,-0.51463 0.16065,-0.99268 0.57227,-1.40429 l 1.5,-1.5 a 0.50005,0.50005 0 0 0 0.0117,-0.0117 c 0.39634,-0.4242 0.86629,-0.60725 1.38672,-0.57618 a 0.50005,0.50005 0 1 0 0.0586,-0.99804 z"
- id="path23281"
- inkscape:connector-curvature="0" />
<g
style="display:inline;fill:#ffffff;enable-background:new"
id="g23341"
@@ -13044,7 +13039,7 @@
inkscape:export-ydpi="96"
inkscape:export-xdpi="96"
inkscape:export-filename="blender_icons.png"
- transform="translate(-20,168)"
+ transform="translate(-21,168)"
id="g15951-6"
style="display:inline;opacity:1;fill:#ffffff;enable-background:new">
<path
@@ -14438,7 +14433,7 @@
<path
id="path16385"
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:new"
- d="m 516.5,432 c -0.1326,2e-5 -0.25976,0.0527 -0.35352,0.14647 L 514.29297,434 H 511.5 c -0.27613,3e-5 -0.49997,0.22387 -0.5,0.5 v 8 c 3e-5,0.27613 0.22387,0.49997 0.5,0.5 h 6.45312 0.004 c 0.0131,-8.2e-4 0.0261,-0.002 0.0391,-0.004 0.004,5e-5 0.008,5e-5 0.0117,0 0.0143,0.002 0.0286,0.003 0.043,0.004 h 0.006 5.44336 c 0.27613,-3e-5 0.49997,-0.22387 0.5,-0.5 v -8 c -3e-5,-0.27613 -0.22387,-0.49997 -0.5,-0.5 h -1.79297 l -1.85351,-1.85353 C 519.76,432.05268 519.6327,431.99995 519.5,432 Z m 1.49781,1.99804 c 2.21589,-3.2e-4 4.00185,1.7855 4.00195,4.00196 -9e-4,2.19736 -1.75841,3.97457 -3.95508,4 -0.0131,8.2e-4 -0.0261,0.002 -0.0391,0.004 -0.0149,-0.002 -0.0299,-0.003 -0.0449,-0.004 -10e-4,0 -0.003,0 -0.004,0 -2.19824,-0.0228 -3.95803,-1.80057 -3.95898,-4 9e-5,-2.21578 1.78479,-4.00131 4,-4.00196 z M 517.99805,435 C 516.34742,435 515,436.34922 515,438 c 0,1.65079 1.34742,3 2.99805,3 1.65063,0 3,-1.34921 3,-3 0,-1.65078 -1.34937,-3 -3,-3 z m 0,1 c 1.11009,0 2,0.88955 2,2 0,1.11045 -0.88991,2 -2,2 C 516.88796,440 516,439.11045 516,438 c 0,-1.11045 0.88796,-2 1.99805,-2 z"
+ d="m 515.5,432 c -0.1326,2e-5 -0.25976,0.0527 -0.35352,0.14647 L 513.29297,434 H 510.5 c -0.27613,3e-5 -0.49997,0.22387 -0.5,0.5 v 8 c 3e-5,0.27613 0.22387,0.49997 0.5,0.5 h 6.45312 0.004 c 0.0131,-8.2e-4 0.0261,-0.002 0.0391,-0.004 0.004,5e-5 0.008,5e-5 0.0117,0 0.0143,0.002 0.0286,0.003 0.043,0.004 h 0.006 5.44336 c 0.27613,-3e-5 0.49997,-0.22387 0.5,-0.5 v -8 c -3e-5,-0.27613 -0.22387,-0.49997 -0.5,-0.5 h -1.79297 l -1.85351,-1.85353 C 518.76,432.05268 518.6327,431.99995 518.5,432 Z m 1.49781,1.99804 c 2.21589,-3.2e-4 4.00185,1.7855 4.00195,4.00196 -9e-4,2.19736 -1.75841,3.97457 -3.95508,4 -0.0131,8.2e-4 -0.0261,0.002 -0.0391,0.004 -0.0149,-0.002 -0.0299,-0.003 -0.0449,-0.004 -10e-4,0 -0.003,0 -0.004,0 -2.19824,-0.0228 -3.95803,-1.80057 -3.95898,-4 9e-5,-2.21578 1.78479,-4.00131 4,-4.00196 z M 516.99805,435 C 515.34742,435 514,436.34922 514,438 c 0,1.65079 1.34742,3 2.99805,3 1.65063,0 3,-1.34921 3,-3 0,-1.65078 -1.34937,-3 -3,-3 z m 0,1 c 1.11009,0 2,0.88955 2,2 0,1.11045 -0.88991,2 -2,2 C 515.88796,440 515,439.11045 515,438 c 0,-1.11045 0.88796,-2 1.99805,-2 z"
inkscape:connector-curvature="0" />
<path
inkscape:connector-curvature="0"
@@ -14448,18 +14443,18 @@
<path
inkscape:connector-curvature="0"
id="path22635-0-9"
- d="m 495.5,432 a 0.50005,0.50005 0 0 0 -0.35352,0.14648 L 493.29297,434 H 490.5 a 0.50005,0.50005 0 0 0 -0.5,0.5 v 8 a 0.50005,0.50005 0 0 0 0.5,0.5 h 12 a 0.50005,0.50005 0 0 0 0.5,-0.5 v -8 a 0.50005,0.50005 0 0 0 -0.5,-0.5 h -1.79297 l -1.85351,-1.85352 A 0.50005,0.50005 0 0 0 498.5,432 Z m 0.20703,1 h 2.58594 l 1.85351,1.85352 A 0.50005,0.50005 0 0 0 500.5,435 h 1.5 v 7 h -11 v -7 h 2.5 a 0.50005,0.50005 0 0 0 0.35352,-0.14648 z m -0.46094,2.74414 a 0.50005,0.50005 0 0 0 -0.34961,0.85938 l 1.39649,1.39648 -1.39649,1.39648 a 0.50005,0.50005 0 1 0 0.70704,0.70704 L 497,438.70703 l 1.39648,1.39649 a 0.50005,0.50005 0 1 0 0.70704,-0.70704 L 497.70703,438 l 1.39649,-1.39648 a 0.50005,0.50005 0 1 0 -0.70704,-0.70704 L 497,437.29297 l -1.39648,-1.39649 a 0.50005,0.50005 0 0 0 -0.35743,-0.15234 z"
+ d="m 494.5,432 a 0.50005,0.50005 0 0 0 -0.35352,0.14648 L 492.29297,434 H 489.5 a 0.50005,0.50005 0 0 0 -0.5,0.5 v 8 a 0.50005,0.50005 0 0 0 0.5,0.5 h 12 a 0.50005,0.50005 0 0 0 0.5,-0.5 v -8 a 0.50005,0.50005 0 0 0 -0.5,-0.5 h -1.79297 l -1.85351,-1.85352 A 0.50005,0.50005 0 0 0 497.5,432 Z m 0.20703,1 h 2.58594 l 1.85351,1.85352 A 0.50005,0.50005 0 0 0 499.5,435 h 1.5 v 7 h -11 v -7 h 2.5 a 0.50005,0.50005 0 0 0 0.35352,-0.14648 z m -0.46094,2.74414 a 0.50005,0.50005 0 0 0 -0.34961,0.85938 l 1.39649,1.39648 -1.39649,1.39648 a 0.50005,0.50005 0 1 0 0.70704,0.70704 L 496,438.70703 l 1.39648,1.39649 a 0.50005,0.50005 0 1 0 0.70704,-0.70704 L 496.70703,438 l 1.39649,-1.39648 a 0.50005,0.50005 0 1 0 -0.70704,-0.70704 L 496,437.29297 l -1.39648,-1.39649 a 0.50005,0.50005 0 0 0 -0.35743,-0.15234 z"
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:0.6;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;paint-order:fill markers stroke;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:new" />
<path
sodipodi:nodetypes="ccccccccc"
inkscape:connector-curvature="0"
id="path19969-0"
- d="m 471.49125,433 c -0.3497,0.006 -0.58488,0.36077 -0.45507,0.68555 l 4,10.00195 c 0.1779,0.45034 0.82806,0.4102 0.94922,-0.0586 l 1.17578,-4.46875 4.46679,-1.17578 c 0.46499,-0.12321 0.50486,-0.76769 0.0586,-0.94727 l -10,-4.00195 c -0.0621,-0.0247 -0.12852,-0.0366 -0.19532,-0.0351 z"
+ d="m 470.49125,433 c -0.3497,0.006 -0.58488,0.36077 -0.45507,0.68555 l 4,10.00195 c 0.1779,0.45034 0.82806,0.4102 0.94922,-0.0586 l 1.17578,-4.46875 4.46679,-1.17578 c 0.46499,-0.12321 0.50486,-0.76769 0.0586,-0.94727 l -10,-4.00195 c -0.0621,-0.0247 -0.12852,-0.0366 -0.19532,-0.0351 z"
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:new" />
<path
inkscape:connector-curvature="0"
id="path19971-4"
- d="m 450.49078,433 a 0.50005,0.50005 0 0 0 -0.45507,0.68555 l 4,10.00195 a 0.50050292,0.50050292 0 1 0 0.92968,-0.37109 l -3.5664,-8.91797 8.91601,3.5664 a 0.50005,0.50005 0 1 0 0.3711,-0.92773 l -10,-4.00195 A 0.50005,0.50005 0 0 0 450.49078,433 Z"
+ d="m 449.49078,433 a 0.50005,0.50005 0 0 0 -0.45507,0.68555 l 4,10.00195 a 0.50050292,0.50050292 0 1 0 0.92968,-0.37109 l -3.5664,-8.91797 8.91601,3.5664 a 0.50005,0.50005 0 1 0 0.3711,-0.92773 l -10,-4.00195 A 0.50005,0.50005 0 0 0 449.49078,433 Z"
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:0.6;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:new" />
<g
transform="translate(37.00977,-1667.9941)"
@@ -14570,7 +14565,7 @@
<path
inkscape:connector-curvature="0"
id="path13646-9"
- d="m 406.50195,437 a 0.50005,0.50005 0 0 0 -0.33203,0.84375 c 1.3239,1.43817 3.0824,4.1582 6.3457,4.1582 3.26331,0 5.02376,-2.72003 6.34766,-4.1582 a 0.50037481,0.50037481 0 1 0 -0.73633,-0.67773 c -1.43556,1.55946 -2.90607,3.83593 -5.61133,3.83593 -2.70525,0 -4.17576,-2.27647 -5.61132,-3.83593 A 0.50005,0.50005 0 0 0 406.50195,437 Z"
+ d="m 405.50174,437 a 0.50005,0.50005 0 0 0 -0.33203,0.84375 c 1.3239,1.43817 3.0824,4.1582 6.3457,4.1582 3.26331,0 5.02376,-2.72003 6.34766,-4.1582 a 0.50037481,0.50037481 0 1 0 -0.73633,-0.67773 c -1.43556,1.55946 -2.90607,3.83593 -5.61133,3.83593 -2.70525,0 -4.17576,-2.27647 -5.61132,-3.83593 A 0.50005,0.50005 0 0 0 405.50174,437 Z"
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:0.6;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:new" />
<g
transform="translate(315,-0.999996)"
@@ -14623,7 +14618,7 @@
<path
inkscape:connector-curvature="0"
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:new"
- d="m 433.5,433 c -3.27784,-9.4e-4 -5.036,2.7211 -6.36328,4.16211 -0.17644,0.19146 -0.17644,0.48627 0,0.67773 1.3275,1.44124 3.08593,4.15993 6.36328,4.16211 3.27801,0.002 5.03608,-2.72118 6.36328,-4.16211 0.17644,-0.19146 0.17644,-0.48627 0,-0.67773 C 438.53587,435.72096 436.77755,433.00094 433.5,433 Z m 0,1 a 3.4999952,3.4999933 0 0 1 3.5,3.5 3.4999952,3.4999933 0 0 1 -3.5,3.5 3.4999952,3.4999933 0 0 1 -3.5,-3.5 3.4999952,3.4999933 0 0 1 3.5,-3.5 z m 0,2 a 1.4999952,1.4999944 0 0 0 -1.5,1.5 1.4999952,1.4999944 0 0 0 1.5,1.5 1.4999952,1.4999944 0 0 0 1.5,-1.5 1.4999952,1.4999944 0 0 0 -1.5,-1.5 z"
+ d="m 432.49961,433 c -3.27784,-9.4e-4 -5.036,2.7211 -6.36328,4.16211 -0.17644,0.19146 -0.17644,0.48627 0,0.67773 1.3275,1.44124 3.08593,4.15993 6.36328,4.16211 3.27801,0.002 5.03608,-2.72118 6.36328,-4.16211 0.17644,-0.19146 0.17644,-0.48627 0,-0.67773 -1.32741,-1.44115 -3.08573,-4.16117 -6.36328,-4.16211 z m 0,1 a 3.4999952,3.4999933 0 0 1 3.5,3.5 3.4999952,3.4999933 0 0 1 -3.5,3.5 3.4999952,3.4999933 0 0 1 -3.5,-3.5 3.4999952,3.4999933 0 0 1 3.5,-3.5 z m 0,2 a 1.4999952,1.4999944 0 0 0 -1.5,1.5 1.4999952,1.4999944 0 0 0 1.5,1.5 1.4999952,1.4999944 0 0 0 1.5,-1.5 1.4999952,1.4999944 0 0 0 -1.5,-1.5 z"
id="path19347-7" />
<g
id="g19953"
@@ -15552,22 +15547,22 @@
</g>
<path
id="path22885-3-7"
- d="m 538.4922,557 c -0.1299,0 -0.2539,0.055 -0.3457,0.1465 -1.4018,1.4018 -2.9571,1.8535 -5.6465,1.8535 -0.2761,0 -0.5,0.2239 -0.5,0.5 v 3 c 0,2.4627 0.6805,4.0682 1.7871,5.2754 1.1066,1.2072 2.5736,2.0242 4.1777,3.1348 0.084,0.058 0.1832,0.09 0.2852,0.09 h 0.5 c 0.102,-2e-4 0.2015,-0.032 0.2852,-0.09 1.6041,-1.1106 3.0711,-1.9276 4.1777,-3.1348 C 544.3195,566.5682 545,564.9627 545,562.5 v -3 c 0,-0.2761 -0.2239,-0.5 -0.5,-0.5 -2.6894,0 -4.2447,-0.4517 -5.6465,-1.8535 -0.096,-0.096 -0.226,-0.1486 -0.3613,-0.1465 z m 3.4766,3.9902 a 1.0001,1.0001 0 0 1 0.8124,1.6348 l -4,5 a 1.0001,1.0001 0 0 1 -1.4882,0.082 l -2,-2 a 1.0001,1.0001 0 1 1 1.414,-1.414 l 1.209,1.209 3.3028,-4.127 a 1.0001,1.0001 0 0 1 0.75,-0.3848 z"
+ d="m 537.4922,557 c -0.1299,0 -0.2539,0.055 -0.3457,0.1465 -1.4018,1.4018 -2.9571,1.8535 -5.6465,1.8535 -0.2761,0 -0.5,0.2239 -0.5,0.5 v 3 c 0,2.4627 0.6805,4.0682 1.7871,5.2754 1.1066,1.2072 2.5736,2.0242 4.1777,3.1348 0.084,0.058 0.1832,0.09 0.2852,0.09 h 0.5 c 0.102,-2e-4 0.2015,-0.032 0.2852,-0.09 1.6041,-1.1106 3.0711,-1.9276 4.1777,-3.1348 C 543.3195,566.5682 544,564.9627 544,562.5 v -3 c 0,-0.2761 -0.2239,-0.5 -0.5,-0.5 -2.6894,0 -4.2447,-0.4517 -5.6465,-1.8535 -0.096,-0.096 -0.226,-0.1486 -0.3613,-0.1465 z m 3.4766,3.9902 a 1.0001,1.0001 0 0 1 0.8124,1.6348 l -4,5 a 1.0001,1.0001 0 0 1 -1.4882,0.082 l -2,-2 a 1.0001,1.0001 0 1 1 1.414,-1.414 l 1.209,1.209 3.3028,-4.127 a 1.0001,1.0001 0 0 1 0.75,-0.3848 z"
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;paint-order:fill markers stroke;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:new"
inkscape:connector-curvature="0" />
<path
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:0.6;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;paint-order:fill markers stroke;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:new"
- d="m 517.49219,557 a 0.50005,0.50005 0 0 0 -0.34571,0.14648 C 515.74469,558.54828 514.18939,559 511.5,559 a 0.50005,0.50005 0 0 0 -0.5,0.5 v 3 c 0,2.46272 0.6805,4.06818 1.78711,5.27539 1.10661,1.20722 2.57356,2.02419 4.17773,3.13477 A 0.50005,0.50005 0 0 0 517.25,571 h 0.5 a 0.50005,0.50005 0 0 0 0.28516,-0.0898 c 1.60417,-1.11058 3.07112,-1.92755 4.17773,-3.13477 C 523.3195,566.56818 524,564.96272 524,562.5 v -3 a 0.50005,0.50005 0 0 0 -0.5,-0.5 c -2.68939,0 -4.24469,-0.45172 -5.64648,-1.85352 A 0.50005,0.50005 0 0 0 517.49219,557 Z m 0.008,1.07031 c 1.42533,1.26825 3.16641,1.79779 5.5,1.86524 V 562.5 c 0,2.28728 -0.5695,3.55682 -1.52539,4.59961 -0.92707,1.01135 -2.30655,1.81425 -3.88867,2.90039 h -0.17188 c -1.58212,-1.08614 -2.9616,-1.88904 -3.88867,-2.90039 C 512.5695,566.05682 512,564.78728 512,562.5 v -2.56445 c 2.33359,-0.0675 4.07467,-0.59699 5.5,-1.86524 z"
+ d="m 516.49219,557 a 0.50005,0.50005 0 0 0 -0.34571,0.14648 C 514.74469,558.54828 513.18939,559 510.5,559 a 0.50005,0.50005 0 0 0 -0.5,0.5 v 3 c 0,2.46272 0.6805,4.06818 1.78711,5.27539 1.10661,1.20722 2.57356,2.02419 4.17773,3.13477 A 0.50005,0.50005 0 0 0 516.25,571 h 0.5 a 0.50005,0.50005 0 0 0 0.28516,-0.0898 c 1.60417,-1.11058 3.07112,-1.92755 4.17773,-3.13477 C 522.3195,566.56818 523,564.96272 523,562.5 v -3 a 0.50005,0.50005 0 0 0 -0.5,-0.5 c -2.68939,0 -4.24469,-0.45172 -5.64648,-1.85352 A 0.50005,0.50005 0 0 0 516.49219,557 Z m 0.008,1.07031 c 1.42533,1.26825 3.16641,1.79779 5.5,1.86524 V 562.5 c 0,2.28728 -0.5695,3.55682 -1.52539,4.59961 -0.92707,1.01135 -2.30655,1.81425 -3.88867,2.90039 h -0.17188 c -1.58212,-1.08614 -2.9616,-1.88904 -3.88867,-2.90039 C 511.5695,566.05682 511,564.78728 511,562.5 v -2.56445 c 2.33359,-0.0675 4.07467,-0.59699 5.5,-1.86524 z"
id="path22877-22-0"
inkscape:connector-curvature="0" />
<path
inkscape:connector-curvature="0"
- d="m 513,414.00018 h 9 v 5 h -9 z m -1.5,-2 c -0.27613,3e-5 -0.49997,0.22387 -0.5,0.5 v 8 c 3e-5,0.27613 0.22387,0.49997 0.5,0.5 h 5.5 v 1 h -2.5 c -0.67616,-0.01 -0.67616,1.00956 0,1 h 6 c 0.6573,-0.009 0.6573,-0.9907 0,-1 H 518 v -1 h 5.5 c 0.27613,-3e-5 0.49997,-0.22387 0.5,-0.5 v -8 c -3e-5,-0.27613 -0.22387,-0.49997 -0.5,-0.5 z m 0.5,1 h 11 v 7 h -11 z"
+ d="m 512,414.00018 h 9 v 5 h -9 z m -1.5,-2 c -0.27613,3e-5 -0.49997,0.22387 -0.5,0.5 v 8 c 3e-5,0.27613 0.22387,0.49997 0.5,0.5 h 5.5 v 1 h -2.5 c -0.67616,-0.01 -0.67616,1.00956 0,1 h 6 c 0.6573,-0.009 0.6573,-0.9907 0,-1 H 517 v -1 h 5.5 c 0.27613,-3e-5 0.49997,-0.22387 0.5,-0.5 v -8 c -3e-5,-0.27613 -0.22387,-0.49997 -0.5,-0.5 z m 0.5,1 h 11 v 7 h -11 z"
style="opacity:1;vector-effect:none;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;paint-order:fill markers stroke"
id="rect22324-2" />
<path
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:0.6;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:new"
- d="m 490.5,412 c -0.27613,3e-5 -0.49997,0.22387 -0.5,0.5 v 8 c 3e-5,0.27613 0.22387,0.49997 0.5,0.5 h 5.5 v 1 h -2.5 c -0.67616,-0.01 -0.67616,1.00956 0,1 h 6 c 0.6573,-0.009 0.6573,-0.9907 0,-1 H 497 v -1 h 5.5 c 0.27613,-3e-5 0.49997,-0.22387 0.5,-0.5 v -8 c -3e-5,-0.27613 -0.22387,-0.49997 -0.5,-0.5 z m 0.5,1 h 11 v 7 h -11 z"
+ d="m 489.5,412 c -0.27613,3e-5 -0.49997,0.22387 -0.5,0.5 v 8 c 3e-5,0.27613 0.22387,0.49997 0.5,0.5 h 5.5 v 1 h -2.5 c -0.67616,-0.01 -0.67616,1.00956 0,1 h 6 c 0.6573,-0.009 0.6573,-0.9907 0,-1 H 496 v -1 h 5.5 c 0.27613,-3e-5 0.49997,-0.22387 0.5,-0.5 v -8 c -3e-5,-0.27613 -0.22387,-0.49997 -0.5,-0.5 z m 0.5,1 h 11 v 7 h -11 z"
id="path22338-8"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccccccccccccccccccccc" />
@@ -15646,11 +15641,11 @@
<path
inkscape:connector-curvature="0"
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:new"
- d="m 542.77344,306 a 1.0001,1.0001 0 0 0 -0.41211,0.0781 l -4.74024,2 a 1.0004654,1.0004654 0 1 0 0.77735,1.84376 l 1.54883,-0.65235 -2.69532,5.375 -2.78906,-2.30078 a 1.50015,1.50015 0 1 0 -1.9082,2.3125 l 4.24023,3.5 a 1.50015,1.50015 0 0 0 2.29688,-0.48437 l 3.53711,-7.0586 0.41015,1.63086 a 1.0001,1.0001 0 1 0 1.93946,-0.48828 l -1.25977,-5 A 1.0001,1.0001 0 0 0 542.77344,306 Z"
+ d="m 541.77363,306 a 1.0001,1.0001 0 0 0 -0.41211,0.0781 l -4.74024,2 a 1.0004654,1.0004654 0 1 0 0.77735,1.84376 l 1.54883,-0.65235 -2.69532,5.375 -2.78906,-2.30078 a 1.50015,1.50015 0 1 0 -1.9082,2.3125 l 4.24023,3.5 a 1.50015,1.50015 0 0 0 2.29688,-0.48437 l 3.53711,-7.0586 0.41015,1.63086 a 1.0001,1.0001 0 1 0 1.93946,-0.48828 l -1.25977,-5 A 1.0001,1.0001 0 0 0 541.77363,306 Z"
id="path25427-8" />
<path
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:0.6;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
- d="m 521.51367,306 a 0.50005,0.50005 0 0 0 -0.23633,0.0527 l -4,2 a 0.50005,0.50005 0 1 0 0.44532,0.89454 l 2.8164,-1.40821 -4.20508,8.1875 -4.52148,-3.61718 a 0.50024018,0.50024018 0 1 0 -0.625,0.78124 l 5,4 a 0.50005,0.50005 0 0 0 0.75781,-0.1621 l 4.4375,-8.64063 0.63281,2.5332 a 0.50005,0.50005 0 1 0 0.96876,-0.24218 l -1,-4 A 0.50005,0.50005 0 0 0 521.51367,306 Z"
+ d="m 520.51395,306 a 0.50005,0.50005 0 0 0 -0.23633,0.0527 l -4,2 a 0.50005,0.50005 0 1 0 0.44532,0.89454 l 2.8164,-1.40821 -4.20508,8.1875 -4.52148,-3.61718 a 0.50024018,0.50024018 0 1 0 -0.625,0.78124 l 5,4 a 0.50005,0.50005 0 0 0 0.75781,-0.1621 l 4.4375,-8.64063 0.63281,2.5332 a 0.50005,0.50005 0 1 0 0.96876,-0.24218 l -1,-4 A 0.50005,0.50005 0 0 0 520.51395,306 Z"
id="path25488-0"
inkscape:connector-curvature="0" />
<g
@@ -17355,21 +17350,21 @@
id="g905">
<g
transform="matrix(0.6740384,0,0,0.6740384,192.80592,-339.68227)"
- style="display:inline;opacity:0.99;fill:#ffffff;stroke-width:1.07692;enable-background:new"
+ style="display:inline;opacity:0.99;fill:#ffffff;stroke-width:1.07692;enable-background:new"
id="g8599-6-7"
- inkscape:export-filename="blender_icons.png"
- inkscape:export-xdpi="96"
- inkscape:export-ydpi="96">
- <path
+ inkscape:export-filename="blender_icons.png"
+ inkscape:export-xdpi="96"
+ inkscape:export-ydpi="96">
+ <path
id="path8597-7-0"
d="m 331.87142,629.24052 c 0,0.81936 -0.66423,1.48359 -1.48359,1.48359 -0.81937,0 -1.4836,-0.66422 -1.4836,-1.48359 0,-0.81937 0.66423,-1.4836 1.4836,-1.4836 0.81937,0 1.48359,0.66423 1.48359,1.4836 z"
style="opacity:1;vector-effect:none;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1.72218;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;paint-order:fill markers stroke"
inkscape:connector-curvature="0"
sodipodi:nodetypes="sssss" />
- </g>
- <path
+ </g>
+ <path
sodipodi:nodetypes="cccccccccczzcczzzzz"
- inkscape:connector-curvature="0"
+ inkscape:connector-curvature="0"
id="path8595-5-9"
d="m 414.93725,78.999996 c -0.65344,-0.653443 -1.58833,0.255453 -0.88297,0.960812 L 415.18167,81 h -4.6057 c -0.88913,-0.01822 -0.88913,1.018254 0,1 l 2.19337,-0.004 -0.006,0.004 -3.27651,2.873468 c -0.64989,0.580999 0.2216,1.555837 0.87149,0.97484 L 412.00004,84.45 c 0,1.651946 1.15621,3.581251 3.47506,3.550001 C 417.79395,87.968751 419,86.250706 419,84.45 c 0,-1.800705 -1.00462,-2.558141 -1.45954,-3.013074 z M 415.5,82.2 c 1.22478,0 2.25,0.945047 2.25,2.25 0,1.304953 -1.05311,2.25 -2.25,2.25 -1.19689,0 -2.25,-0.960585 -2.25,-2.25 0,-1.289415 1.02522,-2.25 2.25,-2.25 z"
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.3066;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;paint-order:fill markers stroke;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
@@ -17431,25 +17426,25 @@
d="m 414.93725,78.992499 c -0.65344,-0.653443 -1.58833,0.255453 -0.88297,0.960812 l 1.12739,1.039192 h -4.6057 c -0.88913,-0.01822 -0.88913,1.018254 0,1 l 2.19337,-0.004 -0.006,0.004 -3.27651,2.873468 c -0.64989,0.580999 0.2216,1.555837 0.87149,0.97484 l 1.64161,-1.398308 c 0,1.651946 1.15632,3.581251 3.47517,3.550001 2.31885,-0.03125 3.5249,-1.749295 3.5249,-3.550001 0,-1.800705 -1.00462,-2.558141 -1.45954,-3.013074 z M 415.5,82.192503 c 1.22478,0 2.25,0.945047 2.25,2.25 0,1.304953 -1.05311,2.25 -2.25,2.25 -1.19689,0 -2.25,-0.960585 -2.25,-2.25 0,-1.289415 1.02522,-2.25 2.25,-2.25 z"
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.3066;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;paint-order:fill markers stroke;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
</g>
- <g
+ <g
transform="translate(19.000003)"
id="g28228-3-3"
style="display:inline;opacity:0.6;stroke:#ffffff;enable-background:new"
- inkscape:export-filename="blender_icons.png"
- inkscape:export-xdpi="96"
- inkscape:export-ydpi="96">
+ inkscape:export-filename="blender_icons.png"
+ inkscape:export-xdpi="96"
+ inkscape:export-ydpi="96">
<g
id="g28217-6-6"
transform="translate(338.99999,-439.99995)"
style="display:inline;opacity:0.99;stroke:#ffffff;enable-background:new">
- <path
- inkscape:connector-curvature="0"
+ <path
+ inkscape:connector-curvature="0"
id="path28215-0"
transform="translate(-337.99999,439.99995)"
d="m 501.49219,52.992188 c -0.27615,0.0043 -0.49651,0.223792 -0.49219,0.499938 v 1 c -0.01,0.676161 1.00956,0.676161 1,0 v -1 c 0.004,-0.282265 -0.22554,-0.504353 -0.50781,-0.499938 z m -7.00781,0.0067 c -0.12718,0.004 -0.248,0.0564 -0.3379,0.146484 l -4,4.001116 c -0.10126,0.101337 -0.1304,0.223491 -0.13086,0.345704 L 490,57.507812 v 1.984314 c -0.01,0.676161 1.00956,0.676161 1,0 v -1.5 h 3.5 c 0.27613,-3e-5 0.49997,-0.22387 0.5,-0.5 v -3.5 h 1.5 c 0.67616,0.0096 0.67616,-1.002805 0,-0.993242 h -2 v 0.002 c -0.005,-5e-6 -0.0101,-0.0021 -0.0156,-0.002 z m 4.01562,-0.0068 c -0.67616,-0.0096 -0.67616,1.009563 0,1 h 1 c 0.67616,0.0096 0.67616,-1.009563 0,-1 z m 2.99219,3.000062 c -0.27615,0.0043 -0.49651,0.223792 -0.49219,0.499938 v 1 c -0.01,0.676161 1.00956,0.676161 1,0 v -1 c 0.004,-0.282265 -0.22554,-0.504353 -0.50781,-0.499938 z m -11,5 c -0.27615,0.0043 -0.49651,0.223792 -0.49219,0.499938 v 1 c -0.01,0.676161 1.00956,0.676161 1,0 v -1 c 0.004,-0.282265 -0.22554,-0.504353 -0.50781,-0.499938 z m 0,3 c -0.27615,0.0043 -0.49651,0.223792 -0.49219,0.499938 v 1 c -0.01,0.676161 1.00956,0.676161 1,0 v -1 c 0.004,-0.282265 -0.22554,-0.504353 -0.50781,-0.499938 z M 492.5,65.992126 c -0.67616,-0.0096 -0.67616,1.009563 0,1 h 1 c 0.67616,0.0096 0.67616,-1.009563 0,-1 z m 3,0 c -0.67616,-0.0096 -0.67616,1.009563 0,1 h 1 c 0.67616,0.0096 0.67616,-1.009563 0,-1 z"
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
sodipodi:nodetypes="cccccccccccccccccccccccccccccccccccccccccccccccccccccccc" />
- </g>
+ </g>
</g>
</g>
</g>
@@ -17471,10 +17466,10 @@
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccccccscccccccccccccccc" />
</g>
- <path
+ <path
sodipodi:nodetypes="csscccccccccccssscccc"
style="opacity:0.6;fill:#ffffff"
- inkscape:connector-curvature="0"
+ inkscape:connector-curvature="0"
id="path2-6"
d="m 469,101 v 7.5 c 0,0.276 0.224,0.5 0.5,0.5 h 11 c 0.30423,0 0.5,-0.22782 0.5,-0.5 v -4 c 0,-0.65459 -1,-0.65682 -1,0 v 3.5 h -10 v -7 z m 4.48081,-6 c -0.151,0.004 -0.293,0.077 -0.384,0.197 l -3.95,3.949 c -0.314,0.315 -0.091,0.854 0.354,0.854 h 4 c 0.276,0 0.5,-0.224 0.5,-0.5 V 96 H 480.5 c 0.68512,0 0.64092,-1 0,-1 z" />
</g>
diff --git a/release/datafiles/blender_icons16/icon16_editmode_hlt.dat b/release/datafiles/blender_icons16/icon16_editmode_hlt.dat
index a29abf4e4c8..69d4e3bc4a9 100644
--- a/release/datafiles/blender_icons16/icon16_editmode_hlt.dat
+++ b/release/datafiles/blender_icons16/icon16_editmode_hlt.dat
Binary files differ
diff --git a/release/datafiles/blender_icons16/icon16_fake_user_off.dat b/release/datafiles/blender_icons16/icon16_fake_user_off.dat
index a40ac7a148e..1807949b579 100644
--- a/release/datafiles/blender_icons16/icon16_fake_user_off.dat
+++ b/release/datafiles/blender_icons16/icon16_fake_user_off.dat
Binary files differ
diff --git a/release/datafiles/blender_icons16/icon16_fake_user_on.dat b/release/datafiles/blender_icons16/icon16_fake_user_on.dat
index ea1176dacc3..d7f5a678d40 100644
--- a/release/datafiles/blender_icons16/icon16_fake_user_on.dat
+++ b/release/datafiles/blender_icons16/icon16_fake_user_on.dat
Binary files differ
diff --git a/release/datafiles/blender_icons16/icon16_force_boid.dat b/release/datafiles/blender_icons16/icon16_force_boid.dat
index f719054d84a..71f89bd7c04 100644
--- a/release/datafiles/blender_icons16/icon16_force_boid.dat
+++ b/release/datafiles/blender_icons16/icon16_force_boid.dat
Binary files differ
diff --git a/release/datafiles/blender_icons16/icon16_hide_off.dat b/release/datafiles/blender_icons16/icon16_hide_off.dat
index e6917365472..5de3e7d5b00 100644
--- a/release/datafiles/blender_icons16/icon16_hide_off.dat
+++ b/release/datafiles/blender_icons16/icon16_hide_off.dat
Binary files differ
diff --git a/release/datafiles/blender_icons16/icon16_hide_on.dat b/release/datafiles/blender_icons16/icon16_hide_on.dat
index 6303cd53ccf..7930a98a873 100644
--- a/release/datafiles/blender_icons16/icon16_hide_on.dat
+++ b/release/datafiles/blender_icons16/icon16_hide_on.dat
Binary files differ
diff --git a/release/datafiles/blender_icons16/icon16_indirect_only_off.dat b/release/datafiles/blender_icons16/icon16_indirect_only_off.dat
index 58f89be44f6..f7c6c6094e3 100644
--- a/release/datafiles/blender_icons16/icon16_indirect_only_off.dat
+++ b/release/datafiles/blender_icons16/icon16_indirect_only_off.dat
Binary files differ
diff --git a/release/datafiles/blender_icons16/icon16_indirect_only_on.dat b/release/datafiles/blender_icons16/icon16_indirect_only_on.dat
index 2b2b73455ce..d7e504adf0a 100644
--- a/release/datafiles/blender_icons16/icon16_indirect_only_on.dat
+++ b/release/datafiles/blender_icons16/icon16_indirect_only_on.dat
Binary files differ
diff --git a/release/datafiles/blender_icons16/icon16_library_data_indirect.dat b/release/datafiles/blender_icons16/icon16_library_data_indirect.dat
deleted file mode 100644
index 78c012bb755..00000000000
--- a/release/datafiles/blender_icons16/icon16_library_data_indirect.dat
+++ /dev/null
Binary files differ
diff --git a/release/datafiles/blender_icons16/icon16_object_datamode.dat b/release/datafiles/blender_icons16/icon16_object_datamode.dat
index 28293424510..2d2545d372a 100644
--- a/release/datafiles/blender_icons16/icon16_object_datamode.dat
+++ b/release/datafiles/blender_icons16/icon16_object_datamode.dat
Binary files differ
diff --git a/release/datafiles/blender_icons16/icon16_particlemode.dat b/release/datafiles/blender_icons16/icon16_particlemode.dat
index 1a32156a7b8..b5e1321d5f0 100644
--- a/release/datafiles/blender_icons16/icon16_particlemode.dat
+++ b/release/datafiles/blender_icons16/icon16_particlemode.dat
Binary files differ
diff --git a/release/datafiles/blender_icons16/icon16_pose_hlt.dat b/release/datafiles/blender_icons16/icon16_pose_hlt.dat
index 3a59a1c9274..fd3fd905d21 100644
--- a/release/datafiles/blender_icons16/icon16_pose_hlt.dat
+++ b/release/datafiles/blender_icons16/icon16_pose_hlt.dat
Binary files differ
diff --git a/release/datafiles/blender_icons16/icon16_restrict_render_off.dat b/release/datafiles/blender_icons16/icon16_restrict_render_off.dat
index 5eab5eaa538..db720670903 100644
--- a/release/datafiles/blender_icons16/icon16_restrict_render_off.dat
+++ b/release/datafiles/blender_icons16/icon16_restrict_render_off.dat
Binary files differ
diff --git a/release/datafiles/blender_icons16/icon16_restrict_render_on.dat b/release/datafiles/blender_icons16/icon16_restrict_render_on.dat
index 29bebb2ee75..3db7aa2bb86 100644
--- a/release/datafiles/blender_icons16/icon16_restrict_render_on.dat
+++ b/release/datafiles/blender_icons16/icon16_restrict_render_on.dat
Binary files differ
diff --git a/release/datafiles/blender_icons16/icon16_restrict_select_off.dat b/release/datafiles/blender_icons16/icon16_restrict_select_off.dat
index fa8bbcb3a04..26bc4f16244 100644
--- a/release/datafiles/blender_icons16/icon16_restrict_select_off.dat
+++ b/release/datafiles/blender_icons16/icon16_restrict_select_off.dat
Binary files differ
diff --git a/release/datafiles/blender_icons16/icon16_restrict_select_on.dat b/release/datafiles/blender_icons16/icon16_restrict_select_on.dat
index 8fd1bcc97ab..eb106e5f4b1 100644
--- a/release/datafiles/blender_icons16/icon16_restrict_select_on.dat
+++ b/release/datafiles/blender_icons16/icon16_restrict_select_on.dat
Binary files differ
diff --git a/release/datafiles/blender_icons16/icon16_restrict_view_off.dat b/release/datafiles/blender_icons16/icon16_restrict_view_off.dat
index 7b116a56356..717d8d04f32 100644
--- a/release/datafiles/blender_icons16/icon16_restrict_view_off.dat
+++ b/release/datafiles/blender_icons16/icon16_restrict_view_off.dat
Binary files differ
diff --git a/release/datafiles/blender_icons16/icon16_restrict_view_on.dat b/release/datafiles/blender_icons16/icon16_restrict_view_on.dat
index 60ed6d0ef42..54fda79d24e 100644
--- a/release/datafiles/blender_icons16/icon16_restrict_view_on.dat
+++ b/release/datafiles/blender_icons16/icon16_restrict_view_on.dat
Binary files differ
diff --git a/release/datafiles/blender_icons16/icon16_sculptmode_hlt.dat b/release/datafiles/blender_icons16/icon16_sculptmode_hlt.dat
index ab8fbd88fe1..ac49226b300 100644
--- a/release/datafiles/blender_icons16/icon16_sculptmode_hlt.dat
+++ b/release/datafiles/blender_icons16/icon16_sculptmode_hlt.dat
Binary files differ
diff --git a/release/datafiles/blender_icons16/icon16_tpaint_hlt.dat b/release/datafiles/blender_icons16/icon16_tpaint_hlt.dat
index 9a56ff6177f..3537aa62099 100644
--- a/release/datafiles/blender_icons16/icon16_tpaint_hlt.dat
+++ b/release/datafiles/blender_icons16/icon16_tpaint_hlt.dat
Binary files differ
diff --git a/release/datafiles/blender_icons16/icon16_uv_data.dat b/release/datafiles/blender_icons16/icon16_uv_data.dat
index bea802a3bcb..b843c28ee26 100644
--- a/release/datafiles/blender_icons16/icon16_uv_data.dat
+++ b/release/datafiles/blender_icons16/icon16_uv_data.dat
Binary files differ
diff --git a/release/datafiles/blender_icons16/icon16_vpaint_hlt.dat b/release/datafiles/blender_icons16/icon16_vpaint_hlt.dat
index 0ad483ac862..7b4b42af987 100644
--- a/release/datafiles/blender_icons16/icon16_vpaint_hlt.dat
+++ b/release/datafiles/blender_icons16/icon16_vpaint_hlt.dat
Binary files differ
diff --git a/release/datafiles/blender_icons16/icon16_wpaint_hlt.dat b/release/datafiles/blender_icons16/icon16_wpaint_hlt.dat
index 199a859bb5d..f5eaf8ff566 100644
--- a/release/datafiles/blender_icons16/icon16_wpaint_hlt.dat
+++ b/release/datafiles/blender_icons16/icon16_wpaint_hlt.dat
Binary files differ
diff --git a/release/datafiles/blender_icons32/icon32_editmode_hlt.dat b/release/datafiles/blender_icons32/icon32_editmode_hlt.dat
index 6bfcaafe875..1a2f4ad096a 100644
--- a/release/datafiles/blender_icons32/icon32_editmode_hlt.dat
+++ b/release/datafiles/blender_icons32/icon32_editmode_hlt.dat
Binary files differ
diff --git a/release/datafiles/blender_icons32/icon32_fake_user_off.dat b/release/datafiles/blender_icons32/icon32_fake_user_off.dat
index 2e111fa7ba6..53a555f8ac5 100644
--- a/release/datafiles/blender_icons32/icon32_fake_user_off.dat
+++ b/release/datafiles/blender_icons32/icon32_fake_user_off.dat
Binary files differ
diff --git a/release/datafiles/blender_icons32/icon32_fake_user_on.dat b/release/datafiles/blender_icons32/icon32_fake_user_on.dat
index ce276de53d6..81ad3792699 100644
--- a/release/datafiles/blender_icons32/icon32_fake_user_on.dat
+++ b/release/datafiles/blender_icons32/icon32_fake_user_on.dat
Binary files differ
diff --git a/release/datafiles/blender_icons32/icon32_force_boid.dat b/release/datafiles/blender_icons32/icon32_force_boid.dat
index 9043989024b..7fc7cb5ee8c 100644
--- a/release/datafiles/blender_icons32/icon32_force_boid.dat
+++ b/release/datafiles/blender_icons32/icon32_force_boid.dat
Binary files differ
diff --git a/release/datafiles/blender_icons32/icon32_hide_off.dat b/release/datafiles/blender_icons32/icon32_hide_off.dat
index 3194af95943..17469a6095c 100644
--- a/release/datafiles/blender_icons32/icon32_hide_off.dat
+++ b/release/datafiles/blender_icons32/icon32_hide_off.dat
Binary files differ
diff --git a/release/datafiles/blender_icons32/icon32_hide_on.dat b/release/datafiles/blender_icons32/icon32_hide_on.dat
index 50de267bc78..722c25943d5 100644
--- a/release/datafiles/blender_icons32/icon32_hide_on.dat
+++ b/release/datafiles/blender_icons32/icon32_hide_on.dat
Binary files differ
diff --git a/release/datafiles/blender_icons32/icon32_indirect_only_off.dat b/release/datafiles/blender_icons32/icon32_indirect_only_off.dat
index a30545787fc..5dc49925a5a 100644
--- a/release/datafiles/blender_icons32/icon32_indirect_only_off.dat
+++ b/release/datafiles/blender_icons32/icon32_indirect_only_off.dat
Binary files differ
diff --git a/release/datafiles/blender_icons32/icon32_indirect_only_on.dat b/release/datafiles/blender_icons32/icon32_indirect_only_on.dat
index d2b9e894aca..31b4d64986b 100644
--- a/release/datafiles/blender_icons32/icon32_indirect_only_on.dat
+++ b/release/datafiles/blender_icons32/icon32_indirect_only_on.dat
Binary files differ
diff --git a/release/datafiles/blender_icons32/icon32_library_data_indirect.dat b/release/datafiles/blender_icons32/icon32_library_data_indirect.dat
deleted file mode 100644
index bc8198d8a5b..00000000000
--- a/release/datafiles/blender_icons32/icon32_library_data_indirect.dat
+++ /dev/null
Binary files differ
diff --git a/release/datafiles/blender_icons32/icon32_object_datamode.dat b/release/datafiles/blender_icons32/icon32_object_datamode.dat
index d4086196780..32173788c7e 100644
--- a/release/datafiles/blender_icons32/icon32_object_datamode.dat
+++ b/release/datafiles/blender_icons32/icon32_object_datamode.dat
Binary files differ
diff --git a/release/datafiles/blender_icons32/icon32_particlemode.dat b/release/datafiles/blender_icons32/icon32_particlemode.dat
index 343c568ec73..64edd74f980 100644
--- a/release/datafiles/blender_icons32/icon32_particlemode.dat
+++ b/release/datafiles/blender_icons32/icon32_particlemode.dat
Binary files differ
diff --git a/release/datafiles/blender_icons32/icon32_pose_hlt.dat b/release/datafiles/blender_icons32/icon32_pose_hlt.dat
index af5b10ad63a..d5f05a2e730 100644
--- a/release/datafiles/blender_icons32/icon32_pose_hlt.dat
+++ b/release/datafiles/blender_icons32/icon32_pose_hlt.dat
Binary files differ
diff --git a/release/datafiles/blender_icons32/icon32_restrict_render_off.dat b/release/datafiles/blender_icons32/icon32_restrict_render_off.dat
index 7f6cf73fea0..d1cc5a755c4 100644
--- a/release/datafiles/blender_icons32/icon32_restrict_render_off.dat
+++ b/release/datafiles/blender_icons32/icon32_restrict_render_off.dat
Binary files differ
diff --git a/release/datafiles/blender_icons32/icon32_restrict_render_on.dat b/release/datafiles/blender_icons32/icon32_restrict_render_on.dat
index 18184f7fe5f..0d80bea7add 100644
--- a/release/datafiles/blender_icons32/icon32_restrict_render_on.dat
+++ b/release/datafiles/blender_icons32/icon32_restrict_render_on.dat
Binary files differ
diff --git a/release/datafiles/blender_icons32/icon32_restrict_select_off.dat b/release/datafiles/blender_icons32/icon32_restrict_select_off.dat
index b7163da17a0..3e009393eac 100644
--- a/release/datafiles/blender_icons32/icon32_restrict_select_off.dat
+++ b/release/datafiles/blender_icons32/icon32_restrict_select_off.dat
Binary files differ
diff --git a/release/datafiles/blender_icons32/icon32_restrict_select_on.dat b/release/datafiles/blender_icons32/icon32_restrict_select_on.dat
index a4149dc650d..fd8b8c29064 100644
--- a/release/datafiles/blender_icons32/icon32_restrict_select_on.dat
+++ b/release/datafiles/blender_icons32/icon32_restrict_select_on.dat
Binary files differ
diff --git a/release/datafiles/blender_icons32/icon32_restrict_view_off.dat b/release/datafiles/blender_icons32/icon32_restrict_view_off.dat
index df30b2e873f..3737dd34d39 100644
--- a/release/datafiles/blender_icons32/icon32_restrict_view_off.dat
+++ b/release/datafiles/blender_icons32/icon32_restrict_view_off.dat
Binary files differ
diff --git a/release/datafiles/blender_icons32/icon32_restrict_view_on.dat b/release/datafiles/blender_icons32/icon32_restrict_view_on.dat
index 02c08a102d2..d85859c3aed 100644
--- a/release/datafiles/blender_icons32/icon32_restrict_view_on.dat
+++ b/release/datafiles/blender_icons32/icon32_restrict_view_on.dat
Binary files differ
diff --git a/release/datafiles/blender_icons32/icon32_sculptmode_hlt.dat b/release/datafiles/blender_icons32/icon32_sculptmode_hlt.dat
index 8590aa141c5..e5dfa527311 100644
--- a/release/datafiles/blender_icons32/icon32_sculptmode_hlt.dat
+++ b/release/datafiles/blender_icons32/icon32_sculptmode_hlt.dat
Binary files differ
diff --git a/release/datafiles/blender_icons32/icon32_tpaint_hlt.dat b/release/datafiles/blender_icons32/icon32_tpaint_hlt.dat
index b92dec6ef42..cd21f05419c 100644
--- a/release/datafiles/blender_icons32/icon32_tpaint_hlt.dat
+++ b/release/datafiles/blender_icons32/icon32_tpaint_hlt.dat
Binary files differ
diff --git a/release/datafiles/blender_icons32/icon32_uv_data.dat b/release/datafiles/blender_icons32/icon32_uv_data.dat
index d7bf1314c0c..9ef062e760e 100644
--- a/release/datafiles/blender_icons32/icon32_uv_data.dat
+++ b/release/datafiles/blender_icons32/icon32_uv_data.dat
Binary files differ
diff --git a/release/datafiles/blender_icons32/icon32_vpaint_hlt.dat b/release/datafiles/blender_icons32/icon32_vpaint_hlt.dat
index 71d263c5bc9..cee921a6ba8 100644
--- a/release/datafiles/blender_icons32/icon32_vpaint_hlt.dat
+++ b/release/datafiles/blender_icons32/icon32_vpaint_hlt.dat
Binary files differ
diff --git a/release/datafiles/blender_icons32/icon32_wpaint_hlt.dat b/release/datafiles/blender_icons32/icon32_wpaint_hlt.dat
index 9f3bb8421af..0d12a956ef7 100644
--- a/release/datafiles/blender_icons32/icon32_wpaint_hlt.dat
+++ b/release/datafiles/blender_icons32/icon32_wpaint_hlt.dat
Binary files differ
diff --git a/release/datafiles/userdef/userdef_default_theme.c b/release/datafiles/userdef/userdef_default_theme.c
index 292080ef629..08f91781aa0 100644
--- a/release/datafiles/userdef/userdef_default_theme.c
+++ b/release/datafiles/userdef/userdef_default_theme.c
@@ -833,7 +833,7 @@ const bTheme U_theme_default = {
.outline_width = 1,
.facedot_size = 4,
.noodle_curving = 4,
- .grid_levels = 7,
+ .grid_levels = 3,
.dash_alpha = 0.5f,
.syntaxl = RGBA(0x303030ff),
.syntaxs = RGBA(0x973c3cff),
diff --git a/release/license/THIRD-PARTY-LICENSES.txt b/release/license/THIRD-PARTY-LICENSES.txt
index 933f03b5564..59f53832c9b 100644
--- a/release/license/THIRD-PARTY-LICENSES.txt
+++ b/release/license/THIRD-PARTY-LICENSES.txt
@@ -2961,6 +2961,8 @@ 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
+** {fmt}; version 8.1.1 -- https://github.com/fmtlib/fmt
+Copyright (c) 2012 - present, Victor Zverovich
** JSON for Modern C++; version 3.10.2 -- https://github.com/nlohmann/json/
Copyright (c) 2013-2021 Niels Lohmann
** Libxml2; version 2.9.10 -- http://xmlsoft.org/
diff --git a/release/scripts/modules/bl_i18n_utils/settings.py b/release/scripts/modules/bl_i18n_utils/settings.py
index f8975d91f86..ef481a3eb19 100644
--- a/release/scripts/modules/bl_i18n_utils/settings.py
+++ b/release/scripts/modules/bl_i18n_utils/settings.py
@@ -340,7 +340,10 @@ WARN_MSGID_NOT_CAPITALIZED_ALLOWED = {
"y",
"y = (Ax + B)",
# Sub-strings.
+ "all",
+ "all and invert unselected",
"and AMD Radeon Pro 21.Q4 driver or newer",
+ "and NVIDIA driver version 470 or newer",
"available with",
"brown fox",
"can't save image while rendering",
@@ -358,6 +361,7 @@ WARN_MSGID_NOT_CAPITALIZED_ALLOWED = {
"face data",
"gimbal",
"global",
+ "glTF Settings",
"image file not found",
"image format is read-only",
"image path can't be written to",
@@ -370,8 +374,12 @@ WARN_MSGID_NOT_CAPITALIZED_ALLOWED = {
"multi-res modifier",
"non-triangle face",
"normal",
+ "or AMD with macOS 12.3 or newer",
"performance impact!",
"right",
+ "selected",
+ "selected and lock unselected",
+ "selected and unlock unselected",
"the lazy dog",
"to the top level of the tree",
"unable to load movie clip",
@@ -380,6 +388,7 @@ WARN_MSGID_NOT_CAPITALIZED_ALLOWED = {
"unknown error reading file",
"unknown error stating file",
"unknown error writing file",
+ "unselected",
"unsupported font format",
"unsupported format",
"unsupported image format",
diff --git a/release/scripts/modules/bl_i18n_utils/utils_spell_check.py b/release/scripts/modules/bl_i18n_utils/utils_spell_check.py
index 144b7d09422..c0e065bf050 100644
--- a/release/scripts/modules/bl_i18n_utils/utils_spell_check.py
+++ b/release/scripts/modules/bl_i18n_utils/utils_spell_check.py
@@ -104,6 +104,7 @@ class SpellChecker:
"builtin", "builtins",
"bytecode",
"chunksize",
+ "codebase",
"customdata",
"dataset", "datasets",
"de",
@@ -123,6 +124,7 @@ class SpellChecker:
"filepath", "filepaths",
"forcefield", "forcefields",
"framerange",
+ "frontmost",
"fulldome", "fulldomes",
"fullscreen",
"gamepad",
diff --git a/release/scripts/presets/interface_theme/Blender_Light.xml b/release/scripts/presets/interface_theme/Blender_Light.xml
index 9a315763c8b..49955bc3ff9 100644
--- a/release/scripts/presets/interface_theme/Blender_Light.xml
+++ b/release/scripts/presets/interface_theme/Blender_Light.xml
@@ -955,7 +955,7 @@
matte_node="#977474"
distor_node="#749797"
noodle_curving="4"
- grid_levels="7"
+ grid_levels="3"
dash_alpha="0.5"
input_node="#cb3d4a"
output_node="#cb3d4a"
diff --git a/release/scripts/presets/keyconfig/keymap_data/blender_default.py b/release/scripts/presets/keyconfig/keymap_data/blender_default.py
index d307c3d0f0a..b626f6a237a 100644
--- a/release/scripts/presets/keyconfig/keymap_data/blender_default.py
+++ b/release/scripts/presets/keyconfig/keymap_data/blender_default.py
@@ -4690,7 +4690,7 @@ def _template_paint_radial_control(paint, rotation=False, secondary_rotation=Fal
def _template_view3d_select(*, type, value, legacy, select_passthrough, exclude_mod=None):
# NOTE: `exclude_mod` is needed since we don't want this tool to exclude Control-RMB actions when this is used
# as a tool key-map with RMB-select and `use_fallback_tool_rmb` is enabled. See T92467.
- return [(
+ items = [(
"view3d.select",
{"type": type, "value": value, **{m: True for m in mods}},
{"properties": [(c, True) for c in props]},
@@ -4706,6 +4706,17 @@ def _template_view3d_select(*, type, value, legacy, select_passthrough, exclude_
(("toggle", "center", "enumerate"), ("shift", "ctrl", "alt")),
) if exclude_mod is None or exclude_mod not in mods]
+ if select_passthrough and (value == 'PRESS'):
+ # Add an additional click item to de-select all other items,
+ # needed so pass-through is able to de-select other items.
+ items.append((
+ "view3d.select",
+ {"type": type, "value": 'CLICK'},
+ {"properties": [("deselect_all", True)]},
+ ))
+
+ return items
+
def _template_view3d_gpencil_select(*, type, value, legacy, use_select_mouse=True):
return [
@@ -4723,7 +4734,7 @@ def _template_view3d_gpencil_select(*, type, value, legacy, use_select_mouse=Tru
def _template_uv_select(*, type, value, select_passthrough, legacy):
- return [
+ items = [
("uv.select", {"type": type, "value": value},
{"properties": [
*((("deselect_all", True),) if not legacy else ()),
@@ -4733,6 +4744,17 @@ def _template_uv_select(*, type, value, select_passthrough, legacy):
{"properties": [("toggle", True)]}),
]
+ if select_passthrough and (value == 'PRESS'):
+ # Add an additional click item to de-select all other items,
+ # needed so pass-through is able to de-select other items.
+ items.append((
+ "uv.select",
+ {"type": type, "value": 'CLICK'},
+ {"properties": [("deselect_all", True)]},
+ ))
+
+ return items
+
def _template_sequencer_generic_select(*, type, value, legacy):
return [(
diff --git a/release/scripts/startup/bl_operators/geometry_nodes.py b/release/scripts/startup/bl_operators/geometry_nodes.py
index 3616bf52540..c3892e988c5 100644
--- a/release/scripts/startup/bl_operators/geometry_nodes.py
+++ b/release/scripts/startup/bl_operators/geometry_nodes.py
@@ -26,7 +26,7 @@ def geometry_node_group_empty_new():
def geometry_modifier_poll(context):
ob = context.object
- # Test object support for geometry node modifier (No hair object support yet)
+ # Test object support for geometry node modifier (No curves object support yet)
if not ob or ob.type not in {'MESH', 'POINTCLOUD', 'VOLUME', 'CURVE', 'FONT'}:
return False
@@ -50,6 +50,9 @@ class NewGeometryNodesModifier(Operator):
if not modifier:
return {'CANCELLED'}
+ group = geometry_node_group_empty_new()
+ modifier.node_group = group
+
return {'FINISHED'}
diff --git a/release/scripts/startup/bl_ui/properties_grease_pencil_common.py b/release/scripts/startup/bl_ui/properties_grease_pencil_common.py
index 947a7e5c7a7..481753d5e79 100644
--- a/release/scripts/startup/bl_ui/properties_grease_pencil_common.py
+++ b/release/scripts/startup/bl_ui/properties_grease_pencil_common.py
@@ -361,6 +361,10 @@ class GPENCIL_UL_annotation_layer(UIList):
split.prop(gpl, "info", text="", emboss=False)
row = layout.row(align=True)
+
+ icon_xray = 'XRAY' if gpl.show_in_front else 'FACESEL'
+ row.prop(gpl, "show_in_front", text="", icon=icon_xray, emboss=False)
+
row.prop(gpl, "annotation_hide", text="", emboss=False)
elif self.layout_type == 'GRID':
layout.alignment = 'CENTER'
diff --git a/release/scripts/startup/bl_ui/properties_object.py b/release/scripts/startup/bl_ui/properties_object.py
index 89f840306e1..44c30cf4372 100644
--- a/release/scripts/startup/bl_ui/properties_object.py
+++ b/release/scripts/startup/bl_ui/properties_object.py
@@ -246,7 +246,7 @@ class OBJECT_PT_instancing(ObjectButtonsPanel, Panel):
def poll(cls, context):
ob = context.object
# FONT objects need (vertex) instancing for the 'Object Font' feature
- return (ob.type in {'MESH', 'EMPTY', 'POINTCLOUD', 'FONT'})
+ return (ob.type in {'MESH', 'EMPTY', 'FONT'})
def draw(self, context):
layout = self.layout
diff --git a/release/scripts/startup/bl_ui/properties_physics_fluid.py b/release/scripts/startup/bl_ui/properties_physics_fluid.py
index 0e8e452c717..f8dea120db3 100644
--- a/release/scripts/startup/bl_ui/properties_physics_fluid.py
+++ b/release/scripts/startup/bl_ui/properties_physics_fluid.py
@@ -55,7 +55,7 @@ class PhysicButtonsPanel:
md = context.fluid
if md and (md.fluid_type == 'DOMAIN'):
domain = md.domain_settings
- return domain.domain_type in {'GAS'}
+ return domain.domain_type == 'GAS'
return False
@staticmethod
@@ -66,7 +66,7 @@ class PhysicButtonsPanel:
md = context.fluid
if md and (md.fluid_type == 'DOMAIN'):
domain = md.domain_settings
- return domain.domain_type in {'LIQUID'}
+ return domain.domain_type == 'LIQUID'
return False
@staticmethod
@@ -812,7 +812,7 @@ class PHYSICS_PT_mesh(PhysicButtonsPanel, Panel):
col.separator()
col.prop(domain, "mesh_generator", text="Mesh Generator")
- if domain.mesh_generator in {'IMPROVED'}:
+ if domain.mesh_generator == 'IMPROVED':
col = flow.column(align=True)
col.prop(domain, "mesh_smoothen_pos", text="Smoothing Positive")
col.prop(domain, "mesh_smoothen_neg", text="Negative")
@@ -1227,7 +1227,7 @@ class PHYSICS_PT_cache(PhysicButtonsPanel, Panel):
row.enabled = not is_baking_any and not has_baked_data
row.prop(domain, "cache_data_format", text="Format Volumes")
- if md.domain_settings.domain_type in {'LIQUID'} and domain.use_mesh:
+ if md.domain_settings.domain_type == 'LIQUID' and domain.use_mesh:
row = col.row()
row.enabled = not is_baking_any and not has_baked_mesh
row.prop(domain, "cache_mesh_format", text="Meshes")
diff --git a/release/scripts/startup/bl_ui/properties_view_layer.py b/release/scripts/startup/bl_ui/properties_view_layer.py
index 4dee7b73faf..83e797583ad 100644
--- a/release/scripts/startup/bl_ui/properties_view_layer.py
+++ b/release/scripts/startup/bl_ui/properties_view_layer.py
@@ -187,6 +187,33 @@ class VIEWLAYER_PT_layer_passes_cryptomatte(ViewLayerCryptomattePanel, Panel):
COMPAT_ENGINES = {'BLENDER_EEVEE'}
+class ViewLayerLightgroupsPanel(ViewLayerButtonsPanel, Panel):
+ bl_label = "Light Groups"
+
+ def draw(self, context):
+ layout = self.layout
+
+ layout.use_property_split = True
+ layout.use_property_decorate = False
+
+ view_layer = context.view_layer
+
+ row = layout.row()
+ col = row.column()
+ col.template_list("UI_UL_list", "lightgroups", view_layer,
+ "lightgroups", view_layer, "active_lightgroup_index", rows=2)
+
+ col = row.column()
+ sub = col.column(align=True)
+ sub.operator("scene.view_layer_add_lightgroup", icon='ADD', text="")
+ sub.operator("scene.view_layer_remove_lightgroup", icon='REMOVE', text="")
+
+
+class VIEWLAYER_PT_layer_passes_lightgroups(ViewLayerLightgroupsPanel):
+ bl_parent_id = "VIEWLAYER_PT_layer_passes"
+ COMPAT_ENGINES = {'CYCLES'}
+
+
classes = (
VIEWLAYER_PT_layer,
VIEWLAYER_PT_layer_passes,
@@ -195,6 +222,7 @@ classes = (
VIEWLAYER_PT_eevee_layer_passes_effects,
VIEWLAYER_PT_layer_passes_cryptomatte,
VIEWLAYER_PT_layer_passes_aov,
+ VIEWLAYER_PT_layer_passes_lightgroups,
VIEWLAYER_UL_aov,
)
diff --git a/release/scripts/startup/bl_ui/space_outliner.py b/release/scripts/startup/bl_ui/space_outliner.py
index bbe165b9286..eff8ad8e8b3 100644
--- a/release/scripts/startup/bl_ui/space_outliner.py
+++ b/release/scripts/startup/bl_ui/space_outliner.py
@@ -22,6 +22,8 @@ class OUTLINER_HT_header(Header):
if display_mode == 'DATA_API':
OUTLINER_MT_editor_menus.draw_collapsible(context, layout)
+ if display_mode == 'LIBRARY_OVERRIDES':
+ layout.prop(space, "lib_override_view_mode", text="")
layout.separator_spacer()
@@ -41,7 +43,11 @@ class OUTLINER_HT_header(Header):
text="",
icon='FILTER',
)
- if display_mode in {'LIBRARIES', 'LIBRARY_OVERRIDES', 'ORPHAN_DATA'}:
+ if display_mode == 'LIBRARY_OVERRIDES' and space.lib_override_view_mode == 'HIERARCHIES':
+ # Don't add ID type filter for library overrides hierarchies mode. Point of it is to see a hierarchy that is
+ # usually constructed out of different ID types.
+ pass
+ elif display_mode in {'LIBRARIES', 'LIBRARY_OVERRIDES', 'ORPHAN_DATA'}:
row.prop(space, "use_filter_id_type", text="", icon='FILTER')
sub = row.row(align=True)
sub.active = space.use_filter_id_type
@@ -351,7 +357,7 @@ class OUTLINER_PT_filter(Panel):
col = layout.column(align=True)
col.prop(space, "use_sort_alpha")
- if display_mode not in {'LIBRARY_OVERRIDES'}:
+ if display_mode != 'LIBRARY_OVERRIDES':
row = layout.row(align=True)
row.prop(space, "use_sync_select", text="Sync Selection")
@@ -364,13 +370,13 @@ class OUTLINER_PT_filter(Panel):
col.prop(space, "use_filter_complete", text="Exact Match")
col.prop(space, "use_filter_case_sensitive", text="Case Sensitive")
- if display_mode in {'LIBRARY_OVERRIDES'} and bpy.data.libraries:
+ if display_mode == 'LIBRARY_OVERRIDES' and space.lib_override_view_mode == 'PROPERTIES' and bpy.data.libraries:
col.separator()
row = col.row()
row.label(icon='LIBRARY_DATA_OVERRIDE')
row.prop(space, "use_filter_lib_override_system", text="System Overrides")
- if display_mode not in {'VIEW_LAYER'}:
+ if display_mode != 'VIEW_LAYER':
return
layout.separator()
diff --git a/release/scripts/startup/bl_ui/space_topbar.py b/release/scripts/startup/bl_ui/space_topbar.py
index 3355b30dd61..0a428b4ea3f 100644
--- a/release/scripts/startup/bl_ui/space_topbar.py
+++ b/release/scripts/startup/bl_ui/space_topbar.py
@@ -464,7 +464,6 @@ class TOPBAR_MT_file_export(Menu):
bl_owner_use_filter = False
def draw(self, _context):
- self.layout.operator("wm.obj_export", text="Wavefront OBJ (.obj)")
if bpy.app.build_options.collada:
self.layout.operator("wm.collada_export", text="Collada (.dae)")
if bpy.app.build_options.alembic:
@@ -480,6 +479,8 @@ class TOPBAR_MT_file_export(Menu):
if bpy.app.build_options.haru:
self.layout.operator("wm.gpencil_export_pdf", text="Grease Pencil as PDF")
+ self.layout.operator("wm.obj_export", text="Wavefront (.obj) (experimental)")
+
class TOPBAR_MT_file_external_data(Menu):
bl_label = "External Data"
diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py
index f40d96e30a0..a0336f7e7bf 100644
--- a/release/scripts/startup/bl_ui/space_view3d.py
+++ b/release/scripts/startup/bl_ui/space_view3d.py
@@ -514,6 +514,10 @@ class _draw_tool_settings_context_mode:
layout.prop(tool_settings.curves_sculpt, "interpolate_length")
layout.prop(tool_settings.curves_sculpt, "interpolate_shape")
+ if brush.curves_sculpt_tool == 'SNAKE_HOOK':
+ layout.prop(brush, "falloff_shape", expand=True)
+ layout.prop(brush, "curve_preset")
+
if brush.curves_sculpt_tool == 'TEST1':
layout.prop(tool_settings.curves_sculpt, "distance")
@@ -2636,6 +2640,8 @@ class VIEW3D_MT_object_apply(Menu):
def draw(self, _context):
layout = self.layout
+ # Need invoke for the popup confirming the multi-user data operation
+ layout.operator_context = 'INVOKE_DEFAULT'
props = layout.operator("object.transform_apply", text="Location", text_ctxt=i18n_contexts.default)
props.location, props.rotation, props.scale = True, False, False
@@ -2859,6 +2865,9 @@ class VIEW3D_MT_object_convert(Menu):
if bpy.app.build_options.potrace:
layout.operator("gpencil.trace_image", icon='OUTLINER_OB_GREASEPENCIL')
+ if ob and ob.type == 'CURVES':
+ layout.operator("curves.convert_to_particle_system", text="Particle System")
+
class VIEW3D_MT_make_links(Menu):
bl_label = "Link/Transfer Data"
@@ -5297,7 +5306,7 @@ class VIEW3D_MT_pivot_pie(Menu):
pie.prop_enum(context.scene.tool_settings, "transform_pivot_point", value='ACTIVE_ELEMENT')
if (obj is None) or (mode in {'OBJECT', 'POSE', 'WEIGHT_PAINT'}):
pie.prop(context.scene.tool_settings, "use_transform_pivot_point_align")
- if mode in {'EDIT_GPENCIL'}:
+ if mode == 'EDIT_GPENCIL':
pie.prop(context.scene.tool_settings.gpencil_sculpt, "use_scale_thickness")
diff --git a/release/scripts/templates_py/ui_list.py b/release/scripts/templates_py/ui_list.py
index f6b82356a78..9727a1b3678 100644
--- a/release/scripts/templates_py/ui_list.py
+++ b/release/scripts/templates_py/ui_list.py
@@ -18,7 +18,7 @@ class MESH_UL_mylist(bpy.types.UIList):
if self.layout_type in {'DEFAULT', 'COMPACT'}:
pass
# 'GRID' layout type should be as compact as possible (typically a single icon!).
- elif self.layout_type in {'GRID'}:
+ elif self.layout_type == 'GRID':
pass
# Called once to draw filtering/reordering options.
diff --git a/release/scripts/templates_py/ui_list_simple.py b/release/scripts/templates_py/ui_list_simple.py
index ac3f2b984de..c3efe16058a 100644
--- a/release/scripts/templates_py/ui_list_simple.py
+++ b/release/scripts/templates_py/ui_list_simple.py
@@ -29,7 +29,7 @@ class MATERIAL_UL_matslots_example(bpy.types.UIList):
else:
layout.label(text="", translate=False, icon_value=icon)
# 'GRID' layout type should be as compact as possible (typically a single icon!).
- elif self.layout_type in {'GRID'}:
+ elif self.layout_type == 'GRID':
layout.alignment = 'CENTER'
layout.label(text="", icon_value=icon)
diff --git a/source/blender/blenkernel/BKE_blender_version.h b/source/blender/blenkernel/BKE_blender_version.h
index 1639a564508..604c8cb7a06 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 6
+#define BLENDER_FILE_SUBVERSION 8
/* 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_cachefile.h b/source/blender/blenkernel/BKE_cachefile.h
index 425207398a0..41a0ad3f763 100644
--- a/source/blender/blenkernel/BKE_cachefile.h
+++ b/source/blender/blenkernel/BKE_cachefile.h
@@ -51,8 +51,7 @@ void BKE_cachefile_reader_free(struct CacheFile *cache_file, struct CacheReader
* load the data directly if they support it.
*/
bool BKE_cache_file_uses_render_procedural(const struct CacheFile *cache_file,
- struct Scene *scene,
- int dag_eval_mode);
+ struct Scene *scene);
/* Add a layer to the cache_file. Return NULL if the filename is already that of an existing layer
* or if the number of layers exceeds the maximum allowed layer count. */
diff --git a/source/blender/blenkernel/BKE_collection.h b/source/blender/blenkernel/BKE_collection.h
index 7f4360d2e9c..a3bbcc8687a 100644
--- a/source/blender/blenkernel/BKE_collection.h
+++ b/source/blender/blenkernel/BKE_collection.h
@@ -346,6 +346,20 @@ void BKE_scene_objects_iterator_begin(struct BLI_Iterator *iter, void *data_in);
void BKE_scene_objects_iterator_next(struct BLI_Iterator *iter);
void BKE_scene_objects_iterator_end(struct BLI_Iterator *iter);
+/** Iterate over objects in the scene based on a flag.
+ *
+ * \note The object->flag is tested against flag.
+ * */
+typedef struct SceneObjectsIteratorExData {
+ struct Scene *scene;
+ int flag;
+ void *iter_data;
+} SceneObjectsIteratorExData;
+
+void BKE_scene_objects_iterator_begin_ex(struct BLI_Iterator *iter, void *data_in);
+void BKE_scene_objects_iterator_next_ex(struct BLI_Iterator *iter);
+void BKE_scene_objects_iterator_end_ex(struct BLI_Iterator *iter);
+
/**
* Generate a new #GSet (or extend given `objects_gset` if not NULL) with all objects referenced by
* all collections of given `scene`.
diff --git a/source/blender/blenkernel/BKE_curves.hh b/source/blender/blenkernel/BKE_curves.hh
index 82f77d83bec..f097acc497f 100644
--- a/source/blender/blenkernel/BKE_curves.hh
+++ b/source/blender/blenkernel/BKE_curves.hh
@@ -77,6 +77,15 @@ class CurvesGeometryRuntime {
mutable std::mutex position_cache_mutex;
mutable bool position_cache_dirty = true;
+ /**
+ * Cache of lengths along each evaluated curve for for each evaluated point. If a curve is
+ * cyclic, it needs one more length value to correspond to the last segment, so in order to
+ * make slicing this array for a curve fast, an extra float is stored for every curve.
+ */
+ mutable Vector<float> evaluated_length_cache;
+ mutable std::mutex length_cache_mutex;
+ mutable bool length_cache_dirty = true;
+
/** Direction of the spline at each evaluated point. */
mutable Vector<float3> evaluated_tangents_cache;
mutable std::mutex tangent_cache_mutex;
@@ -264,9 +273,30 @@ class CurvesGeometry : public ::CurvesGeometry {
/** Makes sure the data described by #evaluated_offsets if necessary. */
void ensure_evaluated_offsets() const;
+ /**
+ * Retrieve offsets into a Bezier curve's evaluated points for each control point.
+ * Call #ensure_evaluated_offsets() first to ensure that the evaluated offsets cache is current.
+ */
+ Span<int> bezier_evaluated_offsets_for_curve(int curve_index) const;
+
Span<float3> evaluated_positions() const;
/**
+ * Return a cache of accumulated lengths along the curve. Each item is the length of the
+ * subsequent segment (the first value is the length of the first segment rather than 0).
+ * This calculation is rather trivial, and only depends on the evaluated positions, but
+ * the results are used often, and it is necessarily single threaded per curve, so it is cached.
+ *
+ * \param cyclic: This argument is redundant with the data stored for the curve,
+ * but is passed for performance reasons to avoid looking up the attribute.
+ */
+ Span<float> evaluated_lengths_for_curve(int curve_index, bool cyclic) const;
+ float evaluated_length_total_for_curve(int curve_index, bool cyclic) const;
+
+ /** Calculates the data described by #evaluated_lengths_for_curve if necessary. */
+ void ensure_evaluated_lengths() const;
+
+ /**
* Evaluate a generic data to the standard evaluated points of a specific curve,
* defined by the resolution attribute or other factors, depending on the curve type.
*
@@ -281,6 +311,9 @@ class CurvesGeometry : public ::CurvesGeometry {
*/
void ensure_nurbs_basis_cache() const;
+ /** Return the slice of #evaluated_length_cache that corresponds to this curve index. */
+ IndexRange lengths_range_for_curve(int curve_index, bool cyclic) const;
+
/* --------------------------------------------------------------------
* Operations.
*/
@@ -305,6 +338,8 @@ class CurvesGeometry : public ::CurvesGeometry {
void translate(const float3 &translation);
void transform(const float4x4 &matrix);
+ void calculate_bezier_auto_handles();
+
void update_customdata_pointers();
void remove_curves(IndexMask curves_to_delete);
@@ -325,13 +360,12 @@ class CurvesGeometry : public ::CurvesGeometry {
namespace curves {
/**
- * The number of segments between control points, accounting for the last segment of cyclic curves,
- * and the fact that curves with two points cannot be cyclic. The logic is simple, but this
- * function should be used to make intentions clearer.
+ * The number of segments between control points, accounting for the last segment of cyclic
+ * curves. The logic is simple, but this function should be used to make intentions clearer.
*/
inline int curve_segment_size(const int points_num, const bool cyclic)
{
- return (cyclic && points_num > 2) ? points_num : points_num - 1;
+ return cyclic ? points_num : points_num - 1;
}
namespace bezier {
@@ -365,9 +399,37 @@ void calculate_evaluated_offsets(Span<int8_t> handle_types_left,
MutableSpan<int> evaluated_offsets);
/**
+ * Recalculate all auto (#BEZIER_HANDLE_AUTO) and vector (#BEZIER_HANDLE_VECTOR) handles with
+ * positions automatically derived from the neighboring control points, and update aligned
+ * (#BEZIER_HANDLE_ALIGN) handles to line up with neighboring non-aligned handles. The choices
+ * made here are relatively arbitrary, but having standardized behavior is essential.
+ */
+void calculate_auto_handles(bool cyclic,
+ Span<int8_t> types_left,
+ Span<int8_t> types_right,
+ Span<float3> positions,
+ MutableSpan<float3> positions_left,
+ MutableSpan<float3> positions_right);
+
+/**
+ * Change the handles of a single control point, aligning any aligned (#BEZIER_HANDLE_ALIGN)
+ * handles on the other side of the control point.
+ *
+ * \note This ignores the inputs if the handle types are automatically calculated,
+ * so the types should be updated before-hand to be editable.
+ */
+void set_handle_position(const float3 &position,
+ HandleType type,
+ HandleType type_other,
+ const float3 &new_handle,
+ float3 &handle,
+ float3 &handle_other);
+
+/**
* Evaluate a cubic Bezier segment, using the "forward differencing" method.
- * A generic Bezier curve is made up by four points, but in many cases the first and last points
- * are referred to as the control points, and the middle points are the corresponding handles.
+ * A generic Bezier curve is made up by four points, but in many cases the first and last
+ * points are referred to as the control points, and the middle points are the corresponding
+ * handles.
*/
void evaluate_segment(const float3 &point_0,
const float3 &point_1,
diff --git a/source/blender/blenkernel/BKE_geometry_fields.hh b/source/blender/blenkernel/BKE_geometry_fields.hh
new file mode 100644
index 00000000000..36b382feb5f
--- /dev/null
+++ b/source/blender/blenkernel/BKE_geometry_fields.hh
@@ -0,0 +1,165 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#pragma once
+
+/** \file
+ * \ingroup bke
+ *
+ * Common field utilities and field definitions for geometry components.
+ */
+
+#include "BKE_geometry_set.hh"
+
+#include "FN_field.hh"
+
+namespace blender::bke {
+
+class GeometryComponentFieldContext : public fn::FieldContext {
+ private:
+ const GeometryComponent &component_;
+ const AttributeDomain domain_;
+
+ public:
+ GeometryComponentFieldContext(const GeometryComponent &component, const AttributeDomain domain)
+ : component_(component), domain_(domain)
+ {
+ }
+
+ const GeometryComponent &geometry_component() const
+ {
+ return component_;
+ }
+
+ AttributeDomain domain() const
+ {
+ return domain_;
+ }
+};
+
+class GeometryFieldInput : public fn::FieldInput {
+ public:
+ using fn::FieldInput::FieldInput;
+
+ GVArray get_varray_for_context(const fn::FieldContext &context,
+ IndexMask mask,
+ ResourceScope &scope) const override;
+
+ virtual GVArray get_varray_for_context(const GeometryComponent &component,
+ AttributeDomain domain,
+ IndexMask mask) const = 0;
+};
+
+class AttributeFieldInput : public GeometryFieldInput {
+ private:
+ std::string name_;
+
+ public:
+ AttributeFieldInput(std::string name, const CPPType &type)
+ : GeometryFieldInput(type, name), name_(std::move(name))
+ {
+ category_ = Category::NamedAttribute;
+ }
+
+ template<typename T> static fn::Field<T> Create(std::string name)
+ {
+ const CPPType &type = CPPType::get<T>();
+ auto field_input = std::make_shared<AttributeFieldInput>(std::move(name), type);
+ return fn::Field<T>{field_input};
+ }
+
+ StringRefNull attribute_name() const
+ {
+ return name_;
+ }
+
+ GVArray get_varray_for_context(const GeometryComponent &component,
+ AttributeDomain domain,
+ IndexMask mask) const override;
+
+ std::string socket_inspection_name() const override;
+
+ uint64_t hash() const override;
+ bool is_equal_to(const fn::FieldNode &other) const override;
+};
+
+class IDAttributeFieldInput : public GeometryFieldInput {
+ public:
+ IDAttributeFieldInput() : GeometryFieldInput(CPPType::get<int>())
+ {
+ category_ = Category::Generated;
+ }
+
+ GVArray get_varray_for_context(const GeometryComponent &component,
+ AttributeDomain domain,
+ IndexMask mask) const override;
+
+ std::string socket_inspection_name() const override;
+
+ uint64_t hash() const override;
+ bool is_equal_to(const fn::FieldNode &other) const override;
+};
+
+VArray<float3> curve_normals_varray(const CurveComponent &component, const AttributeDomain domain);
+
+VArray<float3> mesh_normals_varray(const MeshComponent &mesh_component,
+ const Mesh &mesh,
+ const IndexMask mask,
+ const AttributeDomain domain);
+
+class NormalFieldInput : public GeometryFieldInput {
+ public:
+ NormalFieldInput() : GeometryFieldInput(CPPType::get<float3>())
+ {
+ category_ = Category::Generated;
+ }
+
+ GVArray get_varray_for_context(const GeometryComponent &component,
+ const AttributeDomain domain,
+ IndexMask mask) const override;
+
+ std::string socket_inspection_name() const override;
+
+ uint64_t hash() const override;
+ bool is_equal_to(const fn::FieldNode &other) const override;
+};
+
+class AnonymousAttributeFieldInput : public GeometryFieldInput {
+ private:
+ /**
+ * A strong reference is required to make sure that the referenced attribute is not removed
+ * automatically.
+ */
+ StrongAnonymousAttributeID anonymous_id_;
+ std::string producer_name_;
+
+ public:
+ AnonymousAttributeFieldInput(StrongAnonymousAttributeID anonymous_id,
+ const CPPType &type,
+ std::string producer_name)
+ : GeometryFieldInput(type, anonymous_id.debug_name()),
+ anonymous_id_(std::move(anonymous_id)),
+ producer_name_(producer_name)
+ {
+ category_ = Category::AnonymousAttribute;
+ }
+
+ template<typename T>
+ static fn::Field<T> Create(StrongAnonymousAttributeID anonymous_id, std::string producer_name)
+ {
+ const CPPType &type = CPPType::get<T>();
+ auto field_input = std::make_shared<AnonymousAttributeFieldInput>(
+ std::move(anonymous_id), type, std::move(producer_name));
+ return fn::Field<T>{field_input};
+ }
+
+ GVArray get_varray_for_context(const GeometryComponent &component,
+ AttributeDomain domain,
+ IndexMask mask) const override;
+
+ std::string socket_inspection_name() const override;
+
+ uint64_t hash() const override;
+ bool is_equal_to(const fn::FieldNode &other) const override;
+};
+
+} // namespace blender::bke
diff --git a/source/blender/blenkernel/BKE_geometry_set.hh b/source/blender/blenkernel/BKE_geometry_set.hh
index bd392057436..559007d1aee 100644
--- a/source/blender/blenkernel/BKE_geometry_set.hh
+++ b/source/blender/blenkernel/BKE_geometry_set.hh
@@ -22,8 +22,6 @@
#include "BKE_attribute_access.hh"
#include "BKE_geometry_set.h"
-#include "FN_field.hh"
-
struct Curves;
struct Collection;
struct Curve;
@@ -1019,155 +1017,3 @@ class VolumeComponent : public GeometryComponent {
static constexpr inline GeometryComponentType static_type = GEO_COMPONENT_TYPE_VOLUME;
};
-
-namespace blender::bke {
-
-class GeometryComponentFieldContext : public fn::FieldContext {
- private:
- const GeometryComponent &component_;
- const AttributeDomain domain_;
-
- public:
- GeometryComponentFieldContext(const GeometryComponent &component, const AttributeDomain domain)
- : component_(component), domain_(domain)
- {
- }
-
- const GeometryComponent &geometry_component() const
- {
- return component_;
- }
-
- AttributeDomain domain() const
- {
- return domain_;
- }
-};
-
-class GeometryFieldInput : public fn::FieldInput {
- public:
- using fn::FieldInput::FieldInput;
-
- GVArray get_varray_for_context(const fn::FieldContext &context,
- IndexMask mask,
- ResourceScope &scope) const override;
-
- virtual GVArray get_varray_for_context(const GeometryComponent &component,
- AttributeDomain domain,
- IndexMask mask) const = 0;
-};
-
-class AttributeFieldInput : public GeometryFieldInput {
- private:
- std::string name_;
-
- public:
- AttributeFieldInput(std::string name, const CPPType &type)
- : GeometryFieldInput(type, name), name_(std::move(name))
- {
- category_ = Category::NamedAttribute;
- }
-
- template<typename T> static fn::Field<T> Create(std::string name)
- {
- const CPPType &type = CPPType::get<T>();
- auto field_input = std::make_shared<AttributeFieldInput>(std::move(name), type);
- return fn::Field<T>{field_input};
- }
-
- StringRefNull attribute_name() const
- {
- return name_;
- }
-
- GVArray get_varray_for_context(const GeometryComponent &component,
- AttributeDomain domain,
- IndexMask mask) const override;
-
- std::string socket_inspection_name() const override;
-
- uint64_t hash() const override;
- bool is_equal_to(const fn::FieldNode &other) const override;
-};
-
-class IDAttributeFieldInput : public GeometryFieldInput {
- public:
- IDAttributeFieldInput() : GeometryFieldInput(CPPType::get<int>())
- {
- category_ = Category::Generated;
- }
-
- GVArray get_varray_for_context(const GeometryComponent &component,
- AttributeDomain domain,
- IndexMask mask) const override;
-
- std::string socket_inspection_name() const override;
-
- uint64_t hash() const override;
- bool is_equal_to(const fn::FieldNode &other) const override;
-};
-
-VArray<float3> curve_normals_varray(const CurveComponent &component, const AttributeDomain domain);
-
-VArray<float3> mesh_normals_varray(const MeshComponent &mesh_component,
- const Mesh &mesh,
- const IndexMask mask,
- const AttributeDomain domain);
-
-class NormalFieldInput : public GeometryFieldInput {
- public:
- NormalFieldInput() : GeometryFieldInput(CPPType::get<float3>())
- {
- category_ = Category::Generated;
- }
-
- GVArray get_varray_for_context(const GeometryComponent &component,
- const AttributeDomain domain,
- IndexMask mask) const override;
-
- std::string socket_inspection_name() const override;
-
- uint64_t hash() const override;
- bool is_equal_to(const fn::FieldNode &other) const override;
-};
-
-class AnonymousAttributeFieldInput : public GeometryFieldInput {
- private:
- /**
- * A strong reference is required to make sure that the referenced attribute is not removed
- * automatically.
- */
- StrongAnonymousAttributeID anonymous_id_;
- std::string producer_name_;
-
- public:
- AnonymousAttributeFieldInput(StrongAnonymousAttributeID anonymous_id,
- const CPPType &type,
- std::string producer_name)
- : GeometryFieldInput(type, anonymous_id.debug_name()),
- anonymous_id_(std::move(anonymous_id)),
- producer_name_(producer_name)
- {
- category_ = Category::AnonymousAttribute;
- }
-
- template<typename T>
- static fn::Field<T> Create(StrongAnonymousAttributeID anonymous_id, std::string producer_name)
- {
- const CPPType &type = CPPType::get<T>();
- auto field_input = std::make_shared<AnonymousAttributeFieldInput>(
- std::move(anonymous_id), type, std::move(producer_name));
- return fn::Field<T>{field_input};
- }
-
- GVArray get_varray_for_context(const GeometryComponent &component,
- AttributeDomain domain,
- IndexMask mask) const override;
-
- std::string socket_inspection_name() const override;
-
- uint64_t hash() const override;
- bool is_equal_to(const fn::FieldNode &other) const override;
-};
-
-} // namespace blender::bke
diff --git a/source/blender/blenkernel/BKE_layer.h b/source/blender/blenkernel/BKE_layer.h
index 77a3223c064..4a3917dafee 100644
--- a/source/blender/blenkernel/BKE_layer.h
+++ b/source/blender/blenkernel/BKE_layer.h
@@ -8,6 +8,7 @@
#include "BKE_collection.h"
+#include "DNA_layer_types.h"
#include "DNA_listBase.h"
#ifdef __cplusplus
@@ -436,15 +437,26 @@ void BKE_view_layer_visible_bases_iterator_end(BLI_Iterator *iter);
IteratorBeginCb func_begin; \
IteratorCb func_next, func_end; \
void *data_in; \
- struct ObjectsVisibleIteratorData data_ = {NULL}; \
- data_.view_layer = _view_layer; \
- data_.v3d = _v3d; \
+\
+ struct ObjectsVisibleIteratorData data_select_ = {NULL}; \
+ data_select_.view_layer = _view_layer; \
+ data_select_.v3d = _v3d; \
+\
+ struct SceneObjectsIteratorExData data_flag_ = {NULL}; \
+ data_flag_.scene = scene; \
+ data_flag_.flag = flag; \
\
if (flag == SELECT) { \
func_begin = &BKE_view_layer_selected_objects_iterator_begin; \
func_next = &BKE_view_layer_selected_objects_iterator_next; \
func_end = &BKE_view_layer_selected_objects_iterator_end; \
- data_in = &data_; \
+ data_in = &data_select_; \
+ } \
+ else if (flag != 0) { \
+ func_begin = BKE_scene_objects_iterator_begin_ex; \
+ func_next = BKE_scene_objects_iterator_next_ex; \
+ func_end = BKE_scene_objects_iterator_end_ex; \
+ data_in = &data_flag_; \
} \
else { \
func_begin = BKE_scene_objects_iterator_begin; \
@@ -570,6 +582,21 @@ bool BKE_view_layer_has_valid_aov(struct ViewLayer *view_layer);
struct ViewLayer *BKE_view_layer_find_with_aov(struct Scene *scene,
struct ViewLayerAOV *view_layer_aov);
+struct ViewLayerLightgroup *BKE_view_layer_add_lightgroup(struct ViewLayer *view_layer);
+void BKE_view_layer_remove_lightgroup(struct ViewLayer *view_layer,
+ struct ViewLayerLightgroup *lightgroup);
+void BKE_view_layer_set_active_lightgroup(struct ViewLayer *view_layer,
+ struct ViewLayerLightgroup *lightgroup);
+struct ViewLayer *BKE_view_layer_find_with_lightgroup(
+ struct Scene *scene, struct ViewLayerLightgroup *view_layer_lightgroup);
+void BKE_view_layer_rename_lightgroup(ViewLayer *view_layer,
+ ViewLayerLightgroup *lightgroup,
+ const char *name);
+
+void BKE_lightgroup_membership_get(struct LightgroupMembership *lgm, char *value);
+int BKE_lightgroup_membership_length(struct LightgroupMembership *lgm);
+void BKE_lightgroup_membership_set(struct LightgroupMembership **lgm, const char *value);
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/blenkernel/BKE_lib_id.h b/source/blender/blenkernel/BKE_lib_id.h
index 040be8d1280..504ab47c1c5 100644
--- a/source/blender/blenkernel/BKE_lib_id.h
+++ b/source/blender/blenkernel/BKE_lib_id.h
@@ -515,7 +515,7 @@ void BKE_main_id_flag_listbase(struct ListBase *lb, int flag, bool value);
void BKE_main_id_flag_all(struct Main *bmain, int flag, bool value);
/**
- * Next to indirect usage in `readfile.c/writefile.c` also in `editobject.c`, `scene.c`.
+ * Next to indirect usage in `readfile.c/writefile.c` also in `editobject.c`, `scene.cc`.
*/
void BKE_main_id_newptr_and_tag_clear(struct Main *bmain);
@@ -594,6 +594,17 @@ bool BKE_id_is_in_global_main(struct ID *id);
bool BKE_id_can_be_asset(const struct ID *id);
+/** Check if that ID can be considered as editable from a high-level (editor) perspective.
+ *
+ * NOTE: This used to be done with a check on whether ID was linked or not, but now with system
+ * overrides this is not enough anymore.
+ *
+ * NOTE: Execution of this function can be somewhat expensive currently. If this becomes an issue,
+ * we should either cache that status info also in virtual override IDs, or address the
+ * long-standing TODO of getting an efficient 'owner_id' access for all embedded ID types.
+ */
+bool BKE_id_is_editable(struct Main *bmain, struct ID *id);
+
/**
* Returns ordered list of data-blocks for display in the UI.
* Result is list of #LinkData of IDs that must be freed.
diff --git a/source/blender/blenkernel/BKE_lib_override.h b/source/blender/blenkernel/BKE_lib_override.h
index 98301ca7a70..dfb2b900b10 100644
--- a/source/blender/blenkernel/BKE_lib_override.h
+++ b/source/blender/blenkernel/BKE_lib_override.h
@@ -65,6 +65,19 @@ void BKE_lib_override_library_free(struct IDOverrideLibrary **override, bool do_
bool BKE_lib_override_library_is_user_edited(struct ID *id);
/**
+ * Check if given ID is a system override.
+ */
+bool BKE_lib_override_library_is_system_defined(struct Main *bmain, struct ID *id);
+
+/**
+ * Check if given ID is a leaf in its liboverride hierarchy (i.e. if it does not use any other
+ * override ID).
+ *
+ * NOTE: Embedded IDs of override IDs are not considered as leaves.
+ */
+bool BKE_lib_override_library_is_hierarchy_leaf(struct Main *bmain, struct ID *id);
+
+/**
* Create an overridden local copy of linked reference.
*
* \note This function is very basic, low-level. It does not consider any hierarchical dependency,
@@ -369,12 +382,22 @@ bool BKE_lib_override_library_main_operations_create(struct Main *bmain, bool fo
/**
* Reset all overrides in given \a id_root, while preserving ID relations.
+ *
+ * \param do_reset_system_override: If \a true, reset the given ID as a system override one (i.e.
+ * non-editable).
*/
-void BKE_lib_override_library_id_reset(struct Main *bmain, struct ID *id_root);
+void BKE_lib_override_library_id_reset(struct Main *bmain,
+ struct ID *id_root,
+ bool do_reset_system_override);
/**
* Reset all overrides in given \a id_root and its dependencies, while preserving ID relations.
+ *
+ * \param do_reset_system_override: If \a true, reset the given ID and all of its descendants in
+ * the override hierarchy as system override ones (i.e. non-editable).
*/
-void BKE_lib_override_library_id_hierarchy_reset(struct Main *bmain, struct ID *id_root);
+void BKE_lib_override_library_id_hierarchy_reset(struct Main *bmain,
+ struct ID *id_root,
+ bool do_reset_system_override);
/**
* Set or clear given tag in all operations in that override property data.
diff --git a/source/blender/blenkernel/BKE_mesh.h b/source/blender/blenkernel/BKE_mesh.h
index 0ba9713b96d..1ad20c52a4b 100644
--- a/source/blender/blenkernel/BKE_mesh.h
+++ b/source/blender/blenkernel/BKE_mesh.h
@@ -571,7 +571,7 @@ typedef struct MLoopNorSpaceArray {
struct LinkNode
*loops_pool; /* Allocated once, avoids to call BLI_linklist_prepend_arena() for each loop! */
char data_type; /* Whether we store loop indices, or pointers to BMLoop. */
- int num_spaces; /* Number of clnors spaces defined in this array. */
+ int spaces_num; /* Number of clnors spaces defined in this array. */
struct MemArena *mem;
} MLoopNorSpaceArray;
/**
diff --git a/source/blender/blenkernel/BKE_modifier.h b/source/blender/blenkernel/BKE_modifier.h
index acdca23b21c..41a02545591 100644
--- a/source/blender/blenkernel/BKE_modifier.h
+++ b/source/blender/blenkernel/BKE_modifier.h
@@ -301,10 +301,8 @@ typedef struct ModifierTypeInfo {
* changes.
*
* This function is optional (assumes false if not present).
- *
- * The dag_eval_mode should be of type eEvaluationMode.
*/
- bool (*dependsOnTime)(struct Scene *scene, struct ModifierData *md, int dag_eval_mode);
+ bool (*dependsOnTime)(struct Scene *scene, struct ModifierData *md);
/**
* True when a deform modifier uses normals, the requiredDataMask
@@ -421,7 +419,7 @@ void BKE_modifier_copydata(const struct ModifierData *md, struct ModifierData *t
void BKE_modifier_copydata_ex(const struct ModifierData *md,
struct ModifierData *target,
int flag);
-bool BKE_modifier_depends_ontime(struct Scene *scene, struct ModifierData *md, int dag_eval_mode);
+bool BKE_modifier_depends_ontime(struct Scene *scene, struct ModifierData *md);
bool BKE_modifier_supports_mapping(struct ModifierData *md);
bool BKE_modifier_supports_cage(struct Scene *scene, struct ModifierData *md);
bool BKE_modifier_couldbe_cage(struct Scene *scene, struct ModifierData *md);
diff --git a/source/blender/blenkernel/BKE_object.h b/source/blender/blenkernel/BKE_object.h
index 17d90e64459..a90b9b12030 100644
--- a/source/blender/blenkernel/BKE_object.h
+++ b/source/blender/blenkernel/BKE_object.h
@@ -163,9 +163,12 @@ int BKE_object_visibility(const struct Object *ob, int dag_eval_mode);
/**
* More general add: creates minimum required data, but without vertices etc.
+ *
+ * \param bmain: The main to add the object to. May be null for #LIB_ID_CREATE_NO_MAIN behavior.
*/
-struct Object *BKE_object_add_only_object(struct Main *bmain, int type, const char *name)
- ATTR_NONNULL(1) ATTR_RETURNS_NONNULL;
+struct Object *BKE_object_add_only_object(struct Main *bmain,
+ int type,
+ const char *name) ATTR_RETURNS_NONNULL;
/**
* General add: to scene, with layer from area and default name.
*
@@ -334,7 +337,7 @@ void BKE_boundbox_minmax(const struct BoundBox *bb,
float r_min[3],
float r_max[3]);
-struct BoundBox *BKE_object_boundbox_get(struct Object *ob);
+const struct BoundBox *BKE_object_boundbox_get(struct Object *ob);
void BKE_object_dimensions_get(struct Object *ob, float r_vec[3]);
/**
* The original scale and object matrix can be passed in so any difference
@@ -352,10 +355,7 @@ void BKE_object_dimensions_set_ex(struct Object *ob,
void BKE_object_dimensions_set(struct Object *ob, const float value[3], int axis_mask);
void BKE_object_empty_draw_type_set(struct Object *ob, int value);
-/**
- * Use this to temporally disable/enable bound-box.
- */
-void BKE_object_boundbox_flag(struct Object *ob, int flag, bool set);
+
void BKE_object_boundbox_calc_from_mesh(struct Object *ob, const struct Mesh *me_eval);
bool BKE_object_boundbox_calc_from_evaluated_geometry(struct Object *ob);
void BKE_object_minmax(struct Object *ob, float r_min[3], float r_max[3], bool use_hidden);
@@ -618,10 +618,7 @@ void BKE_object_groups_clear(struct Main *bmain, struct Scene *scene, struct Obj
*/
struct KDTree_3d *BKE_object_as_kdtree(struct Object *ob, int *r_tot);
-bool BKE_object_modifier_use_time(struct Scene *scene,
- struct Object *ob,
- struct ModifierData *md,
- int dag_eval_mode);
+bool BKE_object_modifier_use_time(struct Scene *scene, struct Object *ob, struct ModifierData *md);
/**
* \note this function should eventually be replaced by depsgraph functionality.
diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt
index 8f7ef035557..3be1c4b1278 100644
--- a/source/blender/blenkernel/CMakeLists.txt
+++ b/source/blender/blenkernel/CMakeLists.txt
@@ -247,7 +247,7 @@ set(SRC
intern/preferences.c
intern/report.c
intern/rigidbody.c
- intern/scene.c
+ intern/scene.cc
intern/screen.c
intern/shader_fx.c
intern/shrinkwrap.c
@@ -370,6 +370,7 @@ set(SRC
BKE_fcurve_driver.h
BKE_fluid.h
BKE_freestyle.h
+ BKE_geometry_fields.hh
BKE_geometry_set.h
BKE_geometry_set.hh
BKE_geometry_set_instances.hh
@@ -599,10 +600,6 @@ if(WITH_IMAGE_CINEON)
add_definitions(-DWITH_CINEON)
endif()
-if(WITH_IMAGE_FRAMESERVER)
- add_definitions(-DWITH_FRAMESERVER)
-endif()
-
if(WITH_IMAGE_HDR)
add_definitions(-DWITH_HDR)
endif()
diff --git a/source/blender/blenkernel/intern/attribute_access.cc b/source/blender/blenkernel/intern/attribute_access.cc
index 8fbab8dde25..d0420b4170a 100644
--- a/source/blender/blenkernel/intern/attribute_access.cc
+++ b/source/blender/blenkernel/intern/attribute_access.cc
@@ -6,6 +6,7 @@
#include "BKE_attribute_math.hh"
#include "BKE_customdata.h"
#include "BKE_deform.h"
+#include "BKE_geometry_fields.hh"
#include "BKE_geometry_set.hh"
#include "BKE_mesh.h"
#include "BKE_pointcloud.h"
diff --git a/source/blender/blenkernel/intern/blendfile.c b/source/blender/blenkernel/intern/blendfile.c
index c32081b5d1c..70c3dc2de39 100644
--- a/source/blender/blenkernel/intern/blendfile.c
+++ b/source/blender/blenkernel/intern/blendfile.c
@@ -352,7 +352,7 @@ static void setup_app_data(bContext *C,
do_versions_ipos_to_animato(bmain);
}
- /* NOTE: readfile's `do_version` does not allow to create new IDs, and only operates on a single
+ /* NOTE: readfile's `do_versions` does not allow to create new IDs, and only operates on a single
* library at a time. This code needs to operate on the whole Main at once. */
/* NOTE: Check bmain version (i.e. current blend file version), AND the versions of all the
* linked libraries. */
diff --git a/source/blender/blenkernel/intern/blendfile_link_append.c b/source/blender/blenkernel/intern/blendfile_link_append.c
index 294fe57c923..be2abdbfb69 100644
--- a/source/blender/blenkernel/intern/blendfile_link_append.c
+++ b/source/blender/blenkernel/intern/blendfile_link_append.c
@@ -999,7 +999,7 @@ static void blendfile_link_append_proxies_convert(Main *bmain, ReportList *repor
RPT_WARNING,
"Proxies have been removed from Blender (%d proxies were automatically converted "
"to library overrides, %d proxies could not be converted and were cleared). "
- "Please consider re-saving any library .blend file with the newest Blender version.",
+ "Please consider re-saving any library .blend file with the newest Blender version",
bf_reports.count.proxies_to_lib_overrides_success,
bf_reports.count.proxies_to_lib_overrides_failures);
}
diff --git a/source/blender/blenkernel/intern/cachefile.c b/source/blender/blenkernel/intern/cachefile.c
index 16fc05266e2..338c74d550c 100644
--- a/source/blender/blenkernel/intern/cachefile.c
+++ b/source/blender/blenkernel/intern/cachefile.c
@@ -417,9 +417,7 @@ float BKE_cachefile_time_offset(const CacheFile *cache_file, const float time, c
return cache_file->is_sequence ? frame : frame / fps - time_offset;
}
-bool BKE_cache_file_uses_render_procedural(const CacheFile *cache_file,
- Scene *scene,
- const int dag_eval_mode)
+bool BKE_cache_file_uses_render_procedural(const CacheFile *cache_file, Scene *scene)
{
RenderEngineType *render_engine_type = RE_engines_find(scene->r.engine);
@@ -428,9 +426,7 @@ bool BKE_cache_file_uses_render_procedural(const CacheFile *cache_file,
return false;
}
- /* The render time procedural is only enabled during viewport rendering. */
- const bool is_final_render = (eEvaluationMode)dag_eval_mode == DAG_EVAL_RENDER;
- return cache_file->use_render_procedural && !is_final_render;
+ return cache_file->use_render_procedural;
}
CacheFileLayer *BKE_cachefile_add_layer(CacheFile *cache_file, const char filename[1024])
diff --git a/source/blender/blenkernel/intern/collection.c b/source/blender/blenkernel/intern/collection.c
index bdaea487cfb..c215321bc30 100644
--- a/source/blender/blenkernel/intern/collection.c
+++ b/source/blender/blenkernel/intern/collection.c
@@ -1929,6 +1929,48 @@ void BKE_scene_objects_iterator_begin(BLI_Iterator *iter, void *data_in)
scene_objects_iterator_begin(iter, scene, NULL);
}
+void BKE_scene_objects_iterator_begin_ex(BLI_Iterator *iter, void *data_in)
+{
+ SceneObjectsIteratorExData *data = data_in;
+
+ BKE_scene_objects_iterator_begin(iter, data->scene);
+
+ /* Pack the data. */
+ data->iter_data = iter->data;
+ iter->data = data_in;
+}
+
+void BKE_scene_objects_iterator_next_ex(struct BLI_Iterator *iter)
+{
+ /* Unpack the data. */
+ SceneObjectsIteratorExData *data = iter->data;
+ iter->data = data->iter_data;
+
+ BKE_scene_objects_iterator_next(iter);
+
+ Object *ob = iter->current;
+ if (ob && (ob->flag & data->flag) == 0) {
+ iter->skip = true;
+ }
+
+ /* Pack the data. */
+ data->iter_data = iter->data;
+ iter->data = data;
+}
+
+void BKE_scene_objects_iterator_end_ex(struct BLI_Iterator *iter)
+{
+ /* Unpack the data. */
+ SceneObjectsIteratorExData *data = iter->data;
+ iter->data = data->iter_data;
+
+ BKE_scene_objects_iterator_end(iter);
+
+ /* Pack the data. */
+ data->iter_data = iter->data;
+ iter->data = data;
+}
+
/**
* Ensures we only get each object once, even when included in several collections.
*/
diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c
index 7a97139748f..fc3f84778f8 100644
--- a/source/blender/blenkernel/intern/constraint.c
+++ b/source/blender/blenkernel/intern/constraint.c
@@ -5412,7 +5412,7 @@ static void transformcache_evaluate(bConstraint *con, bConstraintOb *cob, ListBa
}
/* Do not process data if using a render time procedural. */
- if (BKE_cache_file_uses_render_procedural(cache_file, scene, DEG_get_mode(cob->depsgraph))) {
+ if (BKE_cache_file_uses_render_procedural(cache_file, scene)) {
return;
}
diff --git a/source/blender/blenkernel/intern/crazyspace.c b/source/blender/blenkernel/intern/crazyspace.c
index 9d13bf3ac11..96389c44839 100644
--- a/source/blender/blenkernel/intern/crazyspace.c
+++ b/source/blender/blenkernel/intern/crazyspace.c
@@ -236,7 +236,7 @@ int BKE_crazyspace_get_first_deform_matrices_editbmesh(struct Depsgraph *depsgra
ModifierData *md;
Mesh *me_input = ob->data;
Mesh *me = NULL;
- int i, a, numleft = 0, numVerts = 0;
+ int i, a, modifiers_left_num = 0, verts_num = 0;
int cageIndex = BKE_modifiers_get_cage_index(scene, ob, NULL, 1);
float(*defmats)[3][3] = NULL, (*deformedVerts)[3] = NULL;
VirtualModifierData virtualModifierData;
@@ -266,14 +266,14 @@ int BKE_crazyspace_get_first_deform_matrices_editbmesh(struct Depsgraph *depsgra
BLI_linklist_free((LinkNode *)datamasks, NULL);
me = BKE_mesh_wrapper_from_editmesh_with_coords(em, &cd_mask_extra, NULL, me_input);
- deformedVerts = editbmesh_vert_coords_alloc(em, &numVerts);
- defmats = MEM_mallocN(sizeof(*defmats) * numVerts, "defmats");
+ deformedVerts = editbmesh_vert_coords_alloc(em, &verts_num);
+ defmats = MEM_mallocN(sizeof(*defmats) * verts_num, "defmats");
- for (a = 0; a < numVerts; a++) {
+ for (a = 0; a < verts_num; a++) {
unit_m3(defmats[a]);
}
}
- mti->deformMatricesEM(md, &mectx, em, me, deformedVerts, defmats, numVerts);
+ mti->deformMatricesEM(md, &mectx, em, me, deformedVerts, defmats, verts_num);
}
else {
break;
@@ -283,7 +283,7 @@ int BKE_crazyspace_get_first_deform_matrices_editbmesh(struct Depsgraph *depsgra
for (; md && i <= cageIndex; md = md->next, i++) {
if (editbmesh_modifier_is_enabled(scene, ob, md, me != NULL) &&
BKE_modifier_is_correctable_deformed(md)) {
- numleft++;
+ modifiers_left_num++;
}
}
@@ -294,7 +294,7 @@ int BKE_crazyspace_get_first_deform_matrices_editbmesh(struct Depsgraph *depsgra
*deformmats = defmats;
*deformcos = deformedVerts;
- return numleft;
+ return modifiers_left_num;
}
/**
@@ -319,13 +319,13 @@ static void crazyspace_init_verts_and_matrices(const Mesh *mesh,
float (**deformmats)[3][3],
float (**deformcos)[3])
{
- int num_verts;
- *deformcos = BKE_mesh_vert_coords_alloc(mesh, &num_verts);
- *deformmats = MEM_callocN(sizeof(**deformmats) * num_verts, "defmats");
- for (int a = 0; a < num_verts; a++) {
+ int verts_num;
+ *deformcos = BKE_mesh_vert_coords_alloc(mesh, &verts_num);
+ *deformmats = MEM_callocN(sizeof(**deformmats) * verts_num, "defmats");
+ for (int a = 0; a < verts_num; a++) {
unit_m3((*deformmats)[a]);
}
- BLI_assert(num_verts == mesh->totvert);
+ BLI_assert(verts_num == mesh->totvert);
}
static bool crazyspace_modifier_supports_deform_matrices(ModifierData *md)
@@ -352,7 +352,7 @@ int BKE_sculpt_get_first_deform_matrices(struct Depsgraph *depsgraph,
ModifierData *md;
Mesh *me_eval = NULL;
float(*defmats)[3][3] = NULL, (*deformedVerts)[3] = NULL;
- int numleft = 0;
+ int modifiers_left_num = 0;
VirtualModifierData virtualModifierData;
Object object_eval;
crazyspace_init_object_for_eval(depsgraph, object, &object_eval);
@@ -364,7 +364,7 @@ int BKE_sculpt_get_first_deform_matrices(struct Depsgraph *depsgraph,
if (is_sculpt_mode && has_multires) {
*deformmats = NULL;
*deformcos = NULL;
- return numleft;
+ return modifiers_left_num;
}
md = BKE_modifiers_get_virtual_modifierlist(&object_eval, &virtualModifierData);
@@ -401,7 +401,7 @@ int BKE_sculpt_get_first_deform_matrices(struct Depsgraph *depsgraph,
}
if (crazyspace_modifier_supports_deform(md)) {
- numleft++;
+ modifiers_left_num++;
}
}
@@ -412,7 +412,7 @@ int BKE_sculpt_get_first_deform_matrices(struct Depsgraph *depsgraph,
*deformmats = defmats;
*deformcos = deformedVerts;
- return numleft;
+ return modifiers_left_num;
}
void BKE_crazyspace_build_sculpt(struct Depsgraph *depsgraph,
@@ -489,13 +489,13 @@ void BKE_crazyspace_build_sculpt(struct Depsgraph *depsgraph,
}
if (*deformmats == NULL) {
- int a, numVerts;
+ int a, verts_num;
Mesh *mesh = (Mesh *)object->data;
- *deformcos = BKE_mesh_vert_coords_alloc(mesh, &numVerts);
- *deformmats = MEM_callocN(sizeof(*(*deformmats)) * numVerts, "defmats");
+ *deformcos = BKE_mesh_vert_coords_alloc(mesh, &verts_num);
+ *deformmats = MEM_callocN(sizeof(*(*deformmats)) * verts_num, "defmats");
- for (a = 0; a < numVerts; a++) {
+ for (a = 0; a < verts_num; a++) {
unit_m3((*deformmats)[a]);
}
}
@@ -523,7 +523,7 @@ void BKE_crazyspace_api_eval(Depsgraph *depsgraph,
}
const Mesh *mesh = (const Mesh *)object->data;
- object->runtime.crazyspace_num_verts = mesh->totvert;
+ object->runtime.crazyspace_verts_num = mesh->totvert;
BKE_crazyspace_build_sculpt(depsgraph,
scene,
object,
@@ -537,12 +537,12 @@ void BKE_crazyspace_api_displacement_to_deformed(struct Object *object,
float displacement[3],
float r_displacement_deformed[3])
{
- if (vertex_index < 0 || vertex_index >= object->runtime.crazyspace_num_verts) {
+ if (vertex_index < 0 || vertex_index >= object->runtime.crazyspace_verts_num) {
BKE_reportf(reports,
RPT_ERROR,
"Invalid vertex index %d (expected to be within 0 to %d range)",
vertex_index,
- object->runtime.crazyspace_num_verts);
+ object->runtime.crazyspace_verts_num);
return;
}
@@ -557,12 +557,12 @@ void BKE_crazyspace_api_displacement_to_original(struct Object *object,
float displacement_deformed[3],
float r_displacement[3])
{
- if (vertex_index < 0 || vertex_index >= object->runtime.crazyspace_num_verts) {
+ if (vertex_index < 0 || vertex_index >= object->runtime.crazyspace_verts_num) {
BKE_reportf(reports,
RPT_ERROR,
"Invalid vertex index %d (expected to be within 0 to %d range))",
vertex_index,
- object->runtime.crazyspace_num_verts);
+ object->runtime.crazyspace_verts_num);
return;
}
diff --git a/source/blender/blenkernel/intern/curve.cc b/source/blender/blenkernel/intern/curve.cc
index 02710982564..26f5d7e9cb4 100644
--- a/source/blender/blenkernel/intern/curve.cc
+++ b/source/blender/blenkernel/intern/curve.cc
@@ -3184,7 +3184,7 @@ static void calchandleNurb_intern(BezTriple *bezt,
len *= 2.5614f;
if (len != 0.0f) {
- /* only for fcurves */
+ /* Only for F-curves. */
bool leftviolate = false, rightviolate = false;
if (!is_fcurve || fcurve_smoothing == FCURVE_SMOOTH_NONE) {
@@ -4765,7 +4765,7 @@ bool BKE_nurb_valid_message(const int pnts,
message_dst[0] = 0;
return false;
}
- msg_template = TIP_("At least two points required.");
+ msg_template = TIP_("At least two points required");
break;
case NURBSValidationStatus::MorePointsThanOrderRequired:
msg_template = TIP_("Must have more control points than Order");
diff --git a/source/blender/blenkernel/intern/curve_bezier.cc b/source/blender/blenkernel/intern/curve_bezier.cc
index b11216983b2..30a5869c976 100644
--- a/source/blender/blenkernel/intern/curve_bezier.cc
+++ b/source/blender/blenkernel/intern/curve_bezier.cc
@@ -58,6 +58,131 @@ void calculate_evaluated_offsets(const Span<int8_t> handle_types_left,
evaluated_offsets.last() = offset;
}
+static float3 calculate_aligned_handle(const float3 &position,
+ const float3 &other_handle,
+ const float3 &aligned_handle)
+{
+ /* Keep track of the old length of the opposite handle. */
+ const float length = math::distance(aligned_handle, position);
+ /* Set the other handle to directly opposite from the current handle. */
+ const float3 dir = math::normalize(other_handle - position);
+ return position - dir * length;
+}
+
+static void calculate_point_handles(const HandleType type_left,
+ const HandleType type_right,
+ const float3 position,
+ const float3 prev_position,
+ const float3 next_position,
+ float3 &left,
+ float3 &right)
+{
+ if (ELEM(BEZIER_HANDLE_AUTO, type_left, type_right)) {
+ const float3 prev_diff = position - prev_position;
+ const float3 next_diff = next_position - position;
+ float prev_len = math::length(prev_diff);
+ float next_len = math::length(next_diff);
+ if (prev_len == 0.0f) {
+ prev_len = 1.0f;
+ }
+ if (next_len == 0.0f) {
+ next_len = 1.0f;
+ }
+ const float3 dir = next_diff / next_len + prev_diff / prev_len;
+
+ /* This magic number is unfortunate, but comes from elsewhere in Blender. */
+ const float len = math::length(dir) * 2.5614f;
+ if (len != 0.0f) {
+ if (type_left == BEZIER_HANDLE_AUTO) {
+ const float prev_len_clamped = std::min(prev_len, next_len * 5.0f);
+ left = position + dir * -(prev_len_clamped / len);
+ }
+ if (type_right == BEZIER_HANDLE_AUTO) {
+ const float next_len_clamped = std::min(next_len, prev_len * 5.0f);
+ right = position + dir * (next_len_clamped / len);
+ }
+ }
+ }
+
+ if (type_left == BEZIER_HANDLE_VECTOR) {
+ left = math::interpolate(position, prev_position, 1.0f / 3.0f);
+ }
+
+ if (type_right == BEZIER_HANDLE_VECTOR) {
+ right = math::interpolate(position, next_position, 1.0f / 3.0f);
+ }
+
+ /* When one of the handles is "aligned" handle, it must be aligned with the other, i.e. point in
+ * the opposite direction. Don't handle the case of two aligned handles, because code elsewhere
+ * should keep the pair consistent, and the relative locations aren't affected by other points
+ * anyway. */
+ if (type_left == BEZIER_HANDLE_ALIGN && type_right != BEZIER_HANDLE_ALIGN) {
+ left = calculate_aligned_handle(position, right, left);
+ }
+ else if (type_left != BEZIER_HANDLE_ALIGN && type_right == BEZIER_HANDLE_ALIGN) {
+ right = calculate_aligned_handle(position, left, right);
+ }
+}
+
+void set_handle_position(const float3 &position,
+ const HandleType type,
+ const HandleType type_other,
+ const float3 &new_handle,
+ float3 &handle,
+ float3 &handle_other)
+{
+ /* Don't bother when the handle positions are calculated automatically anyway. */
+ if (ELEM(type, BEZIER_HANDLE_AUTO, BEZIER_HANDLE_VECTOR)) {
+ return;
+ }
+
+ handle = new_handle;
+ if (type_other == BEZIER_HANDLE_ALIGN) {
+ handle_other = calculate_aligned_handle(position, handle, handle_other);
+ }
+}
+
+void calculate_auto_handles(const bool cyclic,
+ const Span<int8_t> types_left,
+ const Span<int8_t> types_right,
+ const Span<float3> positions,
+ MutableSpan<float3> positions_left,
+ MutableSpan<float3> positions_right)
+{
+ const int points_num = positions.size();
+ if (points_num == 1) {
+ return;
+ }
+
+ calculate_point_handles(HandleType(types_left.first()),
+ HandleType(types_right.first()),
+ positions.first(),
+ cyclic ? positions.last() : 2.0f * positions.first() - positions[1],
+ positions[1],
+ positions_left.first(),
+ positions_right.first());
+
+ threading::parallel_for(IndexRange(1, points_num - 2), 1024, [&](IndexRange range) {
+ for (const int i : range) {
+ calculate_point_handles(HandleType(types_left[i]),
+ HandleType(types_right[i]),
+ positions[i],
+ positions[i - 1],
+ positions[i + 1],
+ positions_left[i],
+ positions_right[i]);
+ }
+ });
+
+ calculate_point_handles(HandleType(types_left.last()),
+ HandleType(types_right.last()),
+ positions.last(),
+ positions.last(1),
+ cyclic ? positions.first() : 2.0f * positions.last() - positions.last(1),
+ positions_left.last(),
+ positions_right.last());
+}
+
void evaluate_segment(const float3 &point_0,
const float3 &point_1,
const float3 &point_2,
@@ -150,7 +275,7 @@ static void interpolate_to_evaluated(const Span<T> src,
MutableSpan<T> dst)
{
BLI_assert(!src.is_empty());
- BLI_assert(dst.size() == src.size());
+ BLI_assert(evaluated_offsets.size() == src.size());
BLI_assert(evaluated_offsets.last() == dst.size());
linear_interpolation(src.first(), src[1], dst.take_front(evaluated_offsets.first()));
@@ -178,6 +303,4 @@ void interpolate_to_evaluated(const GSpan src, const Span<int> evaluated_offsets
});
}
-/** \} */
-
} // namespace blender::bke::curves::bezier
diff --git a/source/blender/blenkernel/intern/curve_catmull_rom.cc b/source/blender/blenkernel/intern/curve_catmull_rom.cc
index ea3672dd56b..2db183eea3e 100644
--- a/source/blender/blenkernel/intern/curve_catmull_rom.cc
+++ b/source/blender/blenkernel/intern/curve_catmull_rom.cc
@@ -13,7 +13,7 @@ int calculate_evaluated_size(const int points_num, const bool cyclic, const int
{
const int eval_size = resolution * curve_segment_size(points_num, cyclic);
/* If the curve isn't cyclic, one last point is added to the final point. */
- return (cyclic && points_num > 2) ? eval_size : eval_size + 1;
+ return cyclic ? eval_size : eval_size + 1;
}
/* Adapted from Cycles #catmull_rom_basis_eval function. */
@@ -58,8 +58,14 @@ static void interpolate_to_evaluated(const Span<T> src,
return;
}
if (src.size() == 2) {
- evaluate_segment(src.first(), src.first(), src.last(), src.last(), dst);
- dst.last() = src.last();
+ evaluate_segment(src.first(), src.first(), src.last(), src.last(), dst.take_front(resolution));
+ if (cyclic) {
+ evaluate_segment(
+ src.last(), src.last(), src.first(), src.first(), dst.take_back(resolution));
+ }
+ else {
+ dst.last() = src.last();
+ }
return;
}
diff --git a/source/blender/blenkernel/intern/curves_geometry.cc b/source/blender/blenkernel/intern/curves_geometry.cc
index 7ceaa8f0f37..66088714e63 100644
--- a/source/blender/blenkernel/intern/curves_geometry.cc
+++ b/source/blender/blenkernel/intern/curves_geometry.cc
@@ -11,6 +11,7 @@
#include "BLI_bounds.hh"
#include "BLI_index_mask_ops.hh"
+#include "BLI_length_parameterize.hh"
#include "DNA_curves_types.h"
@@ -547,6 +548,12 @@ Span<int> CurvesGeometry::evaluated_offsets() const
return this->runtime->evaluated_offsets_cache;
}
+Span<int> CurvesGeometry::bezier_evaluated_offsets_for_curve(const int curve_index) const
+{
+ const IndexRange points = this->points_for_curve(curve_index);
+ return this->runtime->bezier_evaluated_offsets.as_span().slice(points);
+}
+
IndexMask CurvesGeometry::indices_for_curve_type(const CurveType type,
Vector<int64_t> &r_indices) const
{
@@ -721,6 +728,69 @@ void CurvesGeometry::interpolate_to_evaluated(const int curve_index,
BLI_assert_unreachable();
}
+IndexRange CurvesGeometry::lengths_range_for_curve(const int curve_index, const bool cyclic) const
+{
+ BLI_assert(cyclic == this->cyclic()[curve_index]);
+ const IndexRange points = this->evaluated_points_for_curve(curve_index);
+ const int start = points.start() + curve_index;
+ const int size = curves::curve_segment_size(points.size(), cyclic);
+ return {start, size};
+}
+
+void CurvesGeometry::ensure_evaluated_lengths() const
+{
+ if (!this->runtime->length_cache_dirty) {
+ return;
+ }
+
+ /* A double checked lock. */
+ std::scoped_lock lock{this->runtime->length_cache_mutex};
+ if (!this->runtime->length_cache_dirty) {
+ return;
+ }
+
+ threading::isolate_task([&]() {
+ /* Use an extra length value for the final cyclic segment for a consistent size
+ * (see comment on #evaluated_length_cache). */
+ const int total_size = this->evaluated_points_num() + this->curves_num();
+ this->runtime->evaluated_length_cache.resize(total_size);
+ MutableSpan<float> evaluated_lengths = this->runtime->evaluated_length_cache;
+
+ Span<float3> evaluated_positions = this->evaluated_positions();
+ VArray<bool> curves_cyclic = this->cyclic();
+
+ threading::parallel_for(this->curves_range(), 128, [&](IndexRange curves_range) {
+ for (const int curve_index : curves_range) {
+ const bool cyclic = curves_cyclic[curve_index];
+ const IndexRange evaluated_points = this->evaluated_points_for_curve(curve_index);
+ if (UNLIKELY(evaluated_points.is_empty())) {
+ continue;
+ }
+ const IndexRange lengths_range = this->lengths_range_for_curve(curve_index, cyclic);
+ length_parameterize::accumulate_lengths(evaluated_positions.slice(evaluated_points),
+ cyclic,
+ evaluated_lengths.slice(lengths_range));
+ }
+ });
+ });
+
+ this->runtime->length_cache_dirty = false;
+}
+
+Span<float> CurvesGeometry::evaluated_lengths_for_curve(const int curve_index,
+ const bool cyclic) const
+{
+ BLI_assert(!this->runtime->length_cache_dirty);
+ const IndexRange range = this->lengths_range_for_curve(curve_index, cyclic);
+ return this->runtime->evaluated_length_cache.as_span().slice(range);
+}
+
+float CurvesGeometry::evaluated_length_total_for_curve(const int curve_index,
+ const bool cyclic) const
+{
+ return this->evaluated_lengths_for_curve(curve_index, cyclic).last();
+}
+
/** \} */
/* -------------------------------------------------------------------- */
@@ -747,6 +817,7 @@ void CurvesGeometry::tag_positions_changed()
this->runtime->position_cache_dirty = true;
this->runtime->tangent_cache_dirty = true;
this->runtime->normal_cache_dirty = true;
+ this->runtime->length_cache_dirty = true;
}
void CurvesGeometry::tag_topology_changed()
{
@@ -755,6 +826,7 @@ void CurvesGeometry::tag_topology_changed()
this->runtime->normal_cache_dirty = true;
this->runtime->offsets_cache_dirty = true;
this->runtime->nurbs_basis_cache_dirty = true;
+ this->runtime->length_cache_dirty = true;
}
void CurvesGeometry::tag_normals_changed()
{
@@ -779,6 +851,34 @@ static void transform_positions(MutableSpan<float3> positions, const float4x4 &m
});
}
+void CurvesGeometry::calculate_bezier_auto_handles()
+{
+ const VArray<int8_t> types = std::as_const(*this).curve_types();
+ if (types.is_single() && types.get_internal_single() != CURVE_TYPE_BEZIER) {
+ return;
+ }
+ const VArray<bool> cyclic = std::as_const(*this).cyclic();
+ const Span<int8_t> types_left = this->handle_types_left();
+ const Span<int8_t> types_right = this->handle_types_right();
+ const Span<float3> positions = this->positions();
+ MutableSpan<float3> positions_left = this->handle_positions_left();
+ MutableSpan<float3> positions_right = this->handle_positions_right();
+
+ threading::parallel_for(this->curves_range(), 128, [&](IndexRange range) {
+ for (const int i_curve : range) {
+ if (types[i_curve] == CURVE_TYPE_BEZIER) {
+ const IndexRange points = this->points_for_curve(i_curve);
+ curves::bezier::calculate_auto_handles(cyclic[i_curve],
+ types_left.slice(points),
+ types_right.slice(points),
+ positions.slice(points),
+ positions_left.slice(points),
+ positions_right.slice(points));
+ }
+ }
+ });
+}
+
void CurvesGeometry::translate(const float3 &translation)
{
/* Use `as_const` because the non-const functions can add the handle attributes. */
diff --git a/source/blender/blenkernel/intern/curves_geometry_test.cc b/source/blender/blenkernel/intern/curves_geometry_test.cc
index e4dc9eead60..baa47bb7cf6 100644
--- a/source/blender/blenkernel/intern/curves_geometry_test.cc
+++ b/source/blender/blenkernel/intern/curves_geometry_test.cc
@@ -226,9 +226,8 @@ TEST(curves_geometry, CatmullRomTwoPointCyclic)
curves.offsets().last() = 2;
curves.cyclic().fill(true);
- /* The cyclic value should be ignored when there are only two control points. There should
- * be 12 evaluated points for the single segment and an extra for the last point. */
- EXPECT_EQ(curves.evaluated_points_num(), 13);
+ /* The curve should still be cyclic when there are only two control points. */
+ EXPECT_EQ(curves.evaluated_points_num(), 24);
}
TEST(curves_geometry, BezierPositionEvaluation)
diff --git a/source/blender/blenkernel/intern/customdata.cc b/source/blender/blenkernel/intern/customdata.cc
index bf6f05300f8..9258c1ffb66 100644
--- a/source/blender/blenkernel/intern/customdata.cc
+++ b/source/blender/blenkernel/intern/customdata.cc
@@ -5379,8 +5379,6 @@ void CustomData_debug_info_from_layers(const CustomData *data, const char *inden
namespace blender::bke {
-/** \} */
-
/* -------------------------------------------------------------------- */
/** \name Custom Data C++ API
* \{ */
diff --git a/source/blender/blenkernel/intern/geometry_component_curves.cc b/source/blender/blenkernel/intern/geometry_component_curves.cc
index 27689d70c77..b5771cc063f 100644
--- a/source/blender/blenkernel/intern/geometry_component_curves.cc
+++ b/source/blender/blenkernel/intern/geometry_component_curves.cc
@@ -9,6 +9,7 @@
#include "BKE_attribute_math.hh"
#include "BKE_curve.h"
#include "BKE_curves.hh"
+#include "BKE_geometry_fields.hh"
#include "BKE_geometry_set.hh"
#include "BKE_lib_id.h"
#include "BKE_spline.hh"
diff --git a/source/blender/blenkernel/intern/geometry_component_mesh.cc b/source/blender/blenkernel/intern/geometry_component_mesh.cc
index 2bfe984462c..f5ed21af19a 100644
--- a/source/blender/blenkernel/intern/geometry_component_mesh.cc
+++ b/source/blender/blenkernel/intern/geometry_component_mesh.cc
@@ -10,6 +10,7 @@
#include "BKE_attribute_access.hh"
#include "BKE_attribute_math.hh"
#include "BKE_deform.h"
+#include "BKE_geometry_fields.hh"
#include "BKE_geometry_set.hh"
#include "BKE_lib_id.h"
#include "BKE_mesh.h"
diff --git a/source/blender/blenkernel/intern/geometry_set.cc b/source/blender/blenkernel/intern/geometry_set.cc
index 0eece6e9ad0..0b08acf92a3 100644
--- a/source/blender/blenkernel/intern/geometry_set.cc
+++ b/source/blender/blenkernel/intern/geometry_set.cc
@@ -8,6 +8,7 @@
#include "BKE_attribute.h"
#include "BKE_attribute_access.hh"
#include "BKE_curves.hh"
+#include "BKE_geometry_fields.hh"
#include "BKE_geometry_set.hh"
#include "BKE_lib_id.h"
#include "BKE_mesh.h"
diff --git a/source/blender/blenkernel/intern/gpencil_geom.cc b/source/blender/blenkernel/intern/gpencil_geom.cc
index a0b6ab2d654..76f21e369aa 100644
--- a/source/blender/blenkernel/intern/gpencil_geom.cc
+++ b/source/blender/blenkernel/intern/gpencil_geom.cc
@@ -572,11 +572,11 @@ static bool BKE_gpencil_stroke_extra_points(bGPDstroke *gps,
bGPDspoint *new_pts = (bGPDspoint *)MEM_mallocN(sizeof(bGPDspoint) * new_count, __func__);
for (int i = 0; i < count_before; i++) {
- memcpy(&new_pts[i], &pts[0], sizeof(bGPDspoint));
+ new_pts[i] = blender::dna::shallow_copy(pts[0]);
}
- memcpy(&new_pts[count_before], pts, sizeof(bGPDspoint) * gps->totpoints);
+ memcpy(static_cast<void *>(&new_pts[count_before]), pts, sizeof(bGPDspoint) * gps->totpoints);
for (int i = new_count - count_after; i < new_count; i++) {
- memcpy(&new_pts[i], &pts[gps->totpoints - 1], sizeof(bGPDspoint));
+ new_pts[i] = blender::dna::shallow_copy(pts[gps->totpoints - 1]);
}
if (gps->dvert) {
@@ -809,7 +809,7 @@ bool BKE_gpencil_stroke_trim_points(bGPDstroke *gps, const int index_from, const
}
new_pt = (bGPDspoint *)MEM_mallocN(sizeof(bGPDspoint) * new_count, "gp_stroke_points_trimmed");
- memcpy(new_pt, &pt[index_from], sizeof(bGPDspoint) * new_count);
+ memcpy(static_cast<void *>(new_pt), &pt[index_from], sizeof(bGPDspoint) * new_count);
if (gps->dvert) {
new_dv = (MDeformVert *)MEM_mallocN(sizeof(MDeformVert) * new_count,
@@ -866,7 +866,7 @@ bool BKE_gpencil_stroke_split(bGPdata *gpd,
gpf, gps, gps->mat_nr, new_count, gps->thickness);
new_pt = new_gps->points; /* Allocated from above. */
- memcpy(new_pt, &pt[before_index], sizeof(bGPDspoint) * new_count);
+ memcpy(static_cast<void *>(new_pt), &pt[before_index], sizeof(bGPDspoint) * new_count);
if (gps->dvert) {
new_dv = (MDeformVert *)MEM_mallocN(sizeof(MDeformVert) * new_count,
@@ -1027,11 +1027,11 @@ bool BKE_gpencil_stroke_smooth_point(bGPDstroke *gps,
* smooth. To solve that problem, choose a different n/2, which does not match the range and
* normalize the weights on finish. This may cause some artifacts at low values.
*
- * keep_shape is a new option to stop the stroke from severly deforming.
+ * keep_shape is a new option to stop the stroke from severely deforming.
* It uses different partially negative weights.
* w = 2 * (nCr(n, j + n/2) / 2^n) - (nCr(3*n, j + n) / 2^(3*n))
* ~ 2 * sqrt(2/(pi*n)) * exp(-2*j*j/n) - sqrt(2/(pi*3*n)) * exp(-2*j*j/(3*n))
- * All weigths still sum up to 1.
+ * All weights still sum up to 1.
* Note these weights only work because the averaging is done in relative coordinates.
*/
float sco[3] = {0.0f, 0.0f, 0.0f};
@@ -1302,7 +1302,7 @@ void BKE_gpencil_stroke_smooth(bGPDstroke *gps,
}
/* Make a copy of the point data to avoid directionality of the smooth operation. */
- bGPDstroke gps_old = *gps;
+ bGPDstroke gps_old = blender::dna::shallow_copy(*gps);
gps_old.points = (bGPDspoint *)MEM_dupallocN(gps->points);
/* Smooth stroke. */
@@ -1765,7 +1765,7 @@ bool BKE_gpencil_stroke_trim(bGPdata *gpd, bGPDstroke *gps)
int idx = start + i;
bGPDspoint *pt_src = &old_points[idx];
bGPDspoint *pt_new = &gps->points[i];
- memcpy(pt_new, pt_src, sizeof(bGPDspoint));
+ *pt_new = blender::dna::shallow_copy(*pt_src);
if (gps->dvert != nullptr) {
dvert_src = &old_dvert[idx];
MDeformVert *dvert = &gps->dvert[i];
@@ -1930,7 +1930,7 @@ void BKE_gpencil_dissolve_points(bGPdata *gpd, bGPDframe *gpf, bGPDstroke *gps,
(gps->dvert != nullptr) ? dvert = gps->dvert : nullptr;
for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
if ((pt->flag & tag) == 0) {
- *npt = *pt;
+ *npt = blender::dna::shallow_copy(*pt);
npt++;
if (gps->dvert != nullptr) {
@@ -2080,7 +2080,7 @@ void BKE_gpencil_stroke_simplify_adaptive(bGPdata *gpd, bGPDstroke *gps, float e
bGPDspoint *pt = &gps->points[j];
if ((marked[i]) || (i == 0) || (i == totpoints - 1)) {
- memcpy(pt, pt_src, sizeof(bGPDspoint));
+ *pt = blender::dna::shallow_copy(*pt_src);
if (gps->dvert != nullptr) {
dvert_src = &old_dvert[i];
MDeformVert *dvert = &gps->dvert[j];
@@ -2142,7 +2142,7 @@ void BKE_gpencil_stroke_simplify_fixed(bGPdata *gpd, bGPDstroke *gps)
bGPDspoint *pt = &gps->points[j];
if ((i == 0) || (i == gps->totpoints - 1) || ((i % 2) > 0.0)) {
- memcpy(pt, pt_src, sizeof(bGPDspoint));
+ *pt = blender::dna::shallow_copy(*pt_src);
if (gps->dvert != nullptr) {
dvert_src = &old_dvert[i];
MDeformVert *dvert = &gps->dvert[j];
@@ -3158,7 +3158,7 @@ bGPDstroke *BKE_gpencil_stroke_delete_tagged_points(bGPdata *gpd,
/* Copy over the relevant point data */
new_stroke->points = (bGPDspoint *)MEM_callocN(sizeof(bGPDspoint) * new_stroke->totpoints,
"gp delete stroke fragment");
- memcpy(new_stroke->points,
+ memcpy(static_cast<void *>(new_stroke->points),
gps->points + island->start_idx,
sizeof(bGPDspoint) * new_stroke->totpoints);
@@ -3471,13 +3471,13 @@ void BKE_gpencil_stroke_join(bGPDstroke *gps_a,
/* don't visibly link the first and last points? */
if (leave_gaps) {
/* 1st: add one tail point to start invisible area */
- point = gps_a->points[gps_a->totpoints - 1];
+ point = blender::dna::shallow_copy(gps_a->points[gps_a->totpoints - 1]);
deltatime = point.time;
gpencil_stroke_copy_point(gps_a, nullptr, &point, delta, 0.0f, 0.0f, 0.0f);
/* 2nd: add one head point to finish invisible area */
- point = gps_b->points[0];
+ point = blender::dna::shallow_copy(gps_b->points[0]);
gpencil_stroke_copy_point(gps_a, nullptr, &point, delta, 0.0f, 0.0f, deltatime);
}
diff --git a/source/blender/blenkernel/intern/gpencil_modifier.c b/source/blender/blenkernel/intern/gpencil_modifier.c
index 33410b4521e..faafd1e1040 100644
--- a/source/blender/blenkernel/intern/gpencil_modifier.c
+++ b/source/blender/blenkernel/intern/gpencil_modifier.c
@@ -743,7 +743,7 @@ void BKE_gpencil_prepare_eval_data(Depsgraph *depsgraph, Scene *scene, Object *o
}
BLI_assert(ob->data != NULL);
- /* Only copy strokes from visible frames to evaluated data.*/
+ /* Only copy strokes from visible frames to evaluated data. */
gpencil_copy_visible_frames_to_eval(depsgraph, scene, ob);
}
diff --git a/source/blender/blenkernel/intern/gpencil_update_cache.c b/source/blender/blenkernel/intern/gpencil_update_cache.c
index bbe576eb847..9113f2e2ab9 100644
--- a/source/blender/blenkernel/intern/gpencil_update_cache.c
+++ b/source/blender/blenkernel/intern/gpencil_update_cache.c
@@ -51,10 +51,8 @@ static void cache_node_free(void *node);
static void update_cache_free(GPencilUpdateCache *cache)
{
- if (cache->children != NULL) {
- BLI_dlrbTree_free(cache->children, cache_node_free);
- MEM_freeN(cache->children);
- }
+ BLI_dlrbTree_free(cache->children, cache_node_free);
+ MEM_SAFE_FREE(cache->children);
MEM_freeN(cache);
}
@@ -83,9 +81,8 @@ static void cache_node_update(void *node, void *data)
/* In case the new cache does a full update, remove its children since they will be all
* updated by this cache. */
- if (new_update_cache->flag == GP_UPDATE_NODE_FULL_COPY && update_cache->children != NULL) {
+ if (new_update_cache->flag == GP_UPDATE_NODE_FULL_COPY) {
BLI_dlrbTree_free(update_cache->children, cache_node_free);
- MEM_freeN(update_cache->children);
}
update_cache_free(new_update_cache);
diff --git a/source/blender/blenkernel/intern/icons.cc b/source/blender/blenkernel/intern/icons.cc
index 8883613786b..2ba6510ee71 100644
--- a/source/blender/blenkernel/intern/icons.cc
+++ b/source/blender/blenkernel/intern/icons.cc
@@ -416,7 +416,7 @@ void BKE_previewimg_id_custom_set(ID *id, const char *path)
bool BKE_previewimg_id_supports_jobs(const ID *id)
{
- return ELEM(GS(id->name), ID_OB, ID_MA, ID_TE, ID_LA, ID_WO, ID_IM, ID_BR);
+ return ELEM(GS(id->name), ID_OB, ID_MA, ID_TE, ID_LA, ID_WO, ID_IM, ID_BR, ID_GR);
}
void BKE_previewimg_deferred_release(PreviewImage *prv)
diff --git a/source/blender/blenkernel/intern/image.cc b/source/blender/blenkernel/intern/image.cc
index b65f3416f0f..3eade265bf2 100644
--- a/source/blender/blenkernel/intern/image.cc
+++ b/source/blender/blenkernel/intern/image.cc
@@ -468,7 +468,9 @@ constexpr IDTypeInfo get_type_info()
IDTypeInfo IDType_ID_IM = get_type_info();
/* prototypes */
-static int image_num_files(struct Image *ima);
+static int image_num_viewfiles(Image *ima);
+static ImBuf *image_load_image_file(
+ Image *ima, ImageUser *iuser, int entry, int cfra, bool is_sequence);
static ImBuf *image_acquire_ibuf(Image *ima, ImageUser *iuser, void **r_lock);
static void image_update_views_format(Image *ima, ImageUser *iuser);
static void image_add_view(Image *ima, const char *viewname, const char *filepath);
@@ -1277,9 +1279,9 @@ bool BKE_image_memorypack(Image *ima)
void BKE_image_packfiles(ReportList *reports, Image *ima, const char *basepath)
{
- const int totfiles = image_num_files(ima);
+ const int tot_viewfiles = image_num_viewfiles(ima);
- if (totfiles == 1) {
+ if (tot_viewfiles == 1) {
ImagePackedFile *imapf = static_cast<ImagePackedFile *>(
MEM_mallocN(sizeof(ImagePackedFile), "Image packed file"));
BLI_addtail(&ima->packedfiles, imapf);
@@ -1313,9 +1315,9 @@ void BKE_image_packfiles_from_mem(ReportList *reports,
char *data,
const size_t data_len)
{
- const int totfiles = image_num_files(ima);
+ const int tot_viewfiles = image_num_viewfiles(ima);
- if (totfiles != 1) {
+ if (tot_viewfiles != 1) {
BKE_report(reports, RPT_ERROR, "Cannot pack multiview images from raw data currently...");
}
else {
@@ -2944,9 +2946,9 @@ void BKE_image_signal(Main *bmain, Image *ima, ImageUser *iuser, int signal)
case IMA_SIGNAL_RELOAD:
/* try to repack file */
if (BKE_image_has_packedfile(ima)) {
- const int totfiles = image_num_files(ima);
+ const int tot_viewfiles = image_num_viewfiles(ima);
- if (totfiles != BLI_listbase_count_at_most(&ima->packedfiles, totfiles + 1)) {
+ if (tot_viewfiles != BLI_listbase_count_at_most(&ima->packedfiles, tot_viewfiles + 1)) {
/* in case there are new available files to be loaded */
image_free_packedfiles(ima);
BKE_image_packfiles(nullptr, ima, ID_BLEND_PATH(bmain, &ima->id));
@@ -3739,7 +3741,7 @@ static int imbuf_alpha_flags_for_image(Image *ima)
/**
* \return the number of files will vary according to the stereo format.
*/
-static int image_num_files(Image *ima)
+static int image_num_viewfiles(Image *ima)
{
const bool is_multiview = BKE_image_is_multiview(ima);
@@ -3754,117 +3756,6 @@ static int image_num_files(Image *ima)
return BLI_listbase_count(&ima->views);
}
-static ImBuf *load_sequence_single(
- Image *ima, ImageUser *iuser, int frame, const int view_id, bool *r_cache_ibuf)
-{
- struct ImBuf *ibuf;
- char name[FILE_MAX];
- int flag;
- ImageUser iuser_t{};
-
- *r_cache_ibuf = true;
-
- ima->lastframe = frame;
-
- if (iuser) {
- iuser_t = *iuser;
- }
- else {
- /* BKE_image_user_file_path() uses this value for file name for sequences. */
- iuser_t.framenr = frame;
- /* TODO(sergey): Do we need to initialize something else here? */
- }
-
- iuser_t.view = view_id;
- BKE_image_user_file_path(&iuser_t, ima, name);
-
- flag = IB_rect | IB_multilayer | IB_metadata;
- flag |= imbuf_alpha_flags_for_image(ima);
-
- /* read ibuf */
- ibuf = IMB_loadiffname(name, flag, ima->colorspace_settings.name);
-
-#if 0
- if (ibuf) {
- printf(AT " loaded %s\n", name);
- }
- else {
- printf(AT " missed %s\n", name);
- }
-#endif
-
- if (ibuf) {
-#ifdef WITH_OPENEXR
- if (ibuf->ftype == IMB_FTYPE_OPENEXR && ibuf->userdata) {
- /* Handle multilayer and multiview cases, don't assign ibuf here.
- * will be set layer in BKE_image_acquire_ibuf from ima->rr. */
- if (IMB_exr_has_multilayer(ibuf->userdata)) {
- image_create_multilayer(ima, ibuf, frame);
- ima->type = IMA_TYPE_MULTILAYER;
- IMB_freeImBuf(ibuf);
- 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;
- }
- }
- else {
- image_init_after_load(ima, iuser, ibuf);
- }
-#else
- image_init_after_load(ima, iuser, ibuf);
-#endif
- }
-
- return ibuf;
-}
-
-static ImBuf *image_load_sequence_file(Image *ima, ImageUser *iuser, int entry, int frame)
-{
- struct ImBuf *ibuf = nullptr;
- const bool is_multiview = BKE_image_is_multiview(ima);
- const int totfiles = image_num_files(ima);
-
- if (!is_multiview) {
- bool put_in_cache;
- ibuf = load_sequence_single(ima, iuser, frame, 0, &put_in_cache);
- if (put_in_cache) {
- image_assign_ibuf(ima, ibuf, 0, entry);
- }
- }
- else {
- const int totviews = BLI_listbase_count(&ima->views);
- 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]);
- }
-
- if (BKE_image_is_stereo(ima) && ima->views_format == R_IMF_VIEWS_STEREO_3D) {
- IMB_ImBufFromStereo3d(ima->stereo3d_format, ibuf_arr[0], &ibuf_arr[0], &ibuf_arr[1]);
- }
-
- /* return the original requested ImBuf */
- ibuf = ibuf_arr[(iuser ? iuser->multi_index : 0)];
-
- for (int i = 0; i < totviews; i++) {
- if (cache_ibuf_arr[i]) {
- image_assign_ibuf(ima, ibuf_arr[i], i, entry);
- }
- }
-
- /* "remove" the others (decrease their refcount) */
- for (int i = 0; i < totviews; i++) {
- if (ibuf_arr[i] != ibuf) {
- IMB_freeImBuf(ibuf_arr[i]);
- }
- }
- }
-
- return ibuf;
-}
-
static ImBuf *image_load_sequence_multilayer(Image *ima, ImageUser *iuser, int entry, int frame)
{
struct ImBuf *ibuf = nullptr;
@@ -3883,7 +3774,7 @@ static ImBuf *image_load_sequence_multilayer(Image *ima, ImageUser *iuser, int e
ima->rr = nullptr;
}
- ibuf = image_load_sequence_file(ima, iuser, entry, frame);
+ ibuf = image_load_image_file(ima, iuser, entry, frame, true);
if (ibuf) { /* actually an error */
ima->type = IMA_TYPE_IMAGE;
@@ -3970,12 +3861,12 @@ static ImBuf *image_load_movie_file(Image *ima, ImageUser *iuser, int frame)
{
struct ImBuf *ibuf = nullptr;
const bool is_multiview = BKE_image_is_multiview(ima);
- const int totfiles = image_num_files(ima);
+ const int tot_viewfiles = image_num_viewfiles(ima);
- if (totfiles != BLI_listbase_count_at_most(&ima->anims, totfiles + 1)) {
+ if (tot_viewfiles != BLI_listbase_count_at_most(&ima->anims, tot_viewfiles + 1)) {
image_free_anims(ima);
- for (int i = 0; i < totfiles; i++) {
+ for (int i = 0; i < tot_viewfiles; i++) {
/* allocate the ImageAnim */
ImageAnim *ia = MEM_cnew<ImageAnim>("Image Anim");
BLI_addtail(&ima->anims, ia);
@@ -3990,7 +3881,7 @@ static ImBuf *image_load_movie_file(Image *ima, ImageUser *iuser, int frame)
const int totviews = BLI_listbase_count(&ima->views);
Array<ImBuf *> ibuf_arr(totviews);
- for (int i = 0; i < totfiles; i++) {
+ for (int i = 0; i < tot_viewfiles; i++) {
ibuf_arr[i] = load_movie_single(ima, iuser, frame, i);
}
@@ -4021,23 +3912,21 @@ static ImBuf *load_image_single(Image *ima,
int cfra,
const int view_id,
const bool has_packed,
+ const bool is_sequence,
bool *r_cache_ibuf)
{
char filepath[FILE_MAX];
struct ImBuf *ibuf = nullptr;
- int flag;
+ int flag = IB_rect | IB_multilayer;
*r_cache_ibuf = true;
/* is there a PackedFile with this image ? */
- if (has_packed) {
- ImagePackedFile *imapf;
-
- flag = IB_rect | IB_multilayer;
- flag |= imbuf_alpha_flags_for_image(ima);
-
- imapf = static_cast<ImagePackedFile *>(BLI_findlink(&ima->packedfiles, view_id));
+ if (has_packed && !is_sequence) {
+ ImagePackedFile *imapf = static_cast<ImagePackedFile *>(
+ BLI_findlink(&ima->packedfiles, view_id));
if (imapf->packedfile) {
+ flag |= imbuf_alpha_flags_for_image(ima);
ibuf = IMB_ibImageFromMemory((unsigned char *)imapf->packedfile->data,
imapf->packedfile->size,
flag,
@@ -4046,14 +3935,17 @@ static ImBuf *load_image_single(Image *ima,
}
}
else {
- ImageUser iuser_t{};
-
- flag = IB_rect | IB_multilayer | IB_metadata;
- flag |= imbuf_alpha_flags_for_image(ima);
+ if (is_sequence) {
+ ima->lastframe = cfra;
+ }
/* get the correct filepath */
- BKE_image_user_frame_calc(ima, iuser, cfra);
+ const bool is_tiled = (ima->source == IMA_SRC_TILED);
+ if (!(is_sequence || is_tiled)) {
+ BKE_image_user_frame_calc(ima, iuser, cfra);
+ }
+ ImageUser iuser_t{};
if (iuser) {
iuser_t = *iuser;
}
@@ -4066,6 +3958,8 @@ static ImBuf *load_image_single(Image *ima,
BKE_image_user_file_path(&iuser_t, ima, filepath);
/* read ibuf */
+ flag |= IB_metadata;
+ flag |= imbuf_alpha_flags_for_image(ima);
ibuf = IMB_loadiffname(filepath, flag, ima->colorspace_settings.name);
}
@@ -4090,7 +3984,7 @@ static ImBuf *load_image_single(Image *ima,
image_init_after_load(ima, iuser, ibuf);
/* Make packed file for auto-pack. */
- if ((has_packed == false) && (G.fileflags & G_FILE_AUTOPACK)) {
+ if (!is_sequence && (has_packed == false) && (G.fileflags & G_FILE_AUTOPACK)) {
ImagePackedFile *imapf = static_cast<ImagePackedFile *>(
MEM_mallocN(sizeof(ImagePackedFile), "Image Pack-file"));
BLI_addtail(&ima->packedfiles, imapf);
@@ -4108,18 +4002,23 @@ static ImBuf *load_image_single(Image *ima,
/* 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)
+static ImBuf *image_load_image_file(
+ Image *ima, ImageUser *iuser, int entry, int cfra, bool is_sequence)
{
struct ImBuf *ibuf = nullptr;
const bool is_multiview = BKE_image_is_multiview(ima);
- const int totfiles = image_num_files(ima);
+ const bool is_tiled = (ima->source == IMA_SRC_TILED);
+ const int tot_viewfiles = image_num_viewfiles(ima);
bool has_packed = BKE_image_has_packedfile(ima);
- /* always ensure clean ima */
- BKE_image_free_buffers(ima);
+ if (!(is_sequence || is_tiled)) {
+ /* ensure clean ima */
+ BKE_image_free_buffers(ima);
+ }
/* this should never happen, but just playing safe */
- if (has_packed) {
+ if (!is_sequence && has_packed) {
+ const int totfiles = tot_viewfiles * BLI_listbase_count(&ima->tiles);
if (totfiles != BLI_listbase_count_at_most(&ima->packedfiles, totfiles + 1)) {
image_free_packedfiles(ima);
has_packed = false;
@@ -4128,9 +4027,10 @@ static ImBuf *image_load_image_file(Image *ima, ImageUser *iuser, int cfra)
if (!is_multiview) {
bool put_in_cache;
- ibuf = load_image_single(ima, iuser, cfra, 0, has_packed, &put_in_cache);
+ ibuf = load_image_single(ima, iuser, cfra, 0, has_packed, is_sequence, &put_in_cache);
if (put_in_cache) {
- image_assign_ibuf(ima, ibuf, IMA_NO_INDEX, 0);
+ const int index = (is_sequence || is_tiled) ? 0 : IMA_NO_INDEX;
+ image_assign_ibuf(ima, ibuf, index, entry);
}
}
else {
@@ -4140,28 +4040,29 @@ static ImBuf *image_load_image_file(Image *ima, ImageUser *iuser, int cfra)
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]);
+ for (int i = 0; i < tot_viewfiles; i++) {
+ ibuf_arr[i] = load_image_single(
+ ima, iuser, cfra, i, has_packed, is_sequence, &cache_ibuf_arr[i]);
}
/* 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) {
+ tot_viewfiles == 1 && totviews >= 2) {
IMB_ImBufFromStereo3d(ima->stereo3d_format, ibuf_arr[0], &ibuf_arr[0], &ibuf_arr[1]);
}
/* return the original requested ImBuf */
- int i = (iuser && iuser->multi_index < totviews) ? iuser->multi_index : 0;
- ibuf = ibuf_arr[i];
+ const int ibuf_index = (iuser && iuser->multi_index < totviews) ? iuser->multi_index : 0;
+ ibuf = ibuf_arr[ibuf_index];
- for (i = 0; i < totviews; i++) {
+ for (int i = 0; i < totviews; i++) {
if (cache_ibuf_arr[i]) {
- image_assign_ibuf(ima, ibuf_arr[i], i, 0);
+ image_assign_ibuf(ima, ibuf_arr[i], i, entry);
}
}
/* "remove" the others (decrease their refcount) */
- for (i = 0; i < totviews; i++) {
+ for (int i = 0; i < totviews; i++) {
if (ibuf_arr[i] != ibuf) {
IMB_freeImBuf(ibuf_arr[i]);
}
@@ -4176,7 +4077,7 @@ static ImBuf *image_get_ibuf_multilayer(Image *ima, ImageUser *iuser)
ImBuf *ibuf = nullptr;
if (ima->rr == nullptr) {
- ibuf = image_load_image_file(ima, iuser, 0);
+ ibuf = image_load_image_file(ima, iuser, 0, 0, false);
if (ibuf) { /* actually an error */
ima->type = IMA_TYPE_IMAGE;
return ibuf;
@@ -4553,7 +4454,7 @@ static ImBuf *image_acquire_ibuf(Image *ima, ImageUser *iuser, void **r_lock)
else if (ima->source == IMA_SRC_SEQUENCE) {
if (ima->type == IMA_TYPE_IMAGE) {
/* Regular files, ibufs in flip-book, allows saving. */
- ibuf = image_load_sequence_file(ima, iuser, entry, entry);
+ ibuf = image_load_image_file(ima, iuser, entry, entry, true);
}
/* no else; on load the ima type can change */
if (ima->type == IMA_TYPE_MULTILAYER) {
@@ -4564,7 +4465,7 @@ static ImBuf *image_acquire_ibuf(Image *ima, ImageUser *iuser, void **r_lock)
else if (ima->source == IMA_SRC_TILED) {
if (ima->type == IMA_TYPE_IMAGE) {
/* Regular files, ibufs in flip-book, allows saving */
- ibuf = image_load_sequence_file(ima, iuser, entry, 0);
+ ibuf = image_load_image_file(ima, iuser, entry, 0, false);
}
/* no else; on load the ima type can change */
if (ima->type == IMA_TYPE_MULTILAYER) {
@@ -4575,7 +4476,8 @@ static ImBuf *image_acquire_ibuf(Image *ima, ImageUser *iuser, void **r_lock)
else if (ima->source == IMA_SRC_FILE) {
if (ima->type == IMA_TYPE_IMAGE) {
- ibuf = image_load_image_file(ima, iuser, entry); /* cfra only for '#', this global is OK */
+ ibuf = image_load_image_file(
+ ima, iuser, 0, entry, false); /* cfra only for '#', this global is OK */
}
/* no else; on load the ima type can change */
if (ima->type == IMA_TYPE_MULTILAYER) {
diff --git a/source/blender/blenkernel/intern/layer.c b/source/blender/blenkernel/intern/layer.c
index ccff4dbed03..c99bf885074 100644
--- a/source/blender/blenkernel/intern/layer.c
+++ b/source/blender/blenkernel/intern/layer.c
@@ -266,6 +266,8 @@ void BKE_view_layer_free_ex(ViewLayer *view_layer, const bool do_id_user)
BLI_freelistN(&view_layer->drawdata);
BLI_freelistN(&view_layer->aovs);
view_layer->active_aov = NULL;
+ BLI_freelistN(&view_layer->lightgroups);
+ view_layer->active_lightgroup = NULL;
MEM_SAFE_FREE(view_layer->stats);
@@ -428,6 +430,29 @@ static void layer_aov_copy_data(ViewLayer *view_layer_dst,
}
}
+static void layer_lightgroup_copy_data(ViewLayer *view_layer_dst,
+ const ViewLayer *view_layer_src,
+ ListBase *lightgroups_dst,
+ const ListBase *lightgroups_src)
+{
+ if (lightgroups_src != NULL) {
+ BLI_duplicatelist(lightgroups_dst, lightgroups_src);
+ }
+
+ ViewLayerLightgroup *lightgroup_dst = lightgroups_dst->first;
+ const ViewLayerLightgroup *lightgroup_src = lightgroups_src->first;
+
+ while (lightgroup_dst != NULL) {
+ BLI_assert(lightgroup_src);
+ if (lightgroup_src == view_layer_src->active_lightgroup) {
+ view_layer_dst->active_lightgroup = lightgroup_dst;
+ }
+
+ lightgroup_dst = lightgroup_dst->next;
+ lightgroup_src = lightgroup_src->next;
+ }
+}
+
static void layer_collections_copy_data(ViewLayer *view_layer_dst,
const ViewLayer *view_layer_src,
ListBase *layer_collections_dst,
@@ -496,6 +521,10 @@ void BKE_view_layer_copy_data(Scene *scene_dst,
layer_aov_copy_data(
view_layer_dst, view_layer_src, &view_layer_dst->aovs, &view_layer_src->aovs);
+ BLI_listbase_clear(&view_layer_dst->lightgroups);
+ layer_lightgroup_copy_data(
+ view_layer_dst, view_layer_src, &view_layer_dst->lightgroups, &view_layer_src->lightgroups);
+
if ((flag & LIB_ID_CREATE_NO_USER_REFCOUNT) == 0) {
id_us_plus((ID *)view_layer_dst->mat_override);
}
@@ -2256,6 +2285,9 @@ void BKE_view_layer_blend_write(BlendWriter *writer, ViewLayer *view_layer)
LISTBASE_FOREACH (ViewLayerAOV *, aov, &view_layer->aovs) {
BLO_write_struct(writer, ViewLayerAOV, aov);
}
+ LISTBASE_FOREACH (ViewLayerLightgroup *, lightgroup, &view_layer->lightgroups) {
+ BLO_write_struct(writer, ViewLayerLightgroup, lightgroup);
+ }
write_layer_collections(writer, &view_layer->layer_collections);
}
@@ -2294,6 +2326,9 @@ void BKE_view_layer_blend_read_data(BlendDataReader *reader, ViewLayer *view_lay
BLO_read_list(reader, &view_layer->aovs);
BLO_read_data_address(reader, &view_layer->active_aov);
+ BLO_read_list(reader, &view_layer->lightgroups);
+ BLO_read_data_address(reader, &view_layer->active_lightgroup);
+
BLI_listbase_clear(&view_layer->drawdata);
view_layer->object_bases_array = NULL;
view_layer->object_bases_hash = NULL;
@@ -2471,4 +2506,117 @@ ViewLayer *BKE_view_layer_find_with_aov(struct Scene *scene, struct ViewLayerAOV
return NULL;
}
+/* -------------------------------------------------------------------- */
+/** \name Light Groups
+ * \{ */
+
+static void viewlayer_lightgroup_make_name_unique(ViewLayer *view_layer,
+ ViewLayerLightgroup *lightgroup)
+{
+ /* Don't allow dots, it's incompatible with OpenEXR convention to store channels
+ * as "layer.pass.channel". */
+ BLI_str_replace_char(lightgroup->name, '.', '_');
+ BLI_uniquename(&view_layer->lightgroups,
+ lightgroup,
+ DATA_("Lightgroup"),
+ '_',
+ offsetof(ViewLayerLightgroup, name),
+ sizeof(lightgroup->name));
+}
+
+static void viewlayer_lightgroup_active_set(ViewLayer *view_layer, ViewLayerLightgroup *lightgroup)
+{
+ if (lightgroup != NULL) {
+ BLI_assert(BLI_findindex(&view_layer->lightgroups, lightgroup) != -1);
+ view_layer->active_lightgroup = lightgroup;
+ }
+ else {
+ view_layer->active_lightgroup = NULL;
+ }
+}
+
+struct ViewLayerLightgroup *BKE_view_layer_add_lightgroup(struct ViewLayer *view_layer)
+{
+ ViewLayerLightgroup *lightgroup;
+ lightgroup = MEM_callocN(sizeof(ViewLayerLightgroup), __func__);
+ BLI_strncpy(lightgroup->name, DATA_("Lightgroup"), sizeof(lightgroup->name));
+ BLI_addtail(&view_layer->lightgroups, lightgroup);
+ viewlayer_lightgroup_active_set(view_layer, lightgroup);
+ viewlayer_lightgroup_make_name_unique(view_layer, lightgroup);
+ return lightgroup;
+}
+
+void BKE_view_layer_remove_lightgroup(ViewLayer *view_layer, ViewLayerLightgroup *lightgroup)
+{
+ BLI_assert(BLI_findindex(&view_layer->lightgroups, lightgroup) != -1);
+ BLI_assert(lightgroup != NULL);
+ if (view_layer->active_lightgroup == lightgroup) {
+ if (lightgroup->next) {
+ viewlayer_lightgroup_active_set(view_layer, lightgroup->next);
+ }
+ else {
+ viewlayer_lightgroup_active_set(view_layer, lightgroup->prev);
+ }
+ }
+ BLI_freelinkN(&view_layer->lightgroups, lightgroup);
+}
+
+void BKE_view_layer_set_active_lightgroup(ViewLayer *view_layer, ViewLayerLightgroup *lightgroup)
+{
+ viewlayer_lightgroup_active_set(view_layer, lightgroup);
+}
+
+ViewLayer *BKE_view_layer_find_with_lightgroup(struct Scene *scene,
+ struct ViewLayerLightgroup *lightgroup)
+{
+ LISTBASE_FOREACH (ViewLayer *, view_layer, &scene->view_layers) {
+ if (BLI_findindex(&view_layer->lightgroups, lightgroup) != -1) {
+ return view_layer;
+ }
+ }
+ return NULL;
+}
+
+void BKE_view_layer_rename_lightgroup(ViewLayer *view_layer,
+ ViewLayerLightgroup *lightgroup,
+ const char *name)
+{
+ BLI_strncpy_utf8(lightgroup->name, name, sizeof(lightgroup->name));
+ viewlayer_lightgroup_make_name_unique(view_layer, lightgroup);
+}
+
+void BKE_lightgroup_membership_get(struct LightgroupMembership *lgm, char *name)
+{
+ if (lgm != NULL) {
+ BLI_strncpy(name, lgm->name, sizeof(lgm->name));
+ }
+ else {
+ name[0] = '\0';
+ }
+}
+
+int BKE_lightgroup_membership_length(struct LightgroupMembership *lgm)
+{
+ if (lgm != NULL) {
+ return strlen(lgm->name);
+ }
+ return 0;
+}
+
+void BKE_lightgroup_membership_set(struct LightgroupMembership **lgm, const char *name)
+{
+ if (name[0] != '\0') {
+ if (*lgm == NULL) {
+ *lgm = MEM_callocN(sizeof(LightgroupMembership), __func__);
+ }
+ BLI_strncpy((*lgm)->name, name, sizeof((*lgm)->name));
+ }
+ else {
+ if (*lgm != NULL) {
+ MEM_freeN(*lgm);
+ *lgm = NULL;
+ }
+ }
+}
+
/** \} */
diff --git a/source/blender/blenkernel/intern/lib_id.c b/source/blender/blenkernel/intern/lib_id.c
index 28745f1d2c7..27427b1fb44 100644
--- a/source/blender/blenkernel/intern/lib_id.c
+++ b/source/blender/blenkernel/intern/lib_id.c
@@ -2165,6 +2165,11 @@ bool BKE_id_can_be_asset(const ID *id)
BKE_idtype_idcode_is_linkable(GS(id->name));
}
+bool BKE_id_is_editable(Main *bmain, ID *id)
+{
+ return !(ID_IS_LINKED(id) || BKE_lib_override_library_is_system_defined(bmain, id));
+}
+
/************************* Datablock order in UI **************************/
static int *id_order_get(ID *id)
diff --git a/source/blender/blenkernel/intern/lib_override.c b/source/blender/blenkernel/intern/lib_override.c
index 64ebb08f5d0..a2338eb9b39 100644
--- a/source/blender/blenkernel/intern/lib_override.c
+++ b/source/blender/blenkernel/intern/lib_override.c
@@ -122,6 +122,9 @@ IDOverrideLibrary *BKE_lib_override_library_init(ID *local_id, ID *reference_id)
local_id->override_library->reference = reference_id;
id_us_plus(local_id->override_library->reference);
local_id->tag &= ~LIB_TAG_OVERRIDE_LIBRARY_REFOK;
+ /* By default initialized liboverrides are 'system overrides', higher-level code is responsible
+ * to unset this flag for specific IDs. */
+ local_id->override_library->flag |= IDOVERRIDE_LIBRARY_FLAG_SYSTEM_DEFINED;
/* TODO: do we want to add tag or flag to referee to mark it as such? */
return local_id->override_library;
}
@@ -276,6 +279,44 @@ bool BKE_lib_override_library_is_user_edited(struct ID *id)
return false;
}
+bool BKE_lib_override_library_is_system_defined(Main *bmain, ID *id)
+{
+
+ if (ID_IS_OVERRIDE_LIBRARY(id)) {
+ ID *override_owner_id;
+ lib_override_get(bmain, id, &override_owner_id);
+ return (override_owner_id->override_library->flag & IDOVERRIDE_LIBRARY_FLAG_SYSTEM_DEFINED) !=
+ 0;
+ }
+ return false;
+}
+
+static int foreachid_is_hierarchy_leaf_fn(LibraryIDLinkCallbackData *cb_data)
+{
+ ID *id_owner = cb_data->id_owner;
+ ID *id = *cb_data->id_pointer;
+ bool *is_leaf = cb_data->user_data;
+
+ if (id != NULL && ID_IS_OVERRIDE_LIBRARY_REAL(id) &&
+ id->override_library->hierarchy_root == id_owner->override_library->hierarchy_root) {
+ *is_leaf = false;
+ return IDWALK_RET_STOP_ITER;
+ }
+ return IDWALK_RET_NOP;
+}
+
+bool BKE_lib_override_library_is_hierarchy_leaf(Main *bmain, ID *id)
+{
+ if (ID_IS_OVERRIDE_LIBRARY_REAL(id)) {
+ bool is_leaf = true;
+ BKE_library_foreach_ID_link(
+ bmain, id, foreachid_is_hierarchy_leaf_fn, &is_leaf, IDWALK_READONLY);
+ return is_leaf;
+ }
+
+ return false;
+}
+
ID *BKE_lib_override_library_create_from_id(Main *bmain,
ID *reference_id,
const bool do_tagged_remap)
@@ -288,6 +329,7 @@ ID *BKE_lib_override_library_create_from_id(Main *bmain,
* mess in case there are a lot of hidden, non-instantiated, non-properly organized dependencies.
* Ref T94650. */
local_id->override_library->flag |= IDOVERRIDE_LIBRARY_FLAG_NO_HIERARCHY;
+ local_id->override_library->flag &= ~IDOVERRIDE_LIBRARY_FLAG_SYSTEM_DEFINED;
local_id->override_library->hierarchy_root = local_id;
if (do_tagged_remap) {
@@ -322,6 +364,18 @@ ID *BKE_lib_override_library_create_from_id(Main *bmain,
return local_id;
}
+static void lib_override_prefill_newid_from_existing_overrides(Main *bmain, ID *id_hierarchy_root)
+{
+ ID *id_iter;
+ FOREACH_MAIN_ID_BEGIN (bmain, id_iter) {
+ if (ID_IS_OVERRIDE_LIBRARY_REAL(id_iter) &&
+ id_iter->override_library->hierarchy_root == id_hierarchy_root) {
+ id_iter->override_library->reference->newid = id_iter;
+ }
+ }
+ FOREACH_MAIN_ID_END;
+}
+
/* TODO: Make this static local function instead? API is becoming complex, and it's not used
* outside of this file anyway. */
bool BKE_lib_override_library_create_from_tag(Main *bmain,
@@ -345,6 +399,13 @@ bool BKE_lib_override_library_create_from_tag(Main *bmain,
* resync process mainly). */
BLI_assert((ID_IS_OVERRIDE_LIBRARY_REAL(id_hierarchy_root) &&
id_hierarchy_root->override_library->reference->lib == id_root_reference->lib));
+
+ if (!do_no_main) {
+ /* When processing within Main, set existing overrides in given hierarchy as 'newid' of their
+ * linked reference. This allows to re-use existing overrides instead of creating new ones in
+ * partial override cases. */
+ lib_override_prefill_newid_from_existing_overrides(bmain, id_hierarchy_root);
+ }
}
if (!ELEM(id_hierarchy_root_reference, NULL, id_root_reference)) {
/* If the reference hierarchy root is given, it must be from the same library as the reference
@@ -1616,6 +1677,8 @@ static bool lib_override_library_resync(Main *bmain,
if (ID_IS_OVERRIDE_LIBRARY_REAL(id_override_new)) {
BLI_assert(ID_IS_OVERRIDE_LIBRARY_REAL(id_override_old));
+ id_override_new->override_library->flag = id_override_old->override_library->flag;
+
/* Copy over overrides rules from old override ID to new one. */
BLI_duplicatelist(&id_override_new->override_library->properties,
&id_override_old->override_library->properties);
@@ -3021,10 +3084,16 @@ bool BKE_lib_override_library_main_operations_create(Main *bmain, const bool for
return create_pool_data.changed;
}
-static bool lib_override_library_id_reset_do(Main *bmain, ID *id_root)
+static bool lib_override_library_id_reset_do(Main *bmain,
+ ID *id_root,
+ const bool do_reset_system_override)
{
bool was_op_deleted = false;
+ if (do_reset_system_override) {
+ id_root->override_library->flag |= IDOVERRIDE_LIBRARY_FLAG_SYSTEM_DEFINED;
+ }
+
LISTBASE_FOREACH_MUTABLE (
IDOverrideLibraryProperty *, op, &id_root->override_library->properties) {
bool do_op_delete = true;
@@ -3080,13 +3149,15 @@ static bool lib_override_library_id_reset_do(Main *bmain, ID *id_root)
return was_op_deleted;
}
-void BKE_lib_override_library_id_reset(Main *bmain, ID *id_root)
+void BKE_lib_override_library_id_reset(Main *bmain,
+ ID *id_root,
+ const bool do_reset_system_override)
{
if (!ID_IS_OVERRIDE_LIBRARY_REAL(id_root)) {
return;
}
- if (lib_override_library_id_reset_do(bmain, id_root)) {
+ if (lib_override_library_id_reset_do(bmain, id_root, do_reset_system_override)) {
if (id_root->override_library->runtime != NULL &&
(id_root->override_library->runtime->tag & IDOVERRIDE_LIBRARY_RUNTIME_TAG_NEEDS_RELOAD) !=
0) {
@@ -3096,7 +3167,9 @@ void BKE_lib_override_library_id_reset(Main *bmain, ID *id_root)
}
}
-static void lib_override_library_id_hierarchy_recursive_reset(Main *bmain, ID *id_root)
+static void lib_override_library_id_hierarchy_recursive_reset(Main *bmain,
+ ID *id_root,
+ const bool do_reset_system_override)
{
if (!ID_IS_OVERRIDE_LIBRARY_REAL(id_root)) {
return;
@@ -3105,7 +3178,7 @@ static void lib_override_library_id_hierarchy_recursive_reset(Main *bmain, ID *i
void **entry_vp = BLI_ghash_lookup_p(bmain->relations->relations_from_pointers, id_root);
if (entry_vp == NULL) {
/* This ID is not used by nor using any other ID. */
- lib_override_library_id_reset_do(bmain, id_root);
+ lib_override_library_id_reset_do(bmain, id_root, do_reset_system_override);
return;
}
@@ -3115,7 +3188,7 @@ static void lib_override_library_id_hierarchy_recursive_reset(Main *bmain, ID *i
return;
}
- lib_override_library_id_reset_do(bmain, id_root);
+ lib_override_library_id_reset_do(bmain, id_root, do_reset_system_override);
/* This way we won't process again that ID, should we encounter it again through another
* relationship hierarchy. */
@@ -3132,17 +3205,19 @@ static void lib_override_library_id_hierarchy_recursive_reset(Main *bmain, ID *i
if (*to_id_entry->id_pointer.to != NULL) {
ID *to_id = *to_id_entry->id_pointer.to;
if (to_id->override_library != NULL) {
- lib_override_library_id_hierarchy_recursive_reset(bmain, to_id);
+ lib_override_library_id_hierarchy_recursive_reset(bmain, to_id, do_reset_system_override);
}
}
}
}
-void BKE_lib_override_library_id_hierarchy_reset(Main *bmain, ID *id_root)
+void BKE_lib_override_library_id_hierarchy_reset(Main *bmain,
+ ID *id_root,
+ const bool do_reset_system_override)
{
BKE_main_relations_create(bmain, 0);
- lib_override_library_id_hierarchy_recursive_reset(bmain, id_root);
+ lib_override_library_id_hierarchy_recursive_reset(bmain, id_root, do_reset_system_override);
BKE_main_relations_free(bmain);
diff --git a/source/blender/blenkernel/intern/lib_override_proxy_conversion.c b/source/blender/blenkernel/intern/lib_override_proxy_conversion.c
index dc164313788..5e9d8e8c4d0 100644
--- a/source/blender/blenkernel/intern/lib_override_proxy_conversion.c
+++ b/source/blender/blenkernel/intern/lib_override_proxy_conversion.c
@@ -62,6 +62,7 @@ bool BKE_lib_override_library_proxy_convert(Main *bmain,
ob_proxy->proxy->id.tag |= LIB_TAG_DOIT;
ob_proxy->proxy->id.newid = &ob_proxy->id;
BKE_lib_override_library_init(&ob_proxy->id, &ob_proxy->proxy->id);
+ ob_proxy->id.override_library->flag &= ~IDOVERRIDE_LIBRARY_FLAG_SYSTEM_DEFINED;
ob_proxy->proxy->proxy_from = NULL;
ob_proxy->proxy = ob_proxy->proxy_group = NULL;
diff --git a/source/blender/blenkernel/intern/mesh_convert.cc b/source/blender/blenkernel/intern/mesh_convert.cc
index fc484e73967..bf9525d5c90 100644
--- a/source/blender/blenkernel/intern/mesh_convert.cc
+++ b/source/blender/blenkernel/intern/mesh_convert.cc
@@ -910,20 +910,18 @@ static void curve_to_mesh_eval_ensure(Object &object)
*
* So we create temporary copy of the object which will use same data as the original bevel, but
* will have no modifiers. */
- Object bevel_object;
- blender::dna::zero_memory(bevel_object);
+ Object bevel_object = blender::dna::shallow_zero_initialize<Object>();
if (curve.bevobj != nullptr) {
- blender::dna::copy_memory(bevel_object, *curve.bevobj);
+ bevel_object = blender::dna::shallow_copy(*curve.bevobj);
BLI_listbase_clear(&bevel_object.modifiers);
BKE_object_runtime_reset(&bevel_object);
curve.bevobj = &bevel_object;
}
/* Same thing for taper. */
- Object taper_object;
- blender::dna::zero_memory(taper_object);
+ Object taper_object = blender::dna::shallow_zero_initialize<Object>();
if (curve.taperobj != nullptr) {
- blender::dna::copy_memory(taper_object, *curve.taperobj);
+ taper_object = blender::dna::shallow_copy(*curve.taperobj);
BLI_listbase_clear(&taper_object.modifiers);
BKE_object_runtime_reset(&taper_object);
curve.taperobj = &taper_object;
@@ -1067,8 +1065,7 @@ static Mesh *mesh_new_from_mesh_object_with_layers(Depsgraph *depsgraph,
return nullptr;
}
- Object object_for_eval;
- blender::dna::zero_memory(object_for_eval);
+ Object object_for_eval = blender::dna::shallow_copy(*object);
if (object_for_eval.runtime.data_orig != nullptr) {
object_for_eval.data = object_for_eval.runtime.data_orig;
}
diff --git a/source/blender/blenkernel/intern/mesh_normals.cc b/source/blender/blenkernel/intern/mesh_normals.cc
index 4448bedb57a..ba1004e8371 100644
--- a/source/blender/blenkernel/intern/mesh_normals.cc
+++ b/source/blender/blenkernel/intern/mesh_normals.cc
@@ -532,7 +532,7 @@ void BKE_lnor_spacearr_init(MLoopNorSpaceArray *lnors_spacearr,
lnors_spacearr->loops_pool = (LinkNode *)BLI_memarena_alloc(
mem, sizeof(LinkNode) * (size_t)numLoops);
- lnors_spacearr->num_spaces = 0;
+ lnors_spacearr->spaces_num = 0;
}
BLI_assert(ELEM(data_type, MLNOR_SPACEARR_BMLOOP_PTR, MLNOR_SPACEARR_LOOP_INDEX));
lnors_spacearr->data_type = data_type;
@@ -550,7 +550,7 @@ void BKE_lnor_spacearr_tls_join(MLoopNorSpaceArray *lnors_spacearr,
{
BLI_assert(lnors_spacearr->data_type == lnors_spacearr_tls->data_type);
BLI_assert(lnors_spacearr->mem != lnors_spacearr_tls->mem);
- lnors_spacearr->num_spaces += lnors_spacearr_tls->num_spaces;
+ lnors_spacearr->spaces_num += lnors_spacearr_tls->spaces_num;
BLI_memarena_merge(lnors_spacearr->mem, lnors_spacearr_tls->mem);
BLI_memarena_free(lnors_spacearr_tls->mem);
lnors_spacearr_tls->mem = nullptr;
@@ -559,7 +559,7 @@ void BKE_lnor_spacearr_tls_join(MLoopNorSpaceArray *lnors_spacearr,
void BKE_lnor_spacearr_clear(MLoopNorSpaceArray *lnors_spacearr)
{
- lnors_spacearr->num_spaces = 0;
+ lnors_spacearr->spaces_num = 0;
lnors_spacearr->lspacearr = nullptr;
lnors_spacearr->loops_pool = nullptr;
if (lnors_spacearr->mem != nullptr) {
@@ -569,7 +569,7 @@ void BKE_lnor_spacearr_clear(MLoopNorSpaceArray *lnors_spacearr)
void BKE_lnor_spacearr_free(MLoopNorSpaceArray *lnors_spacearr)
{
- lnors_spacearr->num_spaces = 0;
+ lnors_spacearr->spaces_num = 0;
lnors_spacearr->lspacearr = nullptr;
lnors_spacearr->loops_pool = nullptr;
BLI_memarena_free(lnors_spacearr->mem);
@@ -578,7 +578,7 @@ void BKE_lnor_spacearr_free(MLoopNorSpaceArray *lnors_spacearr)
MLoopNorSpace *BKE_lnor_space_create(MLoopNorSpaceArray *lnors_spacearr)
{
- lnors_spacearr->num_spaces++;
+ lnors_spacearr->spaces_num++;
return (MLoopNorSpace *)BLI_memarena_calloc(lnors_spacearr->mem, sizeof(MLoopNorSpace));
}
diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c
index 5af8dfc2b72..395deeda4ad 100644
--- a/source/blender/blenkernel/intern/modifier.c
+++ b/source/blender/blenkernel/intern/modifier.c
@@ -233,11 +233,11 @@ bool BKE_modifier_unique_name(ListBase *modifiers, ModifierData *md)
return false;
}
-bool BKE_modifier_depends_ontime(Scene *scene, ModifierData *md, const int dag_eval_mode)
+bool BKE_modifier_depends_ontime(Scene *scene, ModifierData *md)
{
const ModifierTypeInfo *mti = BKE_modifier_get_info(md->type);
- return mti->dependsOnTime && mti->dependsOnTime(scene, md, dag_eval_mode);
+ return mti->dependsOnTime && mti->dependsOnTime(scene, md);
}
bool BKE_modifier_supports_mapping(ModifierData *md)
diff --git a/source/blender/blenkernel/intern/object.cc b/source/blender/blenkernel/intern/object.cc
index 098b7c52664..833e6f882f1 100644
--- a/source/blender/blenkernel/intern/object.cc
+++ b/source/blender/blenkernel/intern/object.cc
@@ -54,6 +54,7 @@
#include "BLI_linklist.h"
#include "BLI_listbase.h"
#include "BLI_math.h"
+#include "BLI_math_vec_types.hh"
#include "BLI_threads.h"
#include "BLI_utildefines.h"
@@ -143,6 +144,8 @@
#include "CCGSubSurf.h"
#include "atomic_ops.h"
+using blender::float3;
+
static CLG_LogRef LOG = {"bke.object"};
/**
@@ -257,6 +260,10 @@ static void object_copy_data(Main *bmain, ID *id_dst, const ID *id_src, const in
else {
ob_dst->preview = nullptr;
}
+
+ if (ob_src->lightgroup) {
+ ob_dst->lightgroup = (LightgroupMembership *)MEM_dupallocN(ob_src->lightgroup);
+ }
}
static void object_free_data(ID *id)
@@ -307,6 +314,8 @@ static void object_free_data(ID *id)
}
BKE_previewimg_free(&ob->preview);
+
+ MEM_SAFE_FREE(ob->lightgroup);
}
static void library_foreach_modifiersForeachIDLink(void *user_data,
@@ -581,6 +590,10 @@ static void object_blend_write(BlendWriter *writer, ID *id, const void *id_addre
BLO_write_struct_list(writer, LinkData, &ob->pc_ids);
BKE_previewimg_blend_write(writer, ob->preview);
+
+ if (ob->lightgroup) {
+ BLO_write_struct(writer, LightgroupMembership, ob->lightgroup);
+ }
}
/* XXX deprecated - old animation system */
@@ -766,7 +779,7 @@ static void object_blend_read_data(BlendDataReader *reader, ID *id)
hmd->indexar = hook->indexar;
hmd->object = hook->parent;
memcpy(hmd->parentinv, hook->parentinv, sizeof(hmd->parentinv));
- hmd->totindex = hook->totindex;
+ hmd->indexar_num = hook->totindex;
BLI_addhead(&ob->modifiers, hmd);
BLI_remlink(&ob->hooks, hook);
@@ -797,6 +810,8 @@ static void object_blend_read_data(BlendDataReader *reader, ID *id)
BLO_read_data_address(reader, &ob->preview);
BKE_previewimg_blend_read(reader, ob->preview);
+
+ BLO_read_data_address(reader, &ob->lightgroup);
}
/* XXX deprecated - old animation system */
@@ -1172,7 +1187,7 @@ static void object_lib_override_apply_post(ID *id_dst, ID *id_src)
static IDProperty *object_asset_dimensions_property(Object *ob)
{
- float dimensions[3];
+ float3 dimensions;
BKE_object_dimensions_get(ob, dimensions);
if (is_zero_v3(dimensions)) {
return nullptr;
@@ -1236,7 +1251,7 @@ IDTypeInfo IDType_ID_OB = {
void BKE_object_workob_clear(Object *workob)
{
- blender::dna::zero_memory(*workob);
+ *workob = blender::dna::shallow_zero_initialize<Object>();
workob->scale[0] = workob->scale[1] = workob->scale[2] = 1.0f;
workob->dscale[0] = workob->dscale[1] = workob->dscale[2] = 1.0f;
@@ -2217,7 +2232,7 @@ Object *BKE_object_add_only_object(Main *bmain, int type, const char *name)
}
/* We cannot use #BKE_id_new here as we need some custom initialization code. */
- Object *ob = (Object *)BKE_libblock_alloc(bmain, ID_OB, name, 0);
+ Object *ob = (Object *)BKE_libblock_alloc(bmain, ID_OB, name, bmain ? 0 : LIB_ID_CREATE_NO_MAIN);
/* We increase object user count when linking to Collections. */
id_us_min(&ob->id);
@@ -2837,7 +2852,7 @@ void BKE_object_obdata_size_init(struct Object *ob, const float size)
void BKE_object_scale_to_mat3(Object *ob, float mat[3][3])
{
- float vec[3];
+ float3 vec;
mul_v3_v3v3(vec, ob->scale, ob->dscale);
size_to_mat3(mat, vec);
}
@@ -3119,7 +3134,7 @@ static bool ob_parcurve(Object *ob, Object *par, float r_mat[4][4])
static void ob_parbone(Object *ob, Object *par, float r_mat[4][4])
{
- float vec[3];
+ float3 vec;
if (par->type != OB_ARMATURE) {
unit_m4(r_mat);
@@ -3540,11 +3555,8 @@ void BKE_object_apply_mat4(Object *ob,
BoundBox *BKE_boundbox_alloc_unit()
{
- const float min[3] = {-1.0f, -1.0f, -1.0f}, max[3] = {1.0f, 1.0f, 1.0f};
-
- BoundBox *bb = MEM_cnew<BoundBox>("OB-BoundBox");
- BKE_boundbox_init_from_minmax(bb, min, max);
-
+ BoundBox *bb = MEM_cnew<BoundBox>(__func__);
+ BKE_boundbox_init_from_minmax(bb, float3(-1), float3(1));
return bb;
}
@@ -3587,7 +3599,7 @@ void BKE_boundbox_minmax(const BoundBox *bb,
}
}
-BoundBox *BKE_object_boundbox_get(Object *ob)
+const BoundBox *BKE_object_boundbox_get(Object *ob)
{
BoundBox *bb = nullptr;
@@ -3627,28 +3639,14 @@ BoundBox *BKE_object_boundbox_get(Object *ob)
return bb;
}
-void BKE_object_boundbox_flag(Object *ob, int flag, const bool set)
-{
- BoundBox *bb = BKE_object_boundbox_get(ob);
- if (bb) {
- if (set) {
- bb->flag |= flag;
- }
- else {
- bb->flag &= ~flag;
- }
- }
-}
-
void BKE_object_boundbox_calc_from_mesh(Object *ob, const Mesh *me_eval)
{
- float min[3], max[3];
-
- INIT_MINMAX(min, max);
+ float3 min(FLT_MAX);
+ float3 max(-FLT_MAX);
if (!BKE_mesh_wrapper_minmax(me_eval, min, max)) {
- zero_v3(min);
- zero_v3(max);
+ min = float3(0);
+ max = float3(0);
}
if (ob->runtime.bb == nullptr) {
@@ -3662,19 +3660,19 @@ void BKE_object_boundbox_calc_from_mesh(Object *ob, const Mesh *me_eval)
bool BKE_object_boundbox_calc_from_evaluated_geometry(Object *ob)
{
- blender::float3 min, max;
- INIT_MINMAX(min, max);
+ float3 min(FLT_MAX);
+ float3 max(-FLT_MAX);
if (ob->runtime.geometry_set_eval) {
if (!ob->runtime.geometry_set_eval->compute_boundbox_without_instances(&min, &max)) {
- zero_v3(min);
- zero_v3(max);
+ min = float3(0);
+ max = float3(0);
}
}
else if (const Mesh *mesh_eval = BKE_object_get_evaluated_mesh(ob)) {
if (!BKE_mesh_wrapper_minmax(mesh_eval, min, max)) {
- zero_v3(min);
- zero_v3(max);
+ min = float3(0);
+ max = float3(0);
}
}
else if (ob->runtime.curve_cache) {
@@ -3705,10 +3703,9 @@ bool BKE_object_boundbox_calc_from_evaluated_geometry(Object *ob)
void BKE_object_dimensions_get(Object *ob, float r_vec[3])
{
- BoundBox *bb = BKE_object_boundbox_get(ob);
+ const BoundBox *bb = BKE_object_boundbox_get(ob);
if (bb) {
- float scale[3];
-
+ float3 scale;
mat4_to_size(scale, ob->obmat);
r_vec[0] = fabsf(scale[0]) * (bb->vec[4][0] - bb->vec[0][0]);
@@ -3726,13 +3723,12 @@ void BKE_object_dimensions_set_ex(Object *ob,
const float ob_scale_orig[3],
const float ob_obmat_orig[4][4])
{
- BoundBox *bb = BKE_object_boundbox_get(ob);
+ const BoundBox *bb = BKE_object_boundbox_get(ob);
if (bb) {
- float len[3];
-
- len[0] = bb->vec[4][0] - bb->vec[0][0];
- len[1] = bb->vec[2][1] - bb->vec[0][1];
- len[2] = bb->vec[1][2] - bb->vec[0][2];
+ float3 len;
+ len.x = bb->vec[4][0] - bb->vec[0][0];
+ len.y = bb->vec[2][1] - bb->vec[0][1];
+ len.z = bb->vec[1][2] - bb->vec[0][2];
for (int i = 0; i < 3; i++) {
if (((1 << i) & axis_mask) == 0) {
@@ -3760,26 +3756,25 @@ void BKE_object_dimensions_set(Object *ob, const float value[3], int axis_mask)
void BKE_object_minmax(Object *ob, float r_min[3], float r_max[3], const bool use_hidden)
{
- float vec[3];
bool changed = false;
switch (ob->type) {
case OB_CURVES_LEGACY:
case OB_FONT:
case OB_SURF: {
- BoundBox bb = *BKE_curve_boundbox_get(ob);
+ const BoundBox bb = *BKE_curve_boundbox_get(ob);
BKE_boundbox_minmax(&bb, ob->obmat, r_min, r_max);
changed = true;
break;
}
case OB_MESH: {
- BoundBox bb = *BKE_mesh_boundbox_get(ob);
+ const BoundBox bb = *BKE_mesh_boundbox_get(ob);
BKE_boundbox_minmax(&bb, ob->obmat, r_min, r_max);
changed = true;
break;
}
case OB_GPENCIL: {
- BoundBox bb = *BKE_gpencil_boundbox_get(ob);
+ const BoundBox bb = *BKE_gpencil_boundbox_get(ob);
BKE_boundbox_minmax(&bb, ob->obmat, r_min, r_max);
changed = true;
break;
@@ -3792,6 +3787,7 @@ void BKE_object_minmax(Object *ob, float r_min[3], float r_max[3], const bool us
for (w = 0; w < lt->pntsw; w++) {
for (v = 0; v < lt->pntsv; v++) {
for (u = 0; u < lt->pntsu; u++, bp++) {
+ float3 vec;
mul_v3_m4v3(vec, ob->obmat, bp->vec);
minmax_v3v3_v3(r_min, r_max, vec);
}
@@ -3815,20 +3811,20 @@ void BKE_object_minmax(Object *ob, float r_min[3], float r_max[3], const bool us
break;
}
case OB_CURVES: {
- BoundBox bb = *BKE_curves_boundbox_get(ob);
+ const BoundBox bb = *BKE_curves_boundbox_get(ob);
BKE_boundbox_minmax(&bb, ob->obmat, r_min, r_max);
changed = true;
break;
}
case OB_POINTCLOUD: {
- BoundBox bb = *BKE_pointcloud_boundbox_get(ob);
+ const BoundBox bb = *BKE_pointcloud_boundbox_get(ob);
BKE_boundbox_minmax(&bb, ob->obmat, r_min, r_max);
changed = true;
break;
}
case OB_VOLUME: {
- BoundBox bb = *BKE_volume_boundbox_get(ob);
+ const BoundBox bb = *BKE_volume_boundbox_get(ob);
BKE_boundbox_minmax(&bb, ob->obmat, r_min, r_max);
changed = true;
break;
@@ -3836,15 +3832,16 @@ void BKE_object_minmax(Object *ob, float r_min[3], float r_max[3], const bool us
}
if (changed == false) {
- float size[3];
+ float3 size = ob->scale;
copy_v3_v3(size, ob->scale);
if (ob->type == OB_EMPTY) {
- mul_v3_fl(size, ob->empty_drawsize);
+ size *= ob->empty_drawsize;
}
minmax_v3v3_v3(r_min, r_max, ob->obmat[3]);
+ float3 vec;
copy_v3_v3(vec, ob->obmat[3]);
add_v3_v3(vec, size);
minmax_v3v3_v3(r_min, r_max, vec);
@@ -3895,7 +3892,7 @@ bool BKE_object_empty_image_data_is_visible_in_view3d(const Object *ob, const Re
/* NOTE: we could normalize the 'view_dir' then use 'eps'
* however the issue with empty objects being visible when viewed from the side
* is only noticeable in orthographic views. */
- float view_dir[3];
+ float3 view_dir;
sub_v3_v3v3(view_dir, rv3d->viewinv[3], ob->obmat[3]);
dot = dot_v3v3(ob->obmat[2], view_dir);
eps = 0.0f;
@@ -3917,7 +3914,7 @@ bool BKE_object_empty_image_data_is_visible_in_view3d(const Object *ob, const Re
}
if (visibility_flag & OB_EMPTY_IMAGE_HIDE_NON_AXIS_ALIGNED) {
- float proj[3];
+ float3 proj;
project_plane_v3_v3v3(proj, ob->obmat[2], rv3d->viewinv[2]);
const float proj_length_sq = len_squared_v3(proj);
if (proj_length_sq > 1e-5f) {
@@ -3950,12 +3947,12 @@ bool BKE_object_minmax_dupli(Depsgraph *depsgraph,
/* Do not modify the original boundbox. */
temp_ob.runtime.bb = nullptr;
BKE_object_replace_data_on_shallow_copy(&temp_ob, dob->ob_data);
- BoundBox *bb = BKE_object_boundbox_get(&temp_ob);
+ const BoundBox *bb = BKE_object_boundbox_get(&temp_ob);
if (bb) {
int i;
for (i = 0; i < 8; i++) {
- float vec[3];
+ float3 vec;
mul_v3_m4v3(vec, dob->mat, bb->vec[i]);
minmax_v3v3_v3(r_min, r_max, vec);
}
@@ -3988,7 +3985,7 @@ static void foreach_display_point_gpencil_stroke_fn(bGPDlayer *UNUSED(layer),
bGPDspoint *pt;
int i;
for (i = 0, pt = stroke->points; i < stroke->totpoints; i++, pt++) {
- float co[3];
+ float3 co;
mul_v3_m4v3(co, iter_data->obmat, &pt->x);
iter_data->point_func_cb(co, iter_data->user_data);
}
@@ -4000,9 +3997,9 @@ void BKE_object_foreach_display_point(Object *ob,
void (*func_cb)(const float[3], void *),
void *user_data)
{
- /* TODO: pointcloud and hair objects support */
+ /* TODO: pointcloud and curves object support */
const Mesh *mesh_eval = BKE_object_get_evaluated_mesh(ob);
- float co[3];
+ float3 co;
if (mesh_eval != nullptr) {
const MVert *mv = mesh_eval->mvert;
@@ -5236,12 +5233,9 @@ KDTree_3d *BKE_object_as_kdtree(Object *ob, int *r_tot)
/** \name Object Modifier Utilities
* \{ */
-bool BKE_object_modifier_use_time(Scene *scene,
- Object *ob,
- ModifierData *md,
- const int dag_eval_mode)
+bool BKE_object_modifier_use_time(Scene *scene, Object *ob, ModifierData *md)
{
- if (BKE_modifier_depends_ontime(scene, md, dag_eval_mode)) {
+ if (BKE_modifier_depends_ontime(scene, md)) {
return true;
}
diff --git a/source/blender/blenkernel/intern/object_dupli.cc b/source/blender/blenkernel/intern/object_dupli.cc
index 009a7bd70be..327035971d5 100644
--- a/source/blender/blenkernel/intern/object_dupli.cc
+++ b/source/blender/blenkernel/intern/object_dupli.cc
@@ -766,68 +766,6 @@ static const DupliGenerator gen_dupli_verts_font = {
/** \} */
/* -------------------------------------------------------------------- */
-/** \name Dupli-Vertices Implementation (#OB_DUPLIVERTS for #PointCloud)
- * \{ */
-
-static void make_child_duplis_pointcloud(const DupliContext *ctx,
- void *UNUSED(userdata),
- Object *child)
-{
- const Object *parent = ctx->object;
- const PointCloud *pointcloud = (PointCloud *)parent->data;
- const float(*co)[3] = pointcloud->co;
- const float *radius = pointcloud->radius;
- const float(*rotation)[4] = nullptr; /* TODO: add optional rotation attribute. */
- const float(*orco)[3] = nullptr; /* TODO: add optional texture coordinate attribute. */
-
- /* Relative transform from parent to child space. */
- float child_imat[4][4];
- mul_m4_m4m4(child_imat, child->imat, parent->obmat);
-
- for (int i = 0; i < pointcloud->totpoint; i++) {
- /* Transform matrix from point position, radius and rotation. */
- float quat[4] = {1.0f, 0.0f, 0.0f, 0.0f};
- float size[3] = {1.0f, 1.0f, 1.0f};
- if (radius) {
- copy_v3_fl(size, radius[i]);
- }
- if (rotation) {
- copy_v4_v4(quat, rotation[i]);
- }
-
- float space_mat[4][4];
- loc_quat_size_to_mat4(space_mat, co[i], quat, size);
-
- /* Make offset relative to child object using relative child transform,
- * and apply object matrix after local vertex transform. */
- mul_mat3_m4_v3(child_imat, space_mat[3]);
-
- /* Create dupli object. */
- float obmat[4][4];
- mul_m4_m4m4(obmat, child->obmat, space_mat);
- DupliObject *dob = make_dupli(ctx, child, obmat, i);
- if (orco) {
- copy_v3_v3(dob->orco, orco[i]);
- }
-
- /* Recursion. */
- make_recursive_duplis(ctx, child, space_mat, i);
- }
-}
-
-static void make_duplis_pointcloud(const DupliContext *ctx)
-{
- make_child_duplis(ctx, nullptr, make_child_duplis_pointcloud);
-}
-
-static const DupliGenerator gen_dupli_verts_pointcloud = {
- OB_DUPLIVERTS, /* type */
- make_duplis_pointcloud /* make_duplis */
-};
-
-/** \} */
-
-/* -------------------------------------------------------------------- */
/** \name Instances Geometry Component Implementation
* \{ */
@@ -1654,9 +1592,6 @@ static const DupliGenerator *get_dupli_generator(const DupliContext *ctx)
if (ctx->object->type == OB_MESH) {
return &gen_dupli_verts;
}
- if (ctx->object->type == OB_POINTCLOUD) {
- return &gen_dupli_verts_pointcloud;
- }
}
else if (transflag & OB_DUPLIFACES) {
if (ctx->object->type == OB_MESH) {
diff --git a/source/blender/blenkernel/intern/object_update.c b/source/blender/blenkernel/intern/object_update.c
index 3bc2139ca0c..fbbd429f58a 100644
--- a/source/blender/blenkernel/intern/object_update.c
+++ b/source/blender/blenkernel/intern/object_update.c
@@ -243,7 +243,7 @@ void BKE_object_handle_data_update(Depsgraph *depsgraph, Scene *scene, Object *o
/** Bounding box from evaluated geometry. */
static void object_sync_boundbox_to_original(Object *object_orig, Object *object_eval)
{
- BoundBox *bb = object_eval->runtime.bb;
+ const BoundBox *bb = object_eval->runtime.bb;
if (!bb || (bb->flag & BOUNDBOX_DIRTY)) {
BKE_object_boundbox_calc_from_evaluated_geometry(object_eval);
}
diff --git a/source/blender/blenkernel/intern/rigidbody.c b/source/blender/blenkernel/intern/rigidbody.c
index c21b525f628..60cc4ce83af 100644
--- a/source/blender/blenkernel/intern/rigidbody.c
+++ b/source/blender/blenkernel/intern/rigidbody.c
@@ -473,7 +473,6 @@ static rbCollisionShape *rigidbody_validate_sim_shape_helper(RigidBodyWorld *rbw
{
RigidBodyOb *rbo = ob->rigidbody_object;
rbCollisionShape *new_shape = NULL;
- BoundBox *bb = NULL;
float size[3] = {1.0f, 1.0f, 1.0f};
float radius = 1.0f;
float height = 1.0f;
@@ -494,7 +493,7 @@ static rbCollisionShape *rigidbody_validate_sim_shape_helper(RigidBodyWorld *rbw
*/
/* XXX: all dimensions are auto-determined now... later can add stored settings for this */
/* get object dimensions without scaling */
- bb = BKE_object_boundbox_get(ob);
+ const BoundBox *bb = BKE_object_boundbox_get(ob);
if (bb) {
size[0] = (bb->vec[4][0] - bb->vec[0][0]);
size[1] = (bb->vec[2][1] - bb->vec[0][1]);
@@ -1678,7 +1677,7 @@ static void rigidbody_update_sim_ob(
if (mesh) {
MVert *mvert = mesh->mvert;
int totvert = mesh->totvert;
- BoundBox *bb = BKE_object_boundbox_get(ob);
+ const BoundBox *bb = BKE_object_boundbox_get(ob);
RB_shape_trimesh_update(rbo->shared->physics_shape,
(float *)mvert,
diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.cc
index b98c82e365e..685d24cee38 100644
--- a/source/blender/blenkernel/intern/scene.c
+++ b/source/blender/blenkernel/intern/scene.cc
@@ -8,9 +8,9 @@
/* Allow using deprecated functionality for .blend file I/O. */
#define DNA_DEPRECATED_ALLOW
-#include <stddef.h>
-#include <stdio.h>
-#include <string.h>
+#include <cstddef>
+#include <cstdio>
+#include <cstring>
#include "MEM_guardedalloc.h"
@@ -139,7 +139,7 @@ static void scene_init_data(ID *id)
scene->toolsettings->autokey_mode = (uchar)U.autokey_mode;
- /* grease pencil multiframe falloff curve */
+ /* Grease pencil multi-frame falloff curve. */
scene->toolsettings->gp_sculpt.cur_falloff = BKE_curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f);
CurveMapping *gp_falloff_curve = scene->toolsettings->gp_sculpt.cur_falloff;
BKE_curvemapping_init(gp_falloff_curve);
@@ -183,11 +183,11 @@ static void scene_init_data(ID *id)
/* multiview - stereo */
BKE_scene_add_render_view(scene, STEREO_LEFT_NAME);
- srv = scene->r.views.first;
+ srv = static_cast<SceneRenderView *>(scene->r.views.first);
BLI_strncpy(srv->suffix, STEREO_LEFT_SUFFIX, sizeof(srv->suffix));
BKE_scene_add_render_view(scene, STEREO_RIGHT_NAME);
- srv = scene->r.views.last;
+ srv = static_cast<SceneRenderView *>(scene->r.views.last);
BLI_strncpy(srv->suffix, STEREO_RIGHT_SUFFIX, sizeof(srv->suffix));
BKE_sound_reset_scene_runtime(scene);
@@ -218,14 +218,14 @@ static void scene_init_data(ID *id)
/* Master Collection */
scene->master_collection = BKE_collection_master_add();
- BKE_view_layer_add(scene, "ViewLayer", NULL, VIEWLAYER_ADD_NEW);
+ BKE_view_layer_add(scene, "ViewLayer", nullptr, VIEWLAYER_ADD_NEW);
}
static void scene_copy_markers(Scene *scene_dst, const Scene *scene_src, const int flag)
{
BLI_duplicatelist(&scene_dst->markers, &scene_src->markers);
LISTBASE_FOREACH (TimeMarker *, marker, &scene_dst->markers) {
- if (marker->prop != NULL) {
+ if (marker->prop != nullptr) {
marker->prop = IDP_CopyProperty_ex(marker->prop, flag);
}
}
@@ -240,9 +240,9 @@ static void scene_copy_data(Main *bmain, ID *id_dst, const ID *id_src, const int
/* We always need allocation of our private ID data. */
const int flag_private_id_data = flag & ~LIB_ID_CREATE_NO_ALLOCATE;
- scene_dst->ed = NULL;
- scene_dst->depsgraph_hash = NULL;
- scene_dst->fps_info = NULL;
+ scene_dst->ed = nullptr;
+ scene_dst->depsgraph_hash = nullptr;
+ scene_dst->fps_info = nullptr;
/* Master Collection */
if (scene_src->master_collection) {
@@ -254,8 +254,8 @@ static void scene_copy_data(Main *bmain, ID *id_dst, const ID *id_src, const int
/* View Layers */
BLI_duplicatelist(&scene_dst->view_layers, &scene_src->view_layers);
- for (ViewLayer *view_layer_src = scene_src->view_layers.first,
- *view_layer_dst = scene_dst->view_layers.first;
+ for (ViewLayer *view_layer_src = static_cast<ViewLayer *>(scene_src->view_layers.first),
+ *view_layer_dst = static_cast<ViewLayer *>(scene_dst->view_layers.first);
view_layer_src;
view_layer_src = view_layer_src->next, view_layer_dst = view_layer_dst->next) {
BKE_view_layer_copy_data(scene_dst, scene_src, view_layer_dst, view_layer_src, flag_subdata);
@@ -299,7 +299,8 @@ static void scene_copy_data(Main *bmain, ID *id_dst, const ID *id_src, const int
/* make a private copy of the avicodecdata */
if (scene_src->r.avicodecdata) {
- scene_dst->r.avicodecdata = MEM_dupallocN(scene_src->r.avicodecdata);
+ scene_dst->r.avicodecdata = static_cast<AviCodecData *>(
+ MEM_dupallocN(scene_src->r.avicodecdata));
scene_dst->r.avicodecdata->lpFormat = MEM_dupallocN(scene_dst->r.avicodecdata->lpFormat);
scene_dst->r.avicodecdata->lpParms = MEM_dupallocN(scene_dst->r.avicodecdata->lpParms);
}
@@ -312,7 +313,7 @@ static void scene_copy_data(Main *bmain, ID *id_dst, const ID *id_src, const int
/* Copy sequencer, this is local data! */
if (scene_src->ed) {
- scene_dst->ed = MEM_callocN(sizeof(*scene_dst->ed), __func__);
+ scene_dst->ed = MEM_cnew<Editing>(__func__);
scene_dst->ed->seqbasep = &scene_dst->ed->seqbase;
SEQ_sequence_base_dupli_recursive(scene_src,
scene_dst,
@@ -326,7 +327,7 @@ static void scene_copy_data(Main *bmain, ID *id_dst, const ID *id_src, const int
BKE_previewimg_id_copy(&scene_dst->id, &scene_src->id);
}
else {
- scene_dst->preview = NULL;
+ scene_dst->preview = nullptr;
}
BKE_scene_copy_data_eevee(scene_dst, scene_src);
@@ -335,7 +336,7 @@ static void scene_copy_data(Main *bmain, ID *id_dst, const ID *id_src, const int
static void scene_free_markers(Scene *scene, bool do_id_user)
{
LISTBASE_FOREACH_MUTABLE (TimeMarker *, marker, &scene->markers) {
- if (marker->prop != NULL) {
+ if (marker->prop != nullptr) {
IDP_FreePropertyContent_ex(marker->prop, do_id_user);
MEM_freeN(marker->prop);
}
@@ -357,22 +358,22 @@ static void scene_free_data(ID *id)
if (scene->nodetree) {
ntreeFreeEmbeddedTree(scene->nodetree);
MEM_freeN(scene->nodetree);
- scene->nodetree = NULL;
+ scene->nodetree = nullptr;
}
if (scene->rigidbody_world) {
/* Prevent rigidbody freeing code to follow other IDs pointers, this should never be allowed
* nor necessary from here, and with new undo code, those pointers may be fully invalid or
* worse, pointing to data actually belonging to new BMain! */
- scene->rigidbody_world->constraints = NULL;
- scene->rigidbody_world->group = NULL;
+ scene->rigidbody_world->constraints = nullptr;
+ scene->rigidbody_world->group = nullptr;
BKE_rigidbody_free_world(scene);
}
if (scene->r.avicodecdata) {
free_avicodecdata(scene->r.avicodecdata);
MEM_freeN(scene->r.avicodecdata);
- scene->r.avicodecdata = NULL;
+ scene->r.avicodecdata = nullptr;
}
scene_free_markers(scene, do_id_user);
@@ -380,7 +381,7 @@ static void scene_free_data(ID *id)
BLI_freelistN(&scene->r.views);
BKE_toolsettings_free(scene->toolsettings);
- scene->toolsettings = NULL;
+ scene->toolsettings = nullptr;
BKE_scene_free_depsgraph_hash(scene);
@@ -395,10 +396,7 @@ static void scene_free_data(ID *id)
BKE_previewimg_free(&scene->preview);
BKE_curvemapping_free_data(&scene->r.mblur_shutter_curve);
- for (ViewLayer *view_layer = scene->view_layers.first, *view_layer_next; view_layer;
- view_layer = view_layer_next) {
- view_layer_next = view_layer->next;
-
+ LISTBASE_FOREACH_MUTABLE (ViewLayer *, view_layer, &scene->view_layers) {
BLI_remlink(&scene->view_layers, view_layer);
BKE_view_layer_free_ex(view_layer, do_id_user);
}
@@ -412,21 +410,21 @@ static void scene_free_data(ID *id)
BKE_collection_free_data(scene->master_collection);
BKE_libblock_free_data_py(&scene->master_collection->id);
MEM_freeN(scene->master_collection);
- scene->master_collection = NULL;
+ scene->master_collection = nullptr;
}
if (scene->eevee.light_cache_data) {
EEVEE_lightcache_free(scene->eevee.light_cache_data);
- scene->eevee.light_cache_data = NULL;
+ scene->eevee.light_cache_data = nullptr;
}
if (scene->display.shading.prop) {
IDP_FreeProperty(scene->display.shading.prop);
- scene->display.shading.prop = NULL;
+ scene->display.shading.prop = nullptr;
}
- /* These are freed on doversion. */
- BLI_assert(scene->layer_properties == NULL);
+ /* These are freed on `do_versions`. */
+ BLI_assert(scene->layer_properties == nullptr);
}
static void scene_foreach_rigidbodyworldSceneLooper(struct RigidBodyWorld *UNUSED(rbw),
@@ -443,14 +441,14 @@ static void scene_foreach_rigidbodyworldSceneLooper(struct RigidBodyWorld *UNUSE
* This code is shared by both the regular `foreach_id` looper, and the code trying to restore or
* preserve ID pointers like brushes across undo-steps.
*/
-typedef enum eSceneForeachUndoPreserveProcess {
+enum eSceneForeachUndoPreserveProcess {
/* Undo when preserving tool-settings from old scene, we also want to try to preserve that ID
* pointer from its old scene's value. */
SCENE_FOREACH_UNDO_RESTORE,
/* Undo when preserving tool-settings from old scene, we want to keep the new value of that ID
* pointer. */
SCENE_FOREACH_UNDO_NO_RESTORE,
-} eSceneForeachUndoPreserveProcess;
+};
static void scene_foreach_toolsettings_id_pointer_process(
ID **id_p,
@@ -464,9 +462,10 @@ static void scene_foreach_toolsettings_id_pointer_process(
ID *id_old = *id_old_p;
/* Old data has not been remapped to new values of the pointers, if we want to keep the old
* pointer here we need its new address. */
- ID *id_old_new = id_old != NULL ? BLO_read_get_new_id_address(reader, id_old->lib, id_old) :
- NULL;
- if (id_old_new != NULL) {
+ ID *id_old_new = id_old != nullptr ?
+ BLO_read_get_new_id_address(reader, id_old->lib, id_old) :
+ nullptr;
+ if (id_old_new != nullptr) {
BLI_assert(ELEM(id_old, id_old_new, id_old_new->orig_id));
*id_old_p = id_old_new;
if (cb_flag & IDWALK_CB_USER) {
@@ -489,7 +488,7 @@ static void scene_foreach_toolsettings_id_pointer_process(
/* Special handling is needed here, as `scene_foreach_toolsettings` (and its dependency
* `scene_foreach_paint`) are also used by `scene_undo_preserve`, where `LibraryForeachIDData
- * *data` is NULL. */
+ * *data` is nullptr. */
#define BKE_LIB_FOREACHID_UNDO_PRESERVE_PROCESS_IDSUPER( \
__data, __id, __do_undo_restore, __action, __reader, __id_old, __cb_flag) \
{ \
@@ -498,7 +497,7 @@ static void scene_foreach_toolsettings_id_pointer_process(
(ID **)&(__id), __action, __reader, (ID **)&(__id_old), __cb_flag); \
} \
else { \
- BLI_assert((__data) != NULL); \
+ BLI_assert((__data) != nullptr); \
BKE_LIB_FOREACHID_PROCESS_IDSUPER(__data, __id, __cb_flag); \
} \
} \
@@ -511,7 +510,7 @@ static void scene_foreach_toolsettings_id_pointer_process(
__func_call; \
} \
else { \
- BLI_assert((__data) != NULL); \
+ BLI_assert((__data) != nullptr); \
BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL(__data, __func_call); \
} \
} \
@@ -536,10 +535,10 @@ static void scene_foreach_paint(LibraryForeachIDData *data,
* this is equivalent to simply looping over slots from `paint`.
* - In case we do `undo_restore`, we only want to consider the slots from the old one, since
* those are the one we keep in the end.
- * + In case the new data has less valid slots, we feed in a dummy NULL pointer.
+ * + In case the new data has less valid slots, we feed in a dummy null pointer.
* + In case the new data has more valid slots, the extra ones are ignored.
*/
- Brush *brush_tmp = NULL;
+ Brush *brush_tmp = nullptr;
Brush **brush_p = i < paint->tool_slots_len ? &paint->tool_slots[i].brush : &brush_tmp;
BKE_LIB_FOREACHID_UNDO_PRESERVE_PROCESS_IDSUPER(data,
*brush_p,
@@ -725,7 +724,7 @@ static void scene_foreach_layer_collection(LibraryForeachIDData *data, ListBase
LISTBASE_FOREACH (LayerCollection *, lc, lb) {
/* XXX This is very weak. The whole idea of keeping pointers to private IDs is very bad
* anyway... */
- const int cb_flag = (lc->collection != NULL &&
+ const int cb_flag = (lc->collection != nullptr &&
(lc->collection->id.flag & LIB_EMBEDDED_DATA) != 0) ?
IDWALK_CB_EMBEDDED :
IDWALK_CB_NOP;
@@ -760,7 +759,7 @@ static bool seq_foreach_member_id_cb(Sequence *seq, void *user_data)
}
if (seq->type == SEQ_TYPE_TEXT && seq->effectdata) {
- TextVars *text_data = seq->effectdata;
+ TextVars *text_data = static_cast<TextVars *>(seq->effectdata);
FOREACHID_PROCESS_IDSUPER(data, text_data->text_font, IDWALK_CB_USER);
}
@@ -792,8 +791,8 @@ static void scene_foreach_id(ID *id, LibraryForeachIDData *data)
BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL(data,
BKE_keyingsets_foreach_id(data, &scene->keyingsets));
- /* This pointer can be NULL during old files reading, better be safe than sorry. */
- if (scene->master_collection != NULL) {
+ /* This pointer can be nullptr during old files reading, better be safe than sorry. */
+ if (scene->master_collection != nullptr) {
BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL(
data, BKE_library_foreach_ID_embedded(data, (ID **)&scene->master_collection));
}
@@ -839,7 +838,7 @@ static void scene_foreach_id(ID *id, LibraryForeachIDData *data)
ToolSettings *toolsett = scene->toolsettings;
if (toolsett) {
BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL(
- data, scene_foreach_toolsettings(data, toolsett, false, NULL, toolsett));
+ data, scene_foreach_toolsettings(data, toolsett, false, nullptr, toolsett));
}
if (scene->rigidbody_world) {
@@ -855,11 +854,10 @@ static void scene_foreach_cache(ID *id,
void *user_data)
{
Scene *scene = (Scene *)id;
- IDCacheKey key = {
- .id_session_uuid = id->session_uuid,
- .offset_in_ID = offsetof(Scene, eevee.light_cache_data),
- .cache_v = scene->eevee.light_cache_data,
- };
+ IDCacheKey key{};
+ key.id_session_uuid = id->session_uuid;
+ key.offset_in_ID = offsetof(Scene, eevee.light_cache_data);
+ key.cache_v = scene->eevee.light_cache_data;
function_callback(id,
&key,
@@ -902,7 +900,7 @@ static bool seq_foreach_path_callback(Sequence *seq, void *user_data)
static void scene_foreach_path(ID *id, BPathForeachPathData *bpath_data)
{
Scene *scene = (Scene *)id;
- if (scene->ed != NULL) {
+ if (scene->ed != nullptr) {
SEQ_for_each_callback(&scene->ed->seqbase, seq_foreach_path_callback, bpath_data);
}
}
@@ -969,7 +967,7 @@ static void scene_blend_write(BlendWriter *writer, ID *id, const void *id_addres
if (tos->gp_interpolate.custom_ipo) {
BKE_curvemapping_blend_write(writer, tos->gp_interpolate.custom_ipo);
}
- /* write grease-pencil multiframe falloff curve to file */
+ /* write grease-pencil multi-frame falloff curve to file */
if (tos->gp_sculpt.cur_falloff) {
BKE_curvemapping_blend_write(writer, tos->gp_sculpt.cur_falloff);
}
@@ -1012,7 +1010,7 @@ static void scene_blend_write(BlendWriter *writer, ID *id, const void *id_addres
LISTBASE_FOREACH (TimeMarker *, marker, &sce->markers) {
BLO_write_struct(writer, TimeMarker, marker);
- if (marker->prop != NULL) {
+ if (marker->prop != nullptr) {
IDP_BlendWrite(writer, marker->prop);
}
}
@@ -1060,7 +1058,7 @@ static void scene_blend_write(BlendWriter *writer, ID *id, const void *id_addres
BKE_collection_blend_write_nolib(writer, sce->master_collection);
}
- /* Eevee Lightcache */
+ /* Eevee Light-cache */
if (sce->eevee.light_cache_data && !BLO_write_is_undo(writer)) {
BLO_write_struct(writer, LightCache, sce->eevee.light_cache_data);
EEVEE_lightcache_blend_write(writer, sce->eevee.light_cache_data);
@@ -1068,8 +1066,8 @@ static void scene_blend_write(BlendWriter *writer, ID *id, const void *id_addres
BKE_screen_view3d_shading_blend_write(writer, &sce->display.shading);
- /* Freed on doversion. */
- BLI_assert(sce->layer_properties == NULL);
+ /* Freed on `do_versions()`. */
+ BLI_assert(sce->layer_properties == nullptr);
}
static void direct_link_paint_helper(BlendDataReader *reader, const Scene *scene, Paint **paint)
@@ -1102,8 +1100,8 @@ static void scene_blend_read_data(BlendDataReader *reader, ID *id)
{
Scene *sce = (Scene *)id;
- sce->depsgraph_hash = NULL;
- sce->fps_info = NULL;
+ sce->depsgraph_hash = nullptr;
+ sce->fps_info = nullptr;
memset(&sce->customdata_mask, 0, sizeof(sce->customdata_mask));
memset(&sce->customdata_mask_modal, 0, sizeof(sce->customdata_mask_modal));
@@ -1144,28 +1142,28 @@ static void scene_blend_read_data(BlendDataReader *reader, ID *id)
BKE_paint_blend_read_data(reader, sce, &sce->toolsettings->imapaint.paint);
- sce->toolsettings->particle.paintcursor = NULL;
- sce->toolsettings->particle.scene = NULL;
- sce->toolsettings->particle.object = NULL;
- sce->toolsettings->gp_sculpt.paintcursor = NULL;
+ sce->toolsettings->particle.paintcursor = nullptr;
+ sce->toolsettings->particle.scene = nullptr;
+ sce->toolsettings->particle.object = nullptr;
+ sce->toolsettings->gp_sculpt.paintcursor = nullptr;
- /* relink grease pencil interpolation curves */
+ /* Relink grease pencil interpolation curves. */
BLO_read_data_address(reader, &sce->toolsettings->gp_interpolate.custom_ipo);
if (sce->toolsettings->gp_interpolate.custom_ipo) {
BKE_curvemapping_blend_read(reader, sce->toolsettings->gp_interpolate.custom_ipo);
}
- /* relink grease pencil multiframe falloff curve */
+ /* Relink grease pencil multi-frame falloff curve. */
BLO_read_data_address(reader, &sce->toolsettings->gp_sculpt.cur_falloff);
if (sce->toolsettings->gp_sculpt.cur_falloff) {
BKE_curvemapping_blend_read(reader, sce->toolsettings->gp_sculpt.cur_falloff);
}
- /* relink grease pencil primitive curve */
+ /* Relink grease pencil primitive curve. */
BLO_read_data_address(reader, &sce->toolsettings->gp_sculpt.cur_primitive);
if (sce->toolsettings->gp_sculpt.cur_primitive) {
BKE_curvemapping_blend_read(reader, sce->toolsettings->gp_sculpt.cur_primitive);
}
- /* Relink toolsettings curve profile */
+ /* Relink toolsettings curve profile. */
BLO_read_data_address(reader, &sce->toolsettings->custom_bevel_profile_preset);
if (sce->toolsettings->custom_bevel_profile_preset) {
BKE_curveprofile_blend_read(reader, sce->toolsettings->custom_bevel_profile_preset);
@@ -1181,9 +1179,9 @@ static void scene_blend_read_data(BlendDataReader *reader, ID *id)
Editing *ed = sce->ed;
BLO_read_data_address(reader, &ed->act_seq);
- ed->cache = NULL;
- ed->prefetch_job = NULL;
- ed->runtime.sequence_lookup = NULL;
+ ed->cache = nullptr;
+ ed->prefetch_job = nullptr;
+ ed->runtime.sequence_lookup = nullptr;
/* recursive link sequences, lb will be correctly initialized */
link_recurs_seq(reader, &ed->seqbase);
@@ -1275,9 +1273,9 @@ static void scene_blend_read_data(BlendDataReader *reader, ID *id)
if (rbw) {
BLO_read_data_address(reader, &rbw->shared);
- if (rbw->shared == NULL) {
+ if (rbw->shared == nullptr) {
/* Link deprecated caches if they exist, so we can use them for versioning.
- * We should only do this when rbw->shared == NULL, because those pointers
+ * We should only do this when rbw->shared == nullptr, because those pointers
* are always set (for compatibility with older Blenders). We mustn't link
* the same pointcache twice. */
BKE_ptcache_blend_read_data(reader, &rbw->ptcaches, &rbw->pointcache, false);
@@ -1291,7 +1289,7 @@ static void scene_blend_read_data(BlendDataReader *reader, ID *id)
/* must nullify the reference to physics sim object, since it no-longer exist
* (and will need to be recalculated)
*/
- rbw->shared->physics_world = NULL;
+ rbw->shared->physics_world = nullptr;
/* link caches */
BKE_ptcache_blend_read_data(reader, &rbw->shared->ptcaches, &rbw->shared->pointcache, false);
@@ -1301,13 +1299,13 @@ static void scene_blend_read_data(BlendDataReader *reader, ID *id)
rbw->ltime = (float)rbw->shared->pointcache->startframe;
}
}
- rbw->objects = NULL;
+ rbw->objects = nullptr;
rbw->numbodies = 0;
/* set effector weights */
BLO_read_data_address(reader, &rbw->effector_weights);
if (!rbw->effector_weights) {
- rbw->effector_weights = BKE_effector_add_weights(NULL);
+ rbw->effector_weights = BKE_effector_add_weights(nullptr);
}
}
@@ -1352,7 +1350,7 @@ static void scene_blend_read_data(BlendDataReader *reader, ID *id)
static void composite_patch(bNodeTree *ntree, Scene *scene)
{
LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
- if (node->id == NULL &&
+ if (node->id == nullptr &&
((node->type == CMP_NODE_R_LAYERS) ||
(node->type == CMP_NODE_CRYPTOMATTE && node->custom1 == CMP_CRYPTOMATTE_SRC_RENDER))) {
node->id = &scene->id;
@@ -1423,14 +1421,14 @@ static void scene_blend_read_lib(BlendLibReader *reader, ID *id)
LISTBASE_FOREACH_MUTABLE (Base *, base_legacy, &sce->base) {
BLO_read_id_address(reader, sce->id.lib, &base_legacy->object);
- if (base_legacy->object == NULL) {
+ if (base_legacy->object == nullptr) {
BLO_reportf_wrap(BLO_read_lib_reports(reader),
RPT_WARNING,
TIP_("LIB: object lost from scene: '%s'"),
sce->id.name + 2);
BLI_remlink(&sce->base, base_legacy);
if (base_legacy == sce->basact) {
- sce->basact = NULL;
+ sce->basact = nullptr;
}
MEM_freeN(base_legacy);
}
@@ -1494,7 +1492,7 @@ static void scene_blend_read_lib(BlendLibReader *reader, ID *id)
}
#ifdef USE_SETSCENE_CHECK
- if (sce->set != NULL) {
+ if (sce->set != nullptr) {
sce->flag |= SCE_READFILE_LIBLINK_NEED_SETSCENE_CHECK;
}
#endif
@@ -1588,12 +1586,12 @@ static void scene_undo_preserve(BlendLibReader *reader, ID *id_new, ID *id_old)
Scene *scene_old = (Scene *)id_old;
SWAP(View3DCursor, scene_old->cursor, scene_new->cursor);
- if (scene_new->toolsettings != NULL && scene_old->toolsettings != NULL) {
+ if (scene_new->toolsettings != nullptr && scene_old->toolsettings != nullptr) {
/* First try to restore ID pointers that can be and should be preserved (like brushes or
* palettes), and counteract the swap of the whole ToolSettings structs below for the others
* (like object ones). */
scene_foreach_toolsettings(
- NULL, scene_new->toolsettings, true, reader, scene_old->toolsettings);
+ nullptr, scene_new->toolsettings, true, reader, scene_old->toolsettings);
SWAP(ToolSettings, *scene_old->toolsettings, *scene_new->toolsettings);
}
}
@@ -1602,46 +1600,50 @@ static void scene_lib_override_apply_post(ID *id_dst, ID *UNUSED(id_src))
{
Scene *scene = (Scene *)id_dst;
- if (scene->rigidbody_world != NULL) {
+ if (scene->rigidbody_world != nullptr) {
PTCacheID pid;
- BKE_ptcache_id_from_rigidbody(&pid, NULL, scene->rigidbody_world);
+ BKE_ptcache_id_from_rigidbody(&pid, nullptr, scene->rigidbody_world);
LISTBASE_FOREACH (PointCache *, point_cache, pid.ptcaches) {
point_cache->flag |= PTCACHE_FLAG_INFO_DIRTY;
}
}
}
-IDTypeInfo IDType_ID_SCE = {
- .id_code = ID_SCE,
- .id_filter = FILTER_ID_SCE,
- .main_listbase_index = INDEX_ID_SCE,
- .struct_size = sizeof(Scene),
- .name = "Scene",
- .name_plural = "scenes",
- .translation_context = BLT_I18NCONTEXT_ID_SCENE,
- .flags = 0,
- .asset_type_info = NULL,
+constexpr IDTypeInfo get_type_info()
+{
+ IDTypeInfo info{};
+ info.id_code = ID_SCE;
+ info.id_filter = FILTER_ID_SCE;
+ info.main_listbase_index = INDEX_ID_SCE;
+ info.struct_size = sizeof(Scene);
+ info.name = "Scene";
+ info.name_plural = "scenes";
+ info.translation_context = BLT_I18NCONTEXT_ID_SCENE;
+ info.flags = 0;
+ info.asset_type_info = nullptr;
- .init_data = scene_init_data,
- .copy_data = scene_copy_data,
- .free_data = scene_free_data,
- /* For now default `BKE_lib_id_make_local_generic()` should work, may need more work though to
- * support all possible corner cases. */
- .make_local = NULL,
- .foreach_id = scene_foreach_id,
- .foreach_cache = scene_foreach_cache,
- .foreach_path = scene_foreach_path,
- .owner_get = NULL,
+ info.init_data = scene_init_data;
+ info.copy_data = scene_copy_data;
+ info.free_data = scene_free_data;
+ /* For now default `BKE_lib_id_make_local_generic()` should work, may need more work though to
+ * support all possible corner cases. */
+ info.make_local = nullptr;
+ info.foreach_id = scene_foreach_id;
+ info.foreach_cache = scene_foreach_cache;
+ info.foreach_path = scene_foreach_path;
+ info.owner_get = nullptr;
- .blend_write = scene_blend_write,
- .blend_read_data = scene_blend_read_data,
- .blend_read_lib = scene_blend_read_lib,
- .blend_read_expand = scene_blend_read_expand,
+ info.blend_write = scene_blend_write;
+ info.blend_read_data = scene_blend_read_data;
+ info.blend_read_lib = scene_blend_read_lib;
+ info.blend_read_expand = scene_blend_read_expand;
- .blend_read_undo_preserve = scene_undo_preserve,
+ info.blend_read_undo_preserve = scene_undo_preserve;
- .lib_override_apply_post = scene_lib_override_apply_post,
-};
+ info.lib_override_apply_post = scene_lib_override_apply_post;
+ return info;
+}
+IDTypeInfo IDType_ID_SCE = get_type_info();
const char *RE_engine_id_BLENDER_EEVEE = "BLENDER_EEVEE";
const char *RE_engine_id_BLENDER_WORKBENCH = "BLENDER_WORKBENCH";
@@ -1652,12 +1654,12 @@ void free_avicodecdata(AviCodecData *acd)
if (acd) {
if (acd->lpFormat) {
MEM_freeN(acd->lpFormat);
- acd->lpFormat = NULL;
+ acd->lpFormat = nullptr;
acd->cbFormat = 0;
}
if (acd->lpParms) {
MEM_freeN(acd->lpParms);
- acd->lpParms = NULL;
+ acd->lpParms = nullptr;
acd->cbParms = 0;
}
}
@@ -1668,11 +1670,7 @@ static void remove_sequencer_fcurves(Scene *sce)
AnimData *adt = BKE_animdata_from_id(&sce->id);
if (adt && adt->action) {
- FCurve *fcu, *nextfcu;
-
- for (fcu = adt->action->curves.first; fcu; fcu = nextfcu) {
- nextfcu = fcu->next;
-
+ LISTBASE_FOREACH_MUTABLE (FCurve *, fcu, &adt->action->curves) {
if ((fcu->rna_path) && strstr(fcu->rna_path, "sequences_all")) {
action_groups_remove_channel(adt->action, fcu);
BKE_fcurve_free(fcu);
@@ -1683,55 +1681,55 @@ static void remove_sequencer_fcurves(Scene *sce)
ToolSettings *BKE_toolsettings_copy(ToolSettings *toolsettings, const int flag)
{
- if (toolsettings == NULL) {
- return NULL;
+ if (toolsettings == nullptr) {
+ return nullptr;
}
- ToolSettings *ts = MEM_dupallocN(toolsettings);
+ ToolSettings *ts = static_cast<ToolSettings *>(MEM_dupallocN(toolsettings));
if (ts->vpaint) {
- ts->vpaint = MEM_dupallocN(ts->vpaint);
+ ts->vpaint = static_cast<VPaint *>(MEM_dupallocN(ts->vpaint));
BKE_paint_copy(&ts->vpaint->paint, &ts->vpaint->paint, flag);
}
if (ts->wpaint) {
- ts->wpaint = MEM_dupallocN(ts->wpaint);
+ ts->wpaint = static_cast<VPaint *>(MEM_dupallocN(ts->wpaint));
BKE_paint_copy(&ts->wpaint->paint, &ts->wpaint->paint, flag);
}
if (ts->sculpt) {
- ts->sculpt = MEM_dupallocN(ts->sculpt);
+ ts->sculpt = static_cast<Sculpt *>(MEM_dupallocN(ts->sculpt));
BKE_paint_copy(&ts->sculpt->paint, &ts->sculpt->paint, flag);
}
if (ts->uvsculpt) {
- ts->uvsculpt = MEM_dupallocN(ts->uvsculpt);
+ ts->uvsculpt = static_cast<UvSculpt *>(MEM_dupallocN(ts->uvsculpt));
BKE_paint_copy(&ts->uvsculpt->paint, &ts->uvsculpt->paint, flag);
}
if (ts->gp_paint) {
- ts->gp_paint = MEM_dupallocN(ts->gp_paint);
+ ts->gp_paint = static_cast<GpPaint *>(MEM_dupallocN(ts->gp_paint));
BKE_paint_copy(&ts->gp_paint->paint, &ts->gp_paint->paint, flag);
}
if (ts->gp_vertexpaint) {
- ts->gp_vertexpaint = MEM_dupallocN(ts->gp_vertexpaint);
+ ts->gp_vertexpaint = static_cast<GpVertexPaint *>(MEM_dupallocN(ts->gp_vertexpaint));
BKE_paint_copy(&ts->gp_vertexpaint->paint, &ts->gp_vertexpaint->paint, flag);
}
if (ts->gp_sculptpaint) {
- ts->gp_sculptpaint = MEM_dupallocN(ts->gp_sculptpaint);
+ ts->gp_sculptpaint = static_cast<GpSculptPaint *>(MEM_dupallocN(ts->gp_sculptpaint));
BKE_paint_copy(&ts->gp_sculptpaint->paint, &ts->gp_sculptpaint->paint, flag);
}
if (ts->gp_weightpaint) {
- ts->gp_weightpaint = MEM_dupallocN(ts->gp_weightpaint);
+ ts->gp_weightpaint = static_cast<GpWeightPaint *>(MEM_dupallocN(ts->gp_weightpaint));
BKE_paint_copy(&ts->gp_weightpaint->paint, &ts->gp_weightpaint->paint, flag);
}
if (ts->curves_sculpt) {
- ts->curves_sculpt = MEM_dupallocN(ts->curves_sculpt);
+ ts->curves_sculpt = static_cast<CurvesSculpt *>(MEM_dupallocN(ts->curves_sculpt));
BKE_paint_copy(&ts->curves_sculpt->paint, &ts->curves_sculpt->paint, flag);
}
BKE_paint_copy(&ts->imapaint.paint, &ts->imapaint.paint, flag);
- ts->particle.paintcursor = NULL;
- ts->particle.scene = NULL;
- ts->particle.object = NULL;
+ ts->particle.paintcursor = nullptr;
+ ts->particle.scene = nullptr;
+ ts->particle.object = nullptr;
/* duplicate Grease Pencil interpolation curve */
ts->gp_interpolate.custom_ipo = BKE_curvemapping_copy(ts->gp_interpolate.custom_ipo);
- /* Duplicate Grease Pencil multiframe falloff. */
+ /* Duplicate Grease Pencil multi-frame falloff. */
ts->gp_sculpt.cur_falloff = BKE_curvemapping_copy(ts->gp_sculpt.cur_falloff);
ts->gp_sculpt.cur_primitive = BKE_curvemapping_copy(ts->gp_sculpt.cur_primitive);
@@ -1743,7 +1741,7 @@ ToolSettings *BKE_toolsettings_copy(ToolSettings *toolsettings, const int flag)
void BKE_toolsettings_free(ToolSettings *toolsettings)
{
- if (toolsettings == NULL) {
+ if (toolsettings == nullptr) {
return;
}
if (toolsettings->vpaint) {
@@ -1788,7 +1786,7 @@ void BKE_toolsettings_free(ToolSettings *toolsettings)
if (toolsettings->gp_interpolate.custom_ipo) {
BKE_curvemapping_free(toolsettings->gp_interpolate.custom_ipo);
}
- /* free Grease Pencil multiframe falloff curve */
+ /* free Grease Pencil multi-frame falloff curve */
if (toolsettings->gp_sculpt.cur_falloff) {
BKE_curvemapping_free(toolsettings->gp_sculpt.cur_falloff);
}
@@ -1811,7 +1809,7 @@ void BKE_scene_copy_data_eevee(Scene *sce_dst, const Scene *sce_src)
{
/* Copy eevee data between scenes. */
sce_dst->eevee = sce_src->eevee;
- sce_dst->eevee.light_cache_data = NULL;
+ sce_dst->eevee.light_cache_data = nullptr;
sce_dst->eevee.light_cache_info[0] = '\0';
/* TODO: Copy the cache. */
}
@@ -1862,7 +1860,7 @@ Scene *BKE_scene_duplicate(Main *bmain, Scene *sce, eSceneCopyMethod type)
/* make a private copy of the avicodecdata */
if (sce->r.avicodecdata) {
- sce_copy->r.avicodecdata = MEM_dupallocN(sce->r.avicodecdata);
+ sce_copy->r.avicodecdata = static_cast<AviCodecData *>(MEM_dupallocN(sce->r.avicodecdata));
sce_copy->r.avicodecdata->lpFormat = MEM_dupallocN(sce_copy->r.avicodecdata->lpFormat);
sce_copy->r.avicodecdata->lpParms = MEM_dupallocN(sce_copy->r.avicodecdata->lpParms);
}
@@ -1870,14 +1868,14 @@ Scene *BKE_scene_duplicate(Main *bmain, Scene *sce, eSceneCopyMethod type)
BKE_sound_reset_scene_runtime(sce_copy);
/* grease pencil */
- sce_copy->gpd = NULL;
+ sce_copy->gpd = nullptr;
- sce_copy->preview = NULL;
+ sce_copy->preview = nullptr;
return sce_copy;
}
- eDupli_ID_Flags duplicate_flags = U.dupflag | USER_DUP_OBJECT;
+ eDupli_ID_Flags duplicate_flags = (eDupli_ID_Flags)(U.dupflag | USER_DUP_OBJECT);
sce_copy = (Scene *)BKE_id_copy(bmain, (ID *)sce);
id_us_min(&sce_copy->id);
@@ -1900,7 +1898,7 @@ Scene *BKE_scene_duplicate(Main *bmain, Scene *sce, eSceneCopyMethod type)
/* In case root duplicated ID is linked, assume we want to get a local copy of it and
* duplicate all expected linked data. */
if (ID_IS_LINKED(sce)) {
- duplicate_flags |= USER_DUP_LINKED_ID;
+ duplicate_flags = (eDupli_ID_Flags)(duplicate_flags | USER_DUP_LINKED_ID);
}
}
@@ -1919,22 +1917,25 @@ Scene *BKE_scene_duplicate(Main *bmain, Scene *sce, eSceneCopyMethod type)
/* Deep-duplicate collections and objects (using preferences' settings for which sub-data to
* duplicate along the object itself). */
- BKE_collection_duplicate(
- bmain, NULL, sce_copy->master_collection, duplicate_flags, LIB_ID_DUPLICATE_IS_SUBPROCESS);
+ BKE_collection_duplicate(bmain,
+ nullptr,
+ sce_copy->master_collection,
+ duplicate_flags,
+ LIB_ID_DUPLICATE_IS_SUBPROCESS);
/* Rigid body world collections may not be instantiated as scene's collections, ensure they
* also get properly duplicated. */
- if (sce_copy->rigidbody_world != NULL) {
- if (sce_copy->rigidbody_world->group != NULL) {
+ if (sce_copy->rigidbody_world != nullptr) {
+ if (sce_copy->rigidbody_world->group != nullptr) {
BKE_collection_duplicate(bmain,
- NULL,
+ nullptr,
sce_copy->rigidbody_world->group,
duplicate_flags,
LIB_ID_DUPLICATE_IS_SUBPROCESS);
}
- if (sce_copy->rigidbody_world->constraints != NULL) {
+ if (sce_copy->rigidbody_world->constraints != nullptr) {
BKE_collection_duplicate(bmain,
- NULL,
+ nullptr,
sce_copy->rigidbody_world->constraints,
duplicate_flags,
LIB_ID_DUPLICATE_IS_SUBPROCESS);
@@ -1995,9 +1996,7 @@ bool BKE_scene_can_be_removed(const Main *bmain, const Scene *scene)
Scene *BKE_scene_add(Main *bmain, const char *name)
{
- Scene *sce;
-
- sce = BKE_id_new(bmain, ID_SCE, name);
+ Scene *sce = static_cast<Scene *>(BKE_id_new(bmain, ID_SCE, name));
id_us_min(&sce->id);
id_us_ensure_real(&sce->id);
@@ -2023,25 +2022,22 @@ Object *BKE_scene_object_find_by_name(const Scene *scene, const char *name)
}
}
}
- return NULL;
+ return nullptr;
}
void BKE_scene_set_background(Main *bmain, Scene *scene)
{
- Object *ob;
-
/* check for cyclic sets, for reading old files but also for definite security (py?) */
BKE_scene_validate_setscene(bmain, scene);
- /* deselect objects (for dataselect) */
- for (ob = bmain->objects.first; ob; ob = ob->id.next) {
+ /* Deselect objects (for data select). */
+ LISTBASE_FOREACH (Object *, ob, &bmain->objects) {
ob->flag &= ~SELECT;
}
/* copy layers and flags from bases to objects */
LISTBASE_FOREACH (ViewLayer *, view_layer, &scene->view_layers) {
LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) {
- ob = base->object;
/* collection patch... */
BKE_scene_object_base_flag_sync_from_base(base);
}
@@ -2060,7 +2056,7 @@ Scene *BKE_scene_set_name(Main *bmain, const char *name)
}
printf("Can't find scene: '%s' in file: '%s'\n", name, BKE_main_blendfile_path(bmain));
- return NULL;
+ return nullptr;
}
int BKE_scene_base_iter_next(
@@ -2071,9 +2067,9 @@ int BKE_scene_base_iter_next(
/* init */
if (val == 0) {
iter->phase = F_START;
- iter->dupob = NULL;
- iter->duplilist = NULL;
- iter->dupli_refob = NULL;
+ iter->dupob = nullptr;
+ iter->duplilist = nullptr;
+ iter->dupli_refob = nullptr;
}
else {
/* run_again is set when a duplilist has been ended */
@@ -2084,7 +2080,7 @@ int BKE_scene_base_iter_next(
if (iter->phase == F_START) {
ViewLayer *view_layer = (depsgraph) ? DEG_get_evaluated_view_layer(depsgraph) :
BKE_view_layer_context_active_PLACEHOLDER(*scene);
- *base = view_layer->object_bases.first;
+ *base = static_cast<Base *>(view_layer->object_bases.first);
if (*base) {
*ob = (*base)->object;
iter->phase = F_SCENE;
@@ -2095,7 +2091,7 @@ int BKE_scene_base_iter_next(
(*scene) = (*scene)->set;
ViewLayer *view_layer_set = BKE_view_layer_default_render(*scene);
if (view_layer_set->object_bases.first) {
- *base = view_layer_set->object_bases.first;
+ *base = static_cast<Base *>(view_layer_set->object_bases.first);
*ob = (*base)->object;
iter->phase = F_SCENE;
break;
@@ -2116,7 +2112,7 @@ int BKE_scene_base_iter_next(
(*scene) = (*scene)->set;
ViewLayer *view_layer_set = BKE_view_layer_default_render(*scene);
if (view_layer_set->object_bases.first) {
- *base = view_layer_set->object_bases.first;
+ *base = static_cast<Base *>(view_layer_set->object_bases.first);
*ob = (*base)->object;
break;
}
@@ -2126,7 +2122,7 @@ int BKE_scene_base_iter_next(
}
}
- if (*base == NULL) {
+ if (*base == nullptr) {
iter->phase = F_START;
}
else {
@@ -2135,16 +2131,16 @@ int BKE_scene_base_iter_next(
/* Collections cannot be duplicated for meta-balls yet,
* this enters eternal loop because of
* makeDispListMBall getting called inside of collection_duplilist */
- if ((*base)->object->instance_collection == NULL) {
+ if ((*base)->object->instance_collection == nullptr) {
iter->duplilist = object_duplilist(depsgraph, (*scene), (*base)->object);
- iter->dupob = iter->duplilist->first;
+ iter->dupob = static_cast<DupliObject *>(iter->duplilist->first);
if (!iter->dupob) {
free_object_duplilist(iter->duplilist);
- iter->duplilist = NULL;
+ iter->duplilist = nullptr;
}
- iter->dupli_refob = NULL;
+ iter->dupli_refob = nullptr;
}
}
}
@@ -2174,11 +2170,11 @@ int BKE_scene_base_iter_next(
if (iter->dupli_refob) {
/* Restore last object's real matrix. */
copy_m4_m4(iter->dupli_refob->obmat, iter->omat);
- iter->dupli_refob = NULL;
+ iter->dupli_refob = nullptr;
}
free_object_duplilist(iter->duplilist);
- iter->duplilist = NULL;
+ iter->duplilist = nullptr;
run_again = true;
}
}
@@ -2195,7 +2191,7 @@ bool BKE_scene_has_view_layer(const Scene *scene, const ViewLayer *layer)
Scene *BKE_scene_find_from_collection(const Main *bmain, const Collection *collection)
{
- for (Scene *scene = bmain->scenes.first; scene; scene = scene->id.next) {
+ LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
LISTBASE_FOREACH (ViewLayer *, layer, &scene->view_layers) {
if (BKE_view_layer_has_collection(layer, collection)) {
return scene;
@@ -2203,21 +2199,21 @@ Scene *BKE_scene_find_from_collection(const Main *bmain, const Collection *colle
}
}
- return NULL;
+ return nullptr;
}
#ifdef DURIAN_CAMERA_SWITCH
Object *BKE_scene_camera_switch_find(Scene *scene)
{
if (scene->r.mode & R_NO_CAMERA_SWITCH) {
- return NULL;
+ return nullptr;
}
const int ctime = (int)BKE_scene_ctime_get(scene);
int frame = -(MAXFRAME + 1);
int min_frame = MAXFRAME + 1;
- Object *camera = NULL;
- Object *first_camera = NULL;
+ Object *camera = nullptr;
+ Object *first_camera = nullptr;
LISTBASE_FOREACH (TimeMarker *, m, &scene->markers) {
if (m->camera && (m->camera->visibility_flag & OB_HIDE_RENDER) == 0) {
@@ -2237,7 +2233,7 @@ Object *BKE_scene_camera_switch_find(Scene *scene)
}
}
- if (camera == NULL) {
+ if (camera == nullptr) {
/* If there's no marker to the left of current frame,
* use camera from left-most marker to solve all sort
* of Schrodinger uncertainties.
@@ -2270,7 +2266,10 @@ const char *BKE_scene_find_marker_name(const Scene *scene, int frame)
const TimeMarker *m1, *m2;
/* search through markers for match */
- for (m1 = markers->first, m2 = markers->last; m1 && m2; m1 = m1->next, m2 = m2->prev) {
+ for (m1 = static_cast<const TimeMarker *>(markers->first),
+ m2 = static_cast<const TimeMarker *>(markers->last);
+ m1 && m2;
+ m1 = m1->next, m2 = m2->prev) {
if (m1->frame == frame) {
return m1->name;
}
@@ -2284,14 +2283,14 @@ const char *BKE_scene_find_marker_name(const Scene *scene, int frame)
}
}
- return NULL;
+ return nullptr;
}
const char *BKE_scene_find_last_marker_name(const Scene *scene, int frame)
{
- const TimeMarker *marker, *best_marker = NULL;
+ const TimeMarker *best_marker = nullptr;
int best_frame = -MAXFRAME * 2;
- for (marker = scene->markers.first; marker; marker = marker->next) {
+ LISTBASE_FOREACH (const TimeMarker *, marker, &scene->markers) {
if (marker->frame == frame) {
return marker->name;
}
@@ -2302,7 +2301,7 @@ const char *BKE_scene_find_last_marker_name(const Scene *scene, int frame)
}
}
- return best_marker ? best_marker->name : NULL;
+ return best_marker ? best_marker->name : nullptr;
}
int BKE_scene_frame_snap_by_seconds(Scene *scene, double interval_in_seconds, int frame)
@@ -2335,7 +2334,7 @@ bool BKE_scene_validate_setscene(Main *bmain, Scene *sce)
Scene *sce_iter;
int a, totscene;
- if (sce->set == NULL) {
+ if (sce->set == nullptr) {
return true;
}
totscene = BLI_listbase_count(&bmain->scenes);
@@ -2344,7 +2343,7 @@ bool BKE_scene_validate_setscene(Main *bmain, Scene *sce)
/* more iterations than scenes means we have a cycle */
if (a > totscene) {
/* the tested scene gets zero'ed, that's typically current scene */
- sce->set = NULL;
+ sce->set = nullptr;
return false;
}
}
@@ -2437,9 +2436,8 @@ int BKE_scene_orientation_get_index_from_flag(Scene *scene, int flag)
static bool check_rendered_viewport_visible(Main *bmain)
{
- wmWindowManager *wm = bmain->wm.first;
- wmWindow *window;
- for (window = wm->windows.first; window != NULL; window = window->next) {
+ wmWindowManager *wm = static_cast<wmWindowManager *>(bmain->wm.first);
+ LISTBASE_FOREACH (const wmWindow *, window, &wm->windows) {
const bScreen *screen = BKE_workspace_active_screen_get(window->workspace_hook);
Scene *scene = window->scene;
RenderEngineType *type = RE_engines_find(scene->r.engine);
@@ -2448,8 +2446,8 @@ static bool check_rendered_viewport_visible(Main *bmain)
continue;
}
- for (ScrArea *area = screen->areabase.first; area != NULL; area = area->next) {
- View3D *v3d = area->spacedata.first;
+ LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
+ View3D *v3d = static_cast<View3D *>(area->spacedata.first);
if (area->spacetype != SPACE_VIEW3D) {
continue;
}
@@ -2462,7 +2460,7 @@ static bool check_rendered_viewport_visible(Main *bmain)
}
/* TODO(campbell): shouldn't we be able to use 'DEG_get_view_layer' here?
- * Currently this is NULL on load, so don't. */
+ * Currently this is nullptr on load, so don't. */
static void prepare_mesh_for_viewport_render(Main *bmain, const ViewLayer *view_layer)
{
/* This is needed to prepare mesh to be used by the render
@@ -2476,18 +2474,15 @@ static void prepare_mesh_for_viewport_render(Main *bmain, const ViewLayer *view_
Object *obedit = OBEDIT_FROM_VIEW_LAYER(view_layer);
if (obedit) {
- Mesh *mesh = obedit->data;
+ Mesh *mesh = static_cast<Mesh *>(obedit->data);
if ((obedit->type == OB_MESH) &&
((obedit->id.recalc & ID_RECALC_ALL) || (mesh->id.recalc & ID_RECALC_ALL))) {
if (check_rendered_viewport_visible(bmain)) {
BMesh *bm = mesh->edit_mesh->bm;
- BM_mesh_bm_to_me(bmain,
- bm,
- mesh,
- (&(struct BMeshToMeshParams){
- .calc_object_remap = true,
- .update_shapekey_indices = true,
- }));
+ BMeshToMeshParams params{};
+ params.calc_object_remap = true;
+ params.update_shapekey_indices = true;
+ BM_mesh_bm_to_me(bmain, bm, mesh, &params);
DEG_id_tag_update(&mesh->id, 0);
}
}
@@ -2630,7 +2625,7 @@ void BKE_scene_graph_update_for_newframe_ex(Depsgraph *depsgraph, const bool cle
BKE_sound_set_cfra(scene->r.cfra);
DEG_graph_relations_update(depsgraph);
/* Update all objects: drivers, matrices, #DispList, etc. flags set
- * by depgraph or manual, no layer check here, gets correct flushed.
+ * by depsgraph or manual, no layer check here, gets correct flushed.
*
* NOTE: Only update for new frame on first iteration. Second iteration is for ensuring user
* edits from callback are properly taken into account. Doing a time update on those would
@@ -2697,13 +2692,11 @@ void BKE_scene_view_layer_graph_evaluated_ensure(Main *bmain, Scene *scene, View
SceneRenderView *BKE_scene_add_render_view(Scene *sce, const char *name)
{
- SceneRenderView *srv;
-
if (!name) {
name = DATA_("RenderView");
}
- srv = MEM_callocN(sizeof(SceneRenderView), "new render view");
+ SceneRenderView *srv = MEM_cnew<SceneRenderView>(__func__);
BLI_strncpy(srv->name, name, sizeof(srv->name));
BLI_uniquename(&sce->r.views,
srv,
@@ -2770,7 +2763,7 @@ Base *_setlooper_base_step(Scene **sce_iter, ViewLayer *view_layer, Base *base)
/* Common case, step to the next. */
return base->next;
}
- if ((base == NULL) && (view_layer != NULL)) {
+ if ((base == nullptr) && (view_layer != nullptr)) {
/* First time looping, return the scenes first base. */
/* For the first loop we should get the layer from workspace when available. */
if (view_layer->object_bases.first) {
@@ -2792,7 +2785,7 @@ Base *_setlooper_base_step(Scene **sce_iter, ViewLayer *view_layer, Base *base)
}
}
- return NULL;
+ return nullptr;
}
bool BKE_scene_use_shading_nodes_custom(Scene *scene)
@@ -2823,10 +2816,10 @@ bool BKE_scene_uses_cycles(const Scene *scene)
}
/* This enumeration has to match the one defined in the Cycles addon. */
-typedef enum eCyclesFeatureSet {
+enum eCyclesFeatureSet {
CYCLES_FEATURES_SUPPORTED = 0,
CYCLES_FEATURES_EXPERIMENTAL = 1,
-} eCyclesFeatureSet;
+};
bool BKE_scene_uses_cycles_experimental_features(Scene *scene)
{
@@ -2845,7 +2838,7 @@ bool BKE_scene_uses_cycles_experimental_features(Scene *scene)
void BKE_scene_base_flag_to_objects(ViewLayer *view_layer)
{
- Base *base = view_layer->object_bases.first;
+ Base *base = static_cast<Base *>(view_layer->object_bases.first);
while (base) {
BKE_scene_object_base_flag_sync_from_base(base);
@@ -2954,7 +2947,6 @@ double BKE_scene_unit_scale(const UnitSettings *unit, const int unit_type, doubl
int BKE_scene_multiview_num_views_get(const RenderData *rd)
{
- SceneRenderView *srv;
int totviews = 0;
if ((rd->scemode & R_MULTIVIEW) == 0) {
@@ -2962,18 +2954,20 @@ int BKE_scene_multiview_num_views_get(const RenderData *rd)
}
if (rd->views_format == SCE_VIEWS_FORMAT_STEREO_3D) {
- srv = BLI_findstring(&rd->views, STEREO_LEFT_NAME, offsetof(SceneRenderView, name));
+ SceneRenderView *srv = static_cast<SceneRenderView *>(
+ BLI_findstring(&rd->views, STEREO_LEFT_NAME, offsetof(SceneRenderView, name)));
if ((srv && srv->viewflag & SCE_VIEW_DISABLE) == 0) {
totviews++;
}
- srv = BLI_findstring(&rd->views, STEREO_RIGHT_NAME, offsetof(SceneRenderView, name));
+ srv = static_cast<SceneRenderView *>(
+ BLI_findstring(&rd->views, STEREO_RIGHT_NAME, offsetof(SceneRenderView, name)));
if ((srv && srv->viewflag & SCE_VIEW_DISABLE) == 0) {
totviews++;
}
}
else {
- for (srv = rd->views.first; srv; srv = srv->next) {
+ LISTBASE_FOREACH (SceneRenderView *, srv, &rd->views) {
if ((srv->viewflag & SCE_VIEW_DISABLE) == 0) {
totviews++;
}
@@ -3001,7 +2995,7 @@ bool BKE_scene_multiview_is_stereo3d(const RenderData *rd)
bool BKE_scene_multiview_is_render_view_active(const RenderData *rd, const SceneRenderView *srv)
{
- if (srv == NULL) {
+ if (srv == nullptr) {
return false;
}
@@ -3027,8 +3021,6 @@ bool BKE_scene_multiview_is_render_view_active(const RenderData *rd, const Scene
bool BKE_scene_multiview_is_render_view_first(const RenderData *rd, const char *viewname)
{
- SceneRenderView *srv;
-
if ((rd->scemode & R_MULTIVIEW) == 0) {
return true;
}
@@ -3037,7 +3029,7 @@ bool BKE_scene_multiview_is_render_view_first(const RenderData *rd, const char *
return true;
}
- for (srv = rd->views.first; srv; srv = srv->next) {
+ LISTBASE_FOREACH (const SceneRenderView *, srv, &rd->views) {
if (BKE_scene_multiview_is_render_view_active(rd, srv)) {
return STREQ(viewname, srv->name);
}
@@ -3048,8 +3040,6 @@ bool BKE_scene_multiview_is_render_view_first(const RenderData *rd, const char *
bool BKE_scene_multiview_is_render_view_last(const RenderData *rd, const char *viewname)
{
- SceneRenderView *srv;
-
if ((rd->scemode & R_MULTIVIEW) == 0) {
return true;
}
@@ -3058,7 +3048,7 @@ bool BKE_scene_multiview_is_render_view_last(const RenderData *rd, const char *v
return true;
}
- for (srv = rd->views.last; srv; srv = srv->prev) {
+ LISTBASE_FOREACH_BACKWARD (const SceneRenderView *, srv, &rd->views) {
if (BKE_scene_multiview_is_render_view_active(rd, srv)) {
return STREQ(viewname, srv->name);
}
@@ -3073,10 +3063,10 @@ SceneRenderView *BKE_scene_multiview_render_view_findindex(const RenderData *rd,
size_t nr;
if ((rd->scemode & R_MULTIVIEW) == 0) {
- return NULL;
+ return nullptr;
}
- for (srv = rd->views.first, nr = 0; srv; srv = srv->next) {
+ for (srv = static_cast<SceneRenderView *>(rd->views.first), nr = 0; srv; srv = srv->next) {
if (BKE_scene_multiview_is_render_view_active(rd, srv)) {
if (nr++ == view_id) {
return srv;
@@ -3110,7 +3100,7 @@ int BKE_scene_multiview_view_id_get(const RenderData *rd, const char *viewname)
return 0;
}
- for (srv = rd->views.first, nr = 0; srv; srv = srv->next) {
+ for (srv = static_cast<SceneRenderView *>(rd->views.first), nr = 0; srv; srv = srv->next) {
if (BKE_scene_multiview_is_render_view_active(rd, srv)) {
if (STREQ(viewname, srv->name)) {
return nr;
@@ -3139,7 +3129,8 @@ void BKE_scene_multiview_view_filepath_get(const RenderData *rd,
SceneRenderView *srv;
char suffix[FILE_MAX];
- srv = BLI_findstring(&rd->views, viewname, offsetof(SceneRenderView, name));
+ srv = static_cast<SceneRenderView *>(
+ BLI_findstring(&rd->views, viewname, offsetof(SceneRenderView, name)));
if (srv) {
BLI_strncpy(suffix, srv->suffix, sizeof(suffix));
}
@@ -3155,11 +3146,12 @@ const char *BKE_scene_multiview_view_suffix_get(const RenderData *rd, const char
{
SceneRenderView *srv;
- if ((viewname == NULL) || (viewname[0] == '\0')) {
+ if ((viewname == nullptr) || (viewname[0] == '\0')) {
return viewname;
}
- srv = BLI_findstring(&rd->views, viewname, offsetof(SceneRenderView, name));
+ srv = static_cast<SceneRenderView *>(
+ BLI_findstring(&rd->views, viewname, offsetof(SceneRenderView, name)));
if (srv) {
return srv->suffix;
}
@@ -3182,7 +3174,6 @@ void BKE_scene_multiview_view_prefix_get(Scene *scene,
char *r_prefix,
const char **r_ext)
{
- SceneRenderView *srv;
size_t index_act;
const char *suf_act;
const char delims[] = {'.', '\0'};
@@ -3191,13 +3182,13 @@ void BKE_scene_multiview_view_prefix_get(Scene *scene,
/* begin of extension */
index_act = BLI_str_rpartition(name, delims, r_ext, &suf_act);
- if (*r_ext == NULL) {
+ if (*r_ext == nullptr) {
return;
}
BLI_assert(index_act > 0);
UNUSED_VARS_NDEBUG(index_act);
- for (srv = scene->r.views.first; srv; srv = srv->next) {
+ LISTBASE_FOREACH (SceneRenderView *, srv, &scene->r.views) {
if (BKE_scene_multiview_is_render_view_active(&scene->r, srv)) {
const size_t len = strlen(srv->suffix);
const size_t ext_len = strlen(*r_ext);
@@ -3250,16 +3241,16 @@ int BKE_scene_multiview_num_videos_get(const RenderData *rd)
/* Manipulation of depsgraph storage. */
/* This is a key which identifies depsgraph. */
-typedef struct DepsgraphKey {
+struct DepsgraphKey {
const ViewLayer *view_layer;
/* TODO(sergey): Need to include window somehow (same layer might be in a
* different states in different windows).
*/
-} DepsgraphKey;
+};
static unsigned int depsgraph_key_hash(const void *key_v)
{
- const DepsgraphKey *key = key_v;
+ const DepsgraphKey *key = static_cast<const DepsgraphKey *>(key_v);
unsigned int hash = BLI_ghashutil_ptrhash(key->view_layer);
/* TODO(sergey): Include hash from other fields in the key. */
return hash;
@@ -3267,21 +3258,21 @@ static unsigned int depsgraph_key_hash(const void *key_v)
static bool depsgraph_key_compare(const void *key_a_v, const void *key_b_v)
{
- const DepsgraphKey *key_a = key_a_v;
- const DepsgraphKey *key_b = key_b_v;
+ const DepsgraphKey *key_a = static_cast<const DepsgraphKey *>(key_a_v);
+ const DepsgraphKey *key_b = static_cast<const DepsgraphKey *>(key_b_v);
/* TODO(sergey): Compare rest of. */
return !(key_a->view_layer == key_b->view_layer);
}
static void depsgraph_key_free(void *key_v)
{
- DepsgraphKey *key = key_v;
+ DepsgraphKey *key = static_cast<DepsgraphKey *>(key_v);
MEM_freeN(key);
}
static void depsgraph_key_value_free(void *value)
{
- Depsgraph *depsgraph = value;
+ Depsgraph *depsgraph = static_cast<Depsgraph *>(value);
DEG_graph_free(depsgraph);
}
@@ -3293,23 +3284,23 @@ void BKE_scene_allocate_depsgraph_hash(Scene *scene)
void BKE_scene_ensure_depsgraph_hash(Scene *scene)
{
- if (scene->depsgraph_hash == NULL) {
+ if (scene->depsgraph_hash == nullptr) {
BKE_scene_allocate_depsgraph_hash(scene);
}
}
void BKE_scene_free_depsgraph_hash(Scene *scene)
{
- if (scene->depsgraph_hash == NULL) {
+ if (scene->depsgraph_hash == nullptr) {
return;
}
BLI_ghash_free(scene->depsgraph_hash, depsgraph_key_free, depsgraph_key_value_free);
- scene->depsgraph_hash = NULL;
+ scene->depsgraph_hash = nullptr;
}
void BKE_scene_free_view_layer_depsgraph(Scene *scene, ViewLayer *view_layer)
{
- if (scene->depsgraph_hash != NULL) {
+ if (scene->depsgraph_hash != nullptr) {
DepsgraphKey key = {view_layer};
BLI_ghash_remove(scene->depsgraph_hash, &key, depsgraph_key_free, depsgraph_key_value_free);
}
@@ -3321,17 +3312,17 @@ static Depsgraph **scene_get_depsgraph_p(Scene *scene,
ViewLayer *view_layer,
const bool allocate_ghash_entry)
{
- /* bmain may be NULL here! */
- BLI_assert(scene != NULL);
- BLI_assert(view_layer != NULL);
+ /* bmain may be nullptr here! */
+ BLI_assert(scene != nullptr);
+ BLI_assert(view_layer != nullptr);
BLI_assert(BKE_scene_has_view_layer(scene, view_layer));
/* Make sure hash itself exists. */
if (allocate_ghash_entry) {
BKE_scene_ensure_depsgraph_hash(scene);
}
- if (scene->depsgraph_hash == NULL) {
- return NULL;
+ if (scene->depsgraph_hash == nullptr) {
+ return nullptr;
}
DepsgraphKey key;
@@ -3350,23 +3341,23 @@ static Depsgraph **scene_get_depsgraph_p(Scene *scene,
}
/* Depsgraph was not found in the ghash, but the key still needs allocating. */
- *key_ptr = MEM_mallocN(sizeof(DepsgraphKey), __func__);
+ *key_ptr = MEM_new<DepsgraphKey>(__func__);
**key_ptr = key;
- *depsgraph_ptr = NULL;
+ *depsgraph_ptr = nullptr;
return depsgraph_ptr;
}
static Depsgraph **scene_ensure_depsgraph_p(Main *bmain, Scene *scene, ViewLayer *view_layer)
{
- BLI_assert(bmain != NULL);
+ BLI_assert(bmain != nullptr);
Depsgraph **depsgraph_ptr = scene_get_depsgraph_p(scene, view_layer, true);
- if (depsgraph_ptr == NULL) {
+ if (depsgraph_ptr == nullptr) {
/* The scene has no depsgraph hash. */
- return NULL;
+ return nullptr;
}
- if (*depsgraph_ptr != NULL) {
+ if (*depsgraph_ptr != nullptr) {
/* The depsgraph was found, no need to allocate. */
return depsgraph_ptr;
}
@@ -3393,25 +3384,25 @@ Depsgraph *BKE_scene_get_depsgraph(const Scene *scene, const ViewLayer *view_lay
{
BLI_assert(BKE_scene_has_view_layer(scene, view_layer));
- if (scene->depsgraph_hash == NULL) {
- return NULL;
+ if (scene->depsgraph_hash == nullptr) {
+ return nullptr;
}
DepsgraphKey key;
key.view_layer = view_layer;
- return BLI_ghash_lookup(scene->depsgraph_hash, &key);
+ return static_cast<Depsgraph *>(BLI_ghash_lookup(scene->depsgraph_hash, &key));
}
Depsgraph *BKE_scene_ensure_depsgraph(Main *bmain, Scene *scene, ViewLayer *view_layer)
{
Depsgraph **depsgraph_ptr = scene_ensure_depsgraph_p(bmain, scene, view_layer);
- return (depsgraph_ptr != NULL) ? *depsgraph_ptr : NULL;
+ return (depsgraph_ptr != nullptr) ? *depsgraph_ptr : nullptr;
}
static char *scene_undo_depsgraph_gen_key(Scene *scene, ViewLayer *view_layer, char *key_full)
{
- if (key_full == NULL) {
- key_full = MEM_callocN(MAX_ID_NAME + FILE_MAX + MAX_NAME, __func__);
+ if (key_full == nullptr) {
+ key_full = static_cast<char *>(MEM_callocN(MAX_ID_NAME + FILE_MAX + MAX_NAME, __func__));
}
size_t key_full_offset = BLI_strncpy_rlen(key_full, scene->id.name, MAX_ID_NAME);
@@ -3430,24 +3421,23 @@ GHash *BKE_scene_undo_depsgraphs_extract(Main *bmain)
GHash *depsgraph_extract = BLI_ghash_new(
BLI_ghashutil_strhash_p, BLI_ghashutil_strcmp, __func__);
- for (Scene *scene = bmain->scenes.first; scene != NULL; scene = scene->id.next) {
- if (scene->depsgraph_hash == NULL) {
+ LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
+ if (scene->depsgraph_hash == nullptr) {
/* In some cases, e.g. when undo has to perform multiple steps at once, no depsgraph will
- * be built so this pointer may be NULL. */
+ * be built so this pointer may be nullptr. */
continue;
}
- for (ViewLayer *view_layer = scene->view_layers.first; view_layer != NULL;
- view_layer = view_layer->next) {
+ LISTBASE_FOREACH (ViewLayer *, view_layer, &scene->view_layers) {
DepsgraphKey key;
key.view_layer = view_layer;
Depsgraph **depsgraph = (Depsgraph **)BLI_ghash_lookup_p(scene->depsgraph_hash, &key);
- if (depsgraph != NULL && *depsgraph != NULL) {
- char *key_full = scene_undo_depsgraph_gen_key(scene, view_layer, NULL);
+ if (depsgraph != nullptr && *depsgraph != nullptr) {
+ char *key_full = scene_undo_depsgraph_gen_key(scene, view_layer, nullptr);
/* We steal the depsgraph from the scene. */
BLI_ghash_insert(depsgraph_extract, key_full, *depsgraph);
- *depsgraph = NULL;
+ *depsgraph = nullptr;
}
}
}
@@ -3457,22 +3447,21 @@ GHash *BKE_scene_undo_depsgraphs_extract(Main *bmain)
void BKE_scene_undo_depsgraphs_restore(Main *bmain, GHash *depsgraph_extract)
{
- for (Scene *scene = bmain->scenes.first; scene != NULL; scene = scene->id.next) {
- for (ViewLayer *view_layer = scene->view_layers.first; view_layer != NULL;
- view_layer = view_layer->next) {
+ LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
+ LISTBASE_FOREACH (ViewLayer *, view_layer, &scene->view_layers) {
char key_full[MAX_ID_NAME + FILE_MAX + MAX_NAME] = {0};
scene_undo_depsgraph_gen_key(scene, view_layer, key_full);
Depsgraph **depsgraph_extract_ptr = (Depsgraph **)BLI_ghash_lookup_p(depsgraph_extract,
key_full);
- if (depsgraph_extract_ptr == NULL) {
+ if (depsgraph_extract_ptr == nullptr) {
continue;
}
- BLI_assert(*depsgraph_extract_ptr != NULL);
+ BLI_assert(*depsgraph_extract_ptr != nullptr);
Depsgraph **depsgraph_scene_ptr = scene_get_depsgraph_p(scene, view_layer, true);
- BLI_assert(depsgraph_scene_ptr != NULL);
- BLI_assert(*depsgraph_scene_ptr == NULL);
+ BLI_assert(depsgraph_scene_ptr != nullptr);
+ BLI_assert(*depsgraph_scene_ptr == nullptr);
/* We steal the depsgraph back from our 'extract' storage to the scene. */
Depsgraph *depsgraph = *depsgraph_extract_ptr;
@@ -3482,7 +3471,7 @@ void BKE_scene_undo_depsgraphs_restore(Main *bmain, GHash *depsgraph_extract)
DEG_graph_tag_relations_update(depsgraph);
*depsgraph_scene_ptr = depsgraph;
- *depsgraph_extract_ptr = NULL;
+ *depsgraph_extract_ptr = nullptr;
}
}
@@ -3515,7 +3504,7 @@ void BKE_scene_transform_orientation_remove(Scene *scene, TransformOrientation *
TransformOrientation *BKE_scene_transform_orientation_find(const Scene *scene, const int index)
{
- return BLI_findlink(&scene->transform_spaces, index);
+ return static_cast<TransformOrientation *>(BLI_findlink(&scene->transform_spaces, index));
}
int BKE_scene_transform_orientation_get_index(const Scene *scene,
diff --git a/source/blender/blenkernel/intern/subsurf_ccg.c b/source/blender/blenkernel/intern/subsurf_ccg.c
index 61ed4233474..91deeda8381 100644
--- a/source/blender/blenkernel/intern/subsurf_ccg.c
+++ b/source/blender/blenkernel/intern/subsurf_ccg.c
@@ -1469,7 +1469,7 @@ static void ccgdm_create_grids(DerivedMesh *dm)
DMFlagMat *gridFlagMats;
CCGFace **gridFaces;
int *gridOffset;
- int index, numFaces, numGrids, S, gIndex /*, gridSize*/;
+ int index, numFaces, numGrids, S, gIndex /*, gridSize */;
if (ccgdm->gridData) {
return;
diff --git a/source/blender/blenkernel/intern/world.c b/source/blender/blenkernel/intern/world.c
index ac8b18f3395..cc3ee06f539 100644
--- a/source/blender/blenkernel/intern/world.c
+++ b/source/blender/blenkernel/intern/world.c
@@ -59,6 +59,8 @@ static void world_free_data(ID *id)
BKE_icon_id_delete((struct ID *)wrld);
BKE_previewimg_free(&wrld->preview);
+
+ MEM_SAFE_FREE(wrld->lightgroup);
}
static void world_init_data(ID *id)
@@ -107,6 +109,10 @@ static void world_copy_data(Main *bmain, ID *id_dst, const ID *id_src, const int
else {
wrld_dst->preview = NULL;
}
+
+ if (wrld_src->lightgroup) {
+ wrld_dst->lightgroup = (LightgroupMembership *)MEM_dupallocN(wrld_src->lightgroup);
+ }
}
static void world_foreach_id(ID *id, LibraryForeachIDData *data)
@@ -142,6 +148,10 @@ static void world_blend_write(BlendWriter *writer, ID *id, const void *id_addres
}
BKE_previewimg_blend_write(writer, wrld->preview);
+
+ if (wrld->lightgroup) {
+ BLO_write_struct(writer, LightgroupMembership, wrld->lightgroup);
+ }
}
static void world_blend_read_data(BlendDataReader *reader, ID *id)
@@ -153,6 +163,8 @@ static void world_blend_read_data(BlendDataReader *reader, ID *id)
BLO_read_data_address(reader, &wrld->preview);
BKE_previewimg_blend_read(reader, wrld->preview);
BLI_listbase_clear(&wrld->gpumaterial);
+
+ BLO_read_data_address(reader, &wrld->lightgroup);
}
static void world_blend_read_lib(BlendLibReader *reader, ID *id)
diff --git a/source/blender/blenlib/BLI_bitmap.h b/source/blender/blenlib/BLI_bitmap.h
index 38c44193ab3..ca11cd6574e 100644
--- a/source/blender/blenlib/BLI_bitmap.h
+++ b/source/blender/blenlib/BLI_bitmap.h
@@ -25,33 +25,33 @@ typedef unsigned int BLI_bitmap;
#define _BITMAP_MASK 31
/**
- * Number of blocks needed to hold '_tot' bits.
+ * Number of blocks needed to hold '_num' bits.
*/
-#define _BITMAP_NUM_BLOCKS(_tot) (((_tot) >> _BITMAP_POWER) + 1)
+#define _BITMAP_NUM_BLOCKS(_num) (((_num) >> _BITMAP_POWER) + 1)
/**
- * Size (in bytes) used to hold '_tot' bits.
+ * Size (in bytes) used to hold '_num' bits.
*/
-#define BLI_BITMAP_SIZE(_tot) ((size_t)(_BITMAP_NUM_BLOCKS(_tot)) * sizeof(BLI_bitmap))
+#define BLI_BITMAP_SIZE(_num) ((size_t)(_BITMAP_NUM_BLOCKS(_num)) * sizeof(BLI_bitmap))
/**
- * Allocate memory for a bitmap with '_tot' bits; free with MEM_freeN().
+ * Allocate memory for a bitmap with '_num' bits; free with MEM_freeN().
*/
-#define BLI_BITMAP_NEW(_tot, _alloc_string) \
- ((BLI_bitmap *)MEM_callocN(BLI_BITMAP_SIZE(_tot), _alloc_string))
+#define BLI_BITMAP_NEW(_num, _alloc_string) \
+ ((BLI_bitmap *)MEM_callocN(BLI_BITMAP_SIZE(_num), _alloc_string))
/**
* Allocate a bitmap on the stack.
*/
-#define BLI_BITMAP_NEW_ALLOCA(_tot) \
- ((BLI_bitmap *)memset(alloca(BLI_BITMAP_SIZE(_tot)), 0, BLI_BITMAP_SIZE(_tot)))
+#define BLI_BITMAP_NEW_ALLOCA(_num) \
+ ((BLI_bitmap *)memset(alloca(BLI_BITMAP_SIZE(_num)), 0, BLI_BITMAP_SIZE(_num)))
/**
* Allocate using given MemArena.
*/
-#define BLI_BITMAP_NEW_MEMARENA(_mem, _tot) \
+#define BLI_BITMAP_NEW_MEMARENA(_mem, _num) \
(CHECK_TYPE_INLINE(_mem, MemArena *), \
- ((BLI_bitmap *)BLI_memarena_calloc(_mem, BLI_BITMAP_SIZE(_tot))))
+ ((BLI_bitmap *)BLI_memarena_calloc(_mem, BLI_BITMAP_SIZE(_num))))
/**
* Get the value of a single bit at '_index'.
@@ -107,12 +107,12 @@ typedef unsigned int BLI_bitmap;
(void)0
/**
- * Resize bitmap to have space for '_tot' bits.
+ * Resize bitmap to have space for '_num' bits.
*/
-#define BLI_BITMAP_RESIZE(_bitmap, _tot) \
+#define BLI_BITMAP_RESIZE(_bitmap, _num) \
{ \
CHECK_TYPE(_bitmap, BLI_bitmap *); \
- (_bitmap) = MEM_recallocN(_bitmap, BLI_BITMAP_SIZE(_tot)); \
+ (_bitmap) = MEM_recallocN(_bitmap, BLI_BITMAP_SIZE(_num)); \
} \
(void)0
diff --git a/source/blender/blenlib/BLI_cpp_type.hh b/source/blender/blenlib/BLI_cpp_type.hh
index 881408f460b..9453eb89a2e 100644
--- a/source/blender/blenlib/BLI_cpp_type.hh
+++ b/source/blender/blenlib/BLI_cpp_type.hh
@@ -110,6 +110,9 @@ class CPPType : NonCopyable, NonMovable {
void (*default_construct_)(void *ptr) = nullptr;
void (*default_construct_indices_)(void *ptr, IndexMask mask) = nullptr;
+ void (*value_initialize_)(void *ptr) = nullptr;
+ void (*value_initialize_indices_)(void *ptr, IndexMask mask) = nullptr;
+
void (*destruct_)(void *ptr) = nullptr;
void (*destruct_indices_)(void *ptr, IndexMask mask) = nullptr;
@@ -326,6 +329,31 @@ class CPPType : NonCopyable, NonMovable {
}
/**
+ * Same as #default_construct, but does zero initialization for trivial types.
+ *
+ * C++ equivalent:
+ * new (ptr) T();
+ */
+ void value_initialize(void *ptr) const
+ {
+ BLI_assert(this->pointer_can_point_to_instance(ptr));
+
+ value_initialize_(ptr);
+ }
+
+ void value_initialize_n(void *ptr, int64_t n) const
+ {
+ this->value_initialize_indices(ptr, IndexMask(n));
+ }
+
+ void value_initialize_indices(void *ptr, IndexMask mask) const
+ {
+ BLI_assert(mask.size() == 0 || this->pointer_can_point_to_instance(ptr));
+
+ value_initialize_indices_(ptr, mask);
+ }
+
+ /**
* Call the destructor on the given instance of this type. The pointer must not be nullptr.
*
* For some trivial types, this does nothing.
@@ -651,9 +679,9 @@ class CPPType : NonCopyable, NonMovable {
* compile-time. This allows the compiler to optimize a function for specific types, while all
* other types can still use a generic fallback function.
*
- * \param Types The types that code should be generated for.
- * \param fn The function object to call. This is expected to have a templated `operator()` and a
- * non-templated `operator()`. The templated version will be called if the current #CPPType
+ * \param Types: The types that code should be generated for.
+ * \param fn: The function object to call. This is expected to have a templated `operator()` and
+ * a non-templated `operator()`. The templated version will be called if the current #CPPType
* matches any of the given types. Otherwise, the non-templated function is called.
*/
template<typename... Types, typename Fn> void to_static_type(const Fn &fn) const
diff --git a/source/blender/blenlib/BLI_cpp_type_make.hh b/source/blender/blenlib/BLI_cpp_type_make.hh
index 9100b2b9a0f..2612348075b 100644
--- a/source/blender/blenlib/BLI_cpp_type_make.hh
+++ b/source/blender/blenlib/BLI_cpp_type_make.hh
@@ -20,6 +20,16 @@ template<typename T> void default_construct_indices_cb(void *ptr, IndexMask mask
mask.foreach_index([&](int64_t i) { new (static_cast<T *>(ptr) + i) T; });
}
+template<typename T> void value_initialize_cb(void *ptr)
+{
+ new (ptr) T();
+}
+
+template<typename T> void value_initialize_indices_cb(void *ptr, IndexMask mask)
+{
+ mask.foreach_index([&](int64_t i) { new (static_cast<T *>(ptr) + i) T(); });
+}
+
template<typename T> void destruct_cb(void *ptr)
{
(static_cast<T *>(ptr))->~T();
@@ -186,6 +196,8 @@ CPPType::CPPType(CPPTypeParam<T, Flags> /* unused */, StringRef debug_name)
if constexpr (std::is_default_constructible_v<T>) {
default_construct_ = default_construct_cb<T>;
default_construct_indices_ = default_construct_indices_cb<T>;
+ value_initialize_ = value_initialize_cb<T>;
+ value_initialize_indices_ = value_initialize_indices_cb<T>;
static T default_value;
default_value_ = (void *)&default_value;
}
diff --git a/source/blender/blenlib/BLI_enumerable_thread_specific.hh b/source/blender/blenlib/BLI_enumerable_thread_specific.hh
index 51bf8d06cf1..a5bd79d5826 100644
--- a/source/blender/blenlib/BLI_enumerable_thread_specific.hh
+++ b/source/blender/blenlib/BLI_enumerable_thread_specific.hh
@@ -3,23 +3,20 @@
#pragma once
#ifdef WITH_TBB
-
-# ifdef WITH_TBB
/* Quiet top level deprecation message, unrelated to API usage here. */
-# if defined(WIN32) && !defined(NOMINMAX)
+# if defined(WIN32) && !defined(NOMINMAX)
/* TBB includes Windows.h which will define min/max macros causing issues
* when we try to use std::min and std::max later on. */
-# define NOMINMAX
-# define TBB_MIN_MAX_CLEANUP
-# endif
-# include <tbb/enumerable_thread_specific.h>
-# ifdef WIN32
+# define NOMINMAX
+# define TBB_MIN_MAX_CLEANUP
+# endif
+# include <tbb/enumerable_thread_specific.h>
+# ifdef WIN32
/* We cannot keep this defined, since other parts of the code deal with this on their own, leading
* to multiple define warnings unless we un-define this, however we can only undefine this if we
* were the ones that made the definition earlier. */
-# ifdef TBB_MIN_MAX_CLEANUP
-# undef NOMINMAX
-# endif
+# ifdef TBB_MIN_MAX_CLEANUP
+# undef NOMINMAX
# endif
# endif
#endif
diff --git a/source/blender/blenlib/BLI_generic_span.hh b/source/blender/blenlib/BLI_generic_span.hh
index f4f93735e06..4c0bfc83ba8 100644
--- a/source/blender/blenlib/BLI_generic_span.hh
+++ b/source/blender/blenlib/BLI_generic_span.hh
@@ -164,6 +164,18 @@ class GMutableSpan {
{
return this->slice(range.start(), range.size());
}
+
+ /**
+ * Copy all values from another span into this span. This invokes undefined behavior when the
+ * destination contains uninitialized data and T is not trivially copy constructible.
+ * The size of both spans is expected to be the same.
+ */
+ void copy_from(GSpan values)
+ {
+ BLI_assert(type_ == &values.type());
+ BLI_assert(size_ == values.size());
+ type_->copy_assign_n(values.data(), data_, size_);
+ }
};
} // namespace blender
diff --git a/source/blender/blenlib/BLI_heap.h b/source/blender/blenlib/BLI_heap.h
index e8aa95f6aa7..882f40c1850 100644
--- a/source/blender/blenlib/BLI_heap.h
+++ b/source/blender/blenlib/BLI_heap.h
@@ -25,7 +25,7 @@ typedef void (*HeapFreeFP)(void *ptr);
*
* \note Use when the size of the heap is known in advance.
*/
-Heap *BLI_heap_new_ex(unsigned int tot_reserve) ATTR_WARN_UNUSED_RESULT;
+Heap *BLI_heap_new_ex(unsigned int reserve_num) ATTR_WARN_UNUSED_RESULT;
Heap *BLI_heap_new(void) ATTR_WARN_UNUSED_RESULT;
void BLI_heap_clear(Heap *heap, HeapFreeFP ptrfreefp) ATTR_NONNULL(1);
void BLI_heap_free(Heap *heap, HeapFreeFP ptrfreefp) ATTR_NONNULL(1);
diff --git a/source/blender/blenlib/BLI_heap_simple.h b/source/blender/blenlib/BLI_heap_simple.h
index 79504096d67..4a63a6d624c 100644
--- a/source/blender/blenlib/BLI_heap_simple.h
+++ b/source/blender/blenlib/BLI_heap_simple.h
@@ -21,7 +21,7 @@ typedef void (*HeapSimpleFreeFP)(void *ptr);
*
* \note Use when the size of the heap is known in advance.
*/
-HeapSimple *BLI_heapsimple_new_ex(unsigned int tot_reserve) ATTR_WARN_UNUSED_RESULT;
+HeapSimple *BLI_heapsimple_new_ex(unsigned int reserve_num) ATTR_WARN_UNUSED_RESULT;
HeapSimple *BLI_heapsimple_new(void) ATTR_WARN_UNUSED_RESULT;
void BLI_heapsimple_clear(HeapSimple *heap, HeapSimpleFreeFP ptrfreefp) ATTR_NONNULL(1);
void BLI_heapsimple_free(HeapSimple *heap, HeapSimpleFreeFP ptrfreefp) ATTR_NONNULL(1);
diff --git a/source/blender/blenlib/BLI_index_mask.hh b/source/blender/blenlib/BLI_index_mask.hh
index 3decd8b9441..b87ab0afc98 100644
--- a/source/blender/blenlib/BLI_index_mask.hh
+++ b/source/blender/blenlib/BLI_index_mask.hh
@@ -163,16 +163,30 @@ class IndexMask {
*/
template<typename CallbackT> void foreach_index(const CallbackT &callback) const
{
- if (this->is_range()) {
- IndexRange range = this->as_range();
- for (int64_t i : range) {
+ this->to_best_mask_type([&](const auto &mask) {
+ for (const int64_t i : mask) {
callback(i);
}
+ });
+ }
+
+ /**
+ * Often an #IndexMask wraps a range of indices without any gaps. In this case, it is more
+ * efficient to compute the indices in a loop on-the-fly instead of reading them from memory.
+ * This method makes it easy to generate code for both cases.
+ *
+ * The given function is expected to take one parameter that can either be of type #IndexRange or
+ * #Span<int64_t>.
+ */
+ template<typename Fn> void to_best_mask_type(const Fn &fn) const
+ {
+ if (this->is_range()) {
+ const IndexRange masked_range = this->as_range();
+ fn(masked_range);
}
else {
- for (int64_t i : indices_) {
- callback(i);
- }
+ const Span<int64_t> masked_indices = indices_;
+ fn(masked_indices);
}
}
diff --git a/source/blender/blenlib/BLI_kdopbvh.h b/source/blender/blenlib/BLI_kdopbvh.h
index 38f3e1ee290..8642d728909 100644
--- a/source/blender/blenlib/BLI_kdopbvh.h
+++ b/source/blender/blenlib/BLI_kdopbvh.h
@@ -181,18 +181,18 @@ int BLI_bvhtree_overlap_thread_num(const BVHTree *tree);
*/
BVHTreeOverlap *BLI_bvhtree_overlap_ex(const BVHTree *tree1,
const BVHTree *tree2,
- uint *r_overlap_tot,
+ uint *r_overlap_num,
BVHTree_OverlapCallback callback,
void *userdata,
uint max_interactions,
int flag);
BVHTreeOverlap *BLI_bvhtree_overlap(const BVHTree *tree1,
const BVHTree *tree2,
- unsigned int *r_overlap_tot,
+ unsigned int *r_overlap_num,
BVHTree_OverlapCallback callback,
void *userdata);
-int *BLI_bvhtree_intersect_plane(BVHTree *tree, float plane[4], uint *r_intersect_tot);
+int *BLI_bvhtree_intersect_plane(BVHTree *tree, float plane[4], uint *r_intersect_num);
/**
* Number of times #BLI_bvhtree_insert has been called.
diff --git a/source/blender/blenlib/BLI_length_parameterize.hh b/source/blender/blenlib/BLI_length_parameterize.hh
new file mode 100644
index 00000000000..e4a4e9cbb9c
--- /dev/null
+++ b/source/blender/blenlib/BLI_length_parameterize.hh
@@ -0,0 +1,80 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#pragma once
+
+/** \file
+ * \ingroup bli
+ */
+
+#include "BLI_math_base.hh"
+#include "BLI_math_color.hh"
+#include "BLI_math_vector.hh"
+#include "BLI_vector.hh"
+
+namespace blender::length_parameterize {
+
+/**
+ * Return the size of the necessary lengths array for a group of points, taking into account the
+ * possible last cyclic segment.
+ *
+ * \note This is the same as #bke::curves::curve_segment_size.
+ */
+inline int lengths_num(const int points_num, const bool cyclic)
+{
+ return cyclic ? points_num : points_num - 1;
+}
+
+/**
+ * Accumulate the length of the next segment into each point.
+ */
+template<typename T>
+void accumulate_lengths(const Span<T> values, const bool cyclic, MutableSpan<float> lengths)
+{
+ BLI_assert(lengths.size() == lengths_num(values.size(), cyclic));
+ float length = 0.0f;
+ for (const int i : IndexRange(values.size() - 1)) {
+ length += math::distance(values[i], values[i + 1]);
+ lengths[i] = length;
+ }
+ if (cyclic) {
+ lengths.last() = length + math::distance(values.last(), values.first());
+ }
+}
+
+template<typename T>
+void linear_interpolation(const Span<T> src,
+ const Span<int> indices,
+ const Span<float> factors,
+ MutableSpan<T> dst)
+{
+ BLI_assert(indices.size() == factors.size());
+ BLI_assert(indices.size() == dst.size());
+ const int last_src_index = src.index_range().last();
+
+ int cyclic_sample_count = 0;
+ for (int i = indices.index_range().last(); i > 0; i--) {
+ if (indices[i] != last_src_index) {
+ break;
+ }
+ dst[i] = math::interpolate(src.last(), src.first(), factors[i]);
+ cyclic_sample_count++;
+ }
+
+ for (const int i : dst.index_range().drop_back(cyclic_sample_count)) {
+ dst[i] = math::interpolate(src[indices[i]], src[indices[i] + 1], factors[i]);
+ }
+}
+
+/**
+ * Find the given number of points, evenly spaced along the provided length. For non-cyclic
+ * sequences, the first point will always be included, and last point will always be included if
+ * the #count is greater than zero. For cyclic sequences, the first point will always be included.
+ *
+ * \warning The #count argument must be greater than zero.
+ */
+void create_uniform_samples(Span<float> lengths,
+ bool cyclic,
+ MutableSpan<int> indices,
+ MutableSpan<float> factors);
+
+} // namespace blender::length_parameterize
diff --git a/source/blender/blenlib/BLI_map.hh b/source/blender/blenlib/BLI_map.hh
index 3cbb81b5c7d..d76aa46502d 100644
--- a/source/blender/blenlib/BLI_map.hh
+++ b/source/blender/blenlib/BLI_map.hh
@@ -962,7 +962,13 @@ class Map {
*/
void clear()
{
- this->noexcept_reset();
+ for (Slot &slot : slots_) {
+ slot.~Slot();
+ new (&slot) Slot();
+ }
+
+ removed_slots_ = 0;
+ occupied_and_removed_slots_ = 0;
}
/**
diff --git a/source/blender/blenlib/BLI_math_color.hh b/source/blender/blenlib/BLI_math_color.hh
new file mode 100644
index 00000000000..5195cfb6238
--- /dev/null
+++ b/source/blender/blenlib/BLI_math_color.hh
@@ -0,0 +1,28 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later
+ * Copyright 2022 Blender Foundation. */
+
+#pragma once
+
+/** \file
+ * \ingroup bli
+ */
+
+#include <cmath>
+#include <type_traits>
+
+#include "BLI_color.hh"
+#include "BLI_math_base.hh"
+
+namespace blender::math {
+
+inline ColorGeometry4f interpolate(const ColorGeometry4f &a,
+ const ColorGeometry4f &b,
+ const float t)
+{
+ return {math::interpolate(a.r, b.r, t),
+ math::interpolate(a.g, b.g, t),
+ math::interpolate(a.b, b.b, t),
+ math::interpolate(a.a, b.a, t)};
+}
+
+} // namespace blender::math
diff --git a/source/blender/blenlib/BLI_math_geom.h b/source/blender/blenlib/BLI_math_geom.h
index c31e3045c97..9e65093a05f 100644
--- a/source/blender/blenlib/BLI_math_geom.h
+++ b/source/blender/blenlib/BLI_math_geom.h
@@ -890,7 +890,7 @@ bool clip_segment_v3_plane(
bool clip_segment_v3_plane_n(const float p1[3],
const float p2[3],
const float plane_array[][4],
- int plane_tot,
+ int plane_num,
float r_p1[3],
float r_p2[3]);
diff --git a/source/blender/blenlib/BLI_mempool.h b/source/blender/blenlib/BLI_mempool.h
index 740cf4dedb9..0313b743401 100644
--- a/source/blender/blenlib/BLI_mempool.h
+++ b/source/blender/blenlib/BLI_mempool.h
@@ -20,7 +20,7 @@ struct BLI_mempool_chunk;
typedef struct BLI_mempool BLI_mempool;
BLI_mempool *BLI_mempool_create(unsigned int esize,
- unsigned int totelem,
+ unsigned int elem_num,
unsigned int pchunk,
unsigned int flag)
ATTR_MALLOC ATTR_WARN_UNUSED_RESULT ATTR_RETURNS_NONNULL;
diff --git a/source/blender/blenlib/BLI_path_util.h b/source/blender/blenlib/BLI_path_util.h
index 7b3e3e983f0..06dd9ab0db9 100644
--- a/source/blender/blenlib/BLI_path_util.h
+++ b/source/blender/blenlib/BLI_path_util.h
@@ -204,12 +204,12 @@ bool BLI_path_filename_ensure(char *filepath, size_t maxlen, const char *filenam
* or before dot if no digits.
* \param tail: Optional area to return copy of part of string following digits,
* or from dot if no digits.
- * \param r_num_len: Optional to return number of digits found.
+ * \param r_digits_len: Optional to return number of digits found.
*/
int BLI_path_sequence_decode(const char *string,
char *head,
char *tail,
- unsigned short *r_num_len);
+ unsigned short *r_digits_len);
/**
* Returns in area pointed to by string a string of the form `<head><pic><tail>`,
* where pic is formatted as `numlen` digits with leading zeroes.
@@ -310,7 +310,7 @@ bool BLI_path_frame_range(char *path, int sta, int end, int digits) ATTR_NONNULL
/**
* Get the frame from a filename formatted by blender's frame scheme
*/
-bool BLI_path_frame_get(char *path, int *r_frame, int *numdigits) ATTR_NONNULL();
+bool BLI_path_frame_get(char *path, int *r_frame, int *r_digits_len) ATTR_NONNULL();
/**
* Given a `path` with digits representing frame numbers, replace the digits with the '#'
* character and extract the extension.
diff --git a/source/blender/blenlib/BLI_polyfill_2d.h b/source/blender/blenlib/BLI_polyfill_2d.h
index a551188737f..ccb4c856de3 100644
--- a/source/blender/blenlib/BLI_polyfill_2d.h
+++ b/source/blender/blenlib/BLI_polyfill_2d.h
@@ -16,7 +16,7 @@ struct MemArena;
* A version of #BLI_polyfill_calc that uses a memory arena to avoid re-allocations.
*/
void BLI_polyfill_calc_arena(const float (*coords)[2],
- unsigned int coords_tot,
+ unsigned int coords_num,
int coords_sign,
unsigned int (*r_tris)[3],
@@ -27,16 +27,16 @@ void BLI_polyfill_calc_arena(const float (*coords)[2],
*
* \param coords: 2D coordinates describing vertices of the polygon,
* in either clockwise or counterclockwise order.
- * \param coords_tot: Total points in the array.
+ * \param coords_num: Total points in the array.
* \param coords_sign: Pass this when we know the sign in advance to avoid extra calculations.
*
* \param r_tris: This array is filled in with triangle indices in clockwise order.
- * The length of the array must be `coords_tot - 2`.
+ * The length of the array must be `coords_num - 2`.
* Indices are guaranteed to be assigned to unique triangles, with valid indices,
* even in the case of degenerate input (self intersecting polygons, zero area ears... etc).
*/
void BLI_polyfill_calc(const float (*coords)[2],
- unsigned int coords_tot,
+ unsigned int coords_num,
int coords_sign,
unsigned int (*r_tris)[3]);
diff --git a/source/blender/blenlib/BLI_polyfill_2d_beautify.h b/source/blender/blenlib/BLI_polyfill_2d_beautify.h
index c5a7cb80ff2..8e14bd5c641 100644
--- a/source/blender/blenlib/BLI_polyfill_2d_beautify.h
+++ b/source/blender/blenlib/BLI_polyfill_2d_beautify.h
@@ -20,7 +20,7 @@ struct MemArena;
* are ignored since the edges won't share 2 faces.
*/
void BLI_polyfill_beautify(const float (*coords)[2],
- unsigned int coords_tot,
+ unsigned int coords_num,
unsigned int (*tris)[3],
/* structs for reuse */
diff --git a/source/blender/blenlib/BLI_rand.h b/source/blender/blenlib/BLI_rand.h
index 2cfd868e943..6382c73d3cb 100644
--- a/source/blender/blenlib/BLI_rand.h
+++ b/source/blender/blenlib/BLI_rand.h
@@ -69,9 +69,9 @@ void BLI_rng_get_tri_sample_float_v3(RNG *rng,
void BLI_rng_shuffle_array(struct RNG *rng,
void *data,
unsigned int elem_size_i,
- unsigned int elem_tot) ATTR_NONNULL(1, 2);
+ unsigned int elem_num) ATTR_NONNULL(1, 2);
-void BLI_rng_shuffle_bitmap(struct RNG *rng, unsigned int *bitmap, unsigned int bits_tot)
+void BLI_rng_shuffle_bitmap(struct RNG *rng, unsigned int *bitmap, unsigned int bits_num)
ATTR_NONNULL(1, 2);
/** Note that skipping is as slow as generating n numbers! */
@@ -96,10 +96,10 @@ float BLI_hash_frand(unsigned int seed) ATTR_WARN_UNUSED_RESULT;
*/
void BLI_array_randomize(void *data,
unsigned int elem_size,
- unsigned int elem_tot,
+ unsigned int elem_num,
unsigned int seed);
-void BLI_bitmap_randomize(unsigned int *bitmap, unsigned int bits_tot, unsigned int seed)
+void BLI_bitmap_randomize(unsigned int *bitmap, unsigned int bits_num, unsigned int seed)
ATTR_NONNULL(1);
/** Better seed for the random number generator, using noise.c hash[] */
diff --git a/source/blender/blenlib/BLI_scanfill.h b/source/blender/blenlib/BLI_scanfill.h
index 8e43a3c5a8f..04ac7cb05e4 100644
--- a/source/blender/blenlib/BLI_scanfill.h
+++ b/source/blender/blenlib/BLI_scanfill.h
@@ -51,7 +51,7 @@ typedef struct ScanFillVert {
unsigned int keyindex;
unsigned short poly_nr;
/** number of edges using this vertex */
- unsigned char edge_tot;
+ unsigned char edge_count;
/** vert status */
unsigned int f : 4;
/** flag callers can use as they like */
diff --git a/source/blender/blenlib/BLI_set.hh b/source/blender/blenlib/BLI_set.hh
index bf177802c97..391d31c2228 100644
--- a/source/blender/blenlib/BLI_set.hh
+++ b/source/blender/blenlib/BLI_set.hh
@@ -515,8 +515,13 @@ class Set {
*/
void clear()
{
- this->~Set();
- new (this) Set();
+ for (Slot &slot : slots_) {
+ slot.~Slot();
+ new (&slot) Slot();
+ }
+
+ removed_slots_ = 0;
+ occupied_and_removed_slots_ = 0;
}
/**
diff --git a/source/blender/blenlib/BLI_task.h b/source/blender/blenlib/BLI_task.h
index 1bd49165048..3be492009b0 100644
--- a/source/blender/blenlib/BLI_task.h
+++ b/source/blender/blenlib/BLI_task.h
@@ -238,18 +238,18 @@ typedef void (*TaskParallelIteratorFunc)(void *__restrict userdata,
* \param iter_func: Callback function used to generate chunks of items.
* \param init_item: The initial item, if necessary (may be NULL if unused).
* \param init_index: The initial index.
- * \param tot_items: The total amount of items to iterate over
+ * \param items_num: The total amount of items to iterate over
* (if unknown, set it to a negative number).
* \param func: Callback function.
* \param settings: See public API doc of TaskParallelSettings for description of all settings.
*
- * \note Static scheduling is only available when \a tot_items is >= 0.
+ * \note Static scheduling is only available when \a items_num is >= 0.
*/
void BLI_task_parallel_iterator(void *userdata,
TaskParallelIteratorIterFunc iter_func,
void *init_item,
int init_index,
- int tot_items,
+ int items_num,
TaskParallelIteratorFunc func,
const TaskParallelSettings *settings);
diff --git a/source/blender/blenlib/BLI_utildefines_stack.h b/source/blender/blenlib/BLI_utildefines_stack.h
index fd5c3c72161..caf1726bbcf 100644
--- a/source/blender/blenlib/BLI_utildefines_stack.h
+++ b/source/blender/blenlib/BLI_utildefines_stack.h
@@ -11,17 +11,17 @@
/* only validate array-bounds in debug mode */
#ifdef DEBUG
-# define STACK_DECLARE(stack) unsigned int _##stack##_index, _##stack##_totalloc
-# define STACK_INIT(stack, tot) \
- ((void)stack, (void)((_##stack##_index) = 0), (void)((_##stack##_totalloc) = (tot)))
+# define STACK_DECLARE(stack) unsigned int _##stack##_index, _##stack##_num_alloc
+# define STACK_INIT(stack, stack_num) \
+ ((void)stack, (void)((_##stack##_index) = 0), (void)((_##stack##_num_alloc) = (stack_num)))
# define _STACK_SIZETEST(stack, off) \
- (BLI_assert((_##stack##_index) + (off) <= _##stack##_totalloc))
+ (BLI_assert((_##stack##_index) + (off) <= _##stack##_num_alloc))
# define _STACK_SWAP_TOTALLOC(stack_a, stack_b) \
- SWAP(unsigned int, _##stack_a##_totalloc, _##stack_b##_totalloc)
+ SWAP(unsigned int, _##stack_a##_num_alloc, _##stack_b##_num_alloc)
#else
# define STACK_DECLARE(stack) unsigned int _##stack##_index
-# define STACK_INIT(stack, tot) \
- ((void)stack, (void)((_##stack##_index) = 0), (void)(0 ? (tot) : 0))
+# define STACK_INIT(stack, stack_num) \
+ ((void)stack, (void)((_##stack##_index) = 0), (void)(0 ? (stack_num) : 0))
# define _STACK_SIZETEST(stack, off) (void)(stack), (void)(off)
# define _STACK_SWAP_TOTALLOC(stack_a, stack_b) (void)(stack_a), (void)(stack_b)
#endif
diff --git a/source/blender/blenlib/BLI_vector_set.hh b/source/blender/blenlib/BLI_vector_set.hh
index 23284fd94bc..4ae1bf9000d 100644
--- a/source/blender/blenlib/BLI_vector_set.hh
+++ b/source/blender/blenlib/BLI_vector_set.hh
@@ -531,7 +531,14 @@ class VectorSet {
*/
void clear()
{
- this->noexcept_reset();
+ destruct_n(keys_, this->size());
+ for (Slot &slot : slots_) {
+ slot.~Slot();
+ new (&slot) Slot();
+ }
+
+ removed_slots_ = 0;
+ occupied_and_removed_slots_ = 0;
}
/**
diff --git a/source/blender/blenlib/CMakeLists.txt b/source/blender/blenlib/CMakeLists.txt
index 647726722b1..99e07264276 100644
--- a/source/blender/blenlib/CMakeLists.txt
+++ b/source/blender/blenlib/CMakeLists.txt
@@ -80,6 +80,7 @@ set(SRC
intern/kdtree_4d.c
intern/lasso_2d.c
intern/listbase.c
+ intern/length_parameterize.cc
intern/math_base.c
intern/math_base_inline.c
intern/math_base_safe_inline.c
@@ -225,6 +226,7 @@ set(SRC
BLI_kdtree.h
BLI_kdtree_impl.h
BLI_lasso_2d.h
+ BLI_length_parameterize.hh
BLI_linear_allocator.hh
BLI_link_utils.h
BLI_linklist.h
@@ -241,6 +243,7 @@ set(SRC
BLI_math_bits.h
BLI_math_boolean.hh
BLI_math_color.h
+ BLI_math_color.hh
BLI_math_color_blend.h
BLI_math_geom.h
BLI_math_inline.h
@@ -435,6 +438,7 @@ if(WITH_GTESTS)
tests/BLI_index_range_test.cc
tests/BLI_inplace_priority_queue_test.cc
tests/BLI_kdopbvh_test.cc
+ tests/BLI_length_parameterize_test.cc
tests/BLI_linear_allocator_test.cc
tests/BLI_linklist_lockfree_test.cc
tests/BLI_listbase_test.cc
diff --git a/source/blender/blenlib/intern/BLI_heap.c b/source/blender/blenlib/intern/BLI_heap.c
index cf8073d4ba4..0bc50f62232 100644
--- a/source/blender/blenlib/intern/BLI_heap.c
+++ b/source/blender/blenlib/intern/BLI_heap.c
@@ -35,7 +35,7 @@ struct HeapNode_Chunk {
* or we allocate past the reserved number.
*
* \note Optimize number for 64kb allocs.
- * \note keep type in sync with tot_nodes in heap_node_alloc_chunk.
+ * \note keep type in sync with nodes_num in heap_node_alloc_chunk.
*/
#define HEAP_CHUNK_DEFAULT_NUM \
((uint)((MEM_SIZE_OPTIMAL((1 << 16) - sizeof(struct HeapNode_Chunk))) / sizeof(HeapNode)))
@@ -137,13 +137,13 @@ static void heap_up(Heap *heap, uint i)
/** \name Internal Memory Management
* \{ */
-static struct HeapNode_Chunk *heap_node_alloc_chunk(uint tot_nodes,
+static struct HeapNode_Chunk *heap_node_alloc_chunk(uint nodes_num,
struct HeapNode_Chunk *chunk_prev)
{
struct HeapNode_Chunk *chunk = MEM_mallocN(
- sizeof(struct HeapNode_Chunk) + (sizeof(HeapNode) * tot_nodes), __func__);
+ sizeof(struct HeapNode_Chunk) + (sizeof(HeapNode) * nodes_num), __func__);
chunk->prev = chunk_prev;
- chunk->bufsize = tot_nodes;
+ chunk->bufsize = nodes_num;
chunk->size = 0;
return chunk;
}
@@ -179,16 +179,16 @@ static void heap_node_free(Heap *heap, HeapNode *node)
/** \name Public Heap API
* \{ */
-Heap *BLI_heap_new_ex(uint tot_reserve)
+Heap *BLI_heap_new_ex(uint reserve_num)
{
Heap *heap = MEM_mallocN(sizeof(Heap), __func__);
/* ensure we have at least one so we can keep doubling it */
heap->size = 0;
- heap->bufsize = MAX2(1u, tot_reserve);
+ heap->bufsize = MAX2(1u, reserve_num);
heap->tree = MEM_mallocN(heap->bufsize * sizeof(HeapNode *), "BLIHeapTree");
heap->nodes.chunk = heap_node_alloc_chunk(
- (tot_reserve > 1) ? tot_reserve : HEAP_CHUNK_DEFAULT_NUM, NULL);
+ (reserve_num > 1) ? reserve_num : HEAP_CHUNK_DEFAULT_NUM, NULL);
heap->nodes.free = NULL;
return heap;
diff --git a/source/blender/blenlib/intern/BLI_heap_simple.c b/source/blender/blenlib/intern/BLI_heap_simple.c
index 0876888bcc5..b6c045cbefa 100644
--- a/source/blender/blenlib/intern/BLI_heap_simple.c
+++ b/source/blender/blenlib/intern/BLI_heap_simple.c
@@ -133,12 +133,12 @@ static void heapsimple_up(HeapSimple *heap, uint i, float active_val, void *acti
/** \name Public HeapSimple API
* \{ */
-HeapSimple *BLI_heapsimple_new_ex(uint tot_reserve)
+HeapSimple *BLI_heapsimple_new_ex(uint reserve_num)
{
HeapSimple *heap = MEM_mallocN(sizeof(HeapSimple), __func__);
/* ensure we have at least one so we can keep doubling it */
heap->size = 0;
- heap->bufsize = MAX2(1u, tot_reserve);
+ heap->bufsize = MAX2(1u, reserve_num);
heap->tree = MEM_mallocN(heap->bufsize * sizeof(HeapSimpleNode), "BLIHeapSimpleTree");
return heap;
}
diff --git a/source/blender/blenlib/intern/BLI_kdopbvh.c b/source/blender/blenlib/intern/BLI_kdopbvh.c
index 0c3497d3edf..0f52c84c45e 100644
--- a/source/blender/blenlib/intern/BLI_kdopbvh.c
+++ b/source/blender/blenlib/intern/BLI_kdopbvh.c
@@ -68,7 +68,7 @@ typedef struct BVHNode {
#endif
float *bv; /* Bounding volume of all nodes, max 13 axis */
int index; /* face, edge, vertex index */
- char totnode; /* how many nodes are used, used for speedup */
+ char node_num; /* how many nodes are used, used for speedup */
char main_axis; /* Axis used to split this node */
} BVHNode;
@@ -79,8 +79,8 @@ struct BVHTree {
BVHNode **nodechild; /* pre-alloc children for nodes */
float *nodebv; /* pre-alloc bounding-volumes for nodes */
float epsilon; /* Epsilon is used for inflation of the K-DOP. */
- int totleaf; /* leafs */
- int totbranch;
+ int leaf_num; /* leafs */
+ int branch_num;
axis_t start_axis, stop_axis; /* bvhtree_kdop_axes array indices according to axis */
axis_t axis; /* KDOP type (6 => OBB, 7 => AABB, ...) */
char tree_type; /* type of tree (4 => quad-tree). */
@@ -325,8 +325,8 @@ static void build_skip_links(BVHTree *tree, BVHNode *node, BVHNode *left, BVHNod
node->skip[0] = left;
node->skip[1] = right;
- for (i = 0; i < node->totnode; i++) {
- if (i + 1 < node->totnode) {
+ for (i = 0; i < node->node_num; i++) {
+ if (i + 1 < node->node_num) {
build_skip_links(tree, node->children[i], left, node->children[i + 1]);
}
else {
@@ -485,9 +485,9 @@ static void bvhtree_info(BVHTree *tree)
tree->axis,
tree->epsilon);
printf("nodes = %d, branches = %d, leafs = %d\n",
- tree->totbranch + tree->totleaf,
- tree->totbranch,
- tree->totleaf);
+ tree->branch_num + tree->leaf_num,
+ tree->branch_num,
+ tree->leaf_num);
printf(
"Memory per node = %ubytes\n",
(uint)(sizeof(BVHNode) + sizeof(BVHNode *) * tree->tree_type + sizeof(float) * tree->axis));
@@ -497,7 +497,7 @@ static void bvhtree_info(BVHTree *tree)
(uint)(sizeof(BVHTree) + MEM_allocN_len(tree->nodes) + MEM_allocN_len(tree->nodearray) +
MEM_allocN_len(tree->nodechild) + MEM_allocN_len(tree->nodebv)));
- bvhtree_print_tree(tree, tree->nodes[tree->totleaf], 0);
+ bvhtree_print_tree(tree, tree->nodes[tree->leaf_num], 0);
}
#endif /* USE_PRINT_TREE */
@@ -508,7 +508,7 @@ static void bvhtree_verify(BVHTree *tree)
int i, j, check = 0;
/* check the pointer list */
- for (i = 0; i < tree->totleaf; i++) {
+ for (i = 0; i < tree->leaf_num; i++) {
if (tree->nodes[i]->parent == NULL) {
printf("Leaf has no parent: %d\n", i);
}
@@ -526,7 +526,7 @@ static void bvhtree_verify(BVHTree *tree)
}
/* check the leaf list */
- for (i = 0; i < tree->totleaf; i++) {
+ for (i = 0; i < tree->leaf_num; i++) {
if (tree->nodearray[i].parent == NULL) {
printf("Leaf has no parent: %d\n", i);
}
@@ -544,9 +544,9 @@ static void bvhtree_verify(BVHTree *tree)
}
printf("branches: %d, leafs: %d, total: %d\n",
- tree->totbranch,
- tree->totleaf,
- tree->totbranch + tree->totleaf);
+ tree->branch_num,
+ tree->leaf_num,
+ tree->branch_num + tree->leaf_num);
}
#endif /* USE_VERIFY_TREE */
@@ -555,7 +555,7 @@ static void bvhtree_verify(BVHTree *tree)
* (basically this is only method to calculate pow(k, n) in O(1).. and stuff like that) */
typedef struct BVHBuildHelper {
int tree_type;
- int totleafs;
+ int leafs_num;
/** Min number of leafs that are achievable from a node at depth `N`. */
int leafs_per_child[32];
@@ -573,11 +573,11 @@ static void build_implicit_tree_helper(const BVHTree *tree, BVHBuildHelper *data
int remain;
int nnodes;
- data->totleafs = tree->totleaf;
+ data->leafs_num = tree->leaf_num;
data->tree_type = tree->tree_type;
- /* Calculate the smallest tree_type^n such that tree_type^n >= num_leafs */
- for (data->leafs_per_child[0] = 1; data->leafs_per_child[0] < data->totleafs;
+ /* Calculate the smallest tree_type^n such that tree_type^n >= leafs_num */
+ for (data->leafs_per_child[0] = 1; data->leafs_per_child[0] < data->leafs_num;
data->leafs_per_child[0] *= data->tree_type) {
/* pass */
}
@@ -589,7 +589,7 @@ static void build_implicit_tree_helper(const BVHTree *tree, BVHBuildHelper *data
data->leafs_per_child[depth] = data->leafs_per_child[depth - 1] / data->tree_type;
}
- remain = data->totleafs - data->leafs_per_child[1];
+ remain = data->leafs_num - data->leafs_per_child[1];
nnodes = (remain + data->tree_type - 2) / (data->tree_type - 1);
data->remain_leafs = remain + nnodes;
}
@@ -604,7 +604,7 @@ static int implicit_leafs_index(const BVHBuildHelper *data, const int depth, con
return min_leaf_index;
}
if (data->leafs_per_child[depth]) {
- return data->totleafs -
+ return data->leafs_num -
(data->branches_on_level[depth - 1] - child_index) * data->leafs_per_child[depth];
}
return data->remain_leafs;
@@ -725,7 +725,7 @@ static void non_recursive_bvh_div_nodes_task_cb(void *__restrict userdata,
split_leafs(data->leafs_array, nth_positions, data->tree_type, split_axis);
- /* Setup children and totnode counters
+ /* Setup `children` and `node_num` counters
* Not really needed but currently most of BVH code
* relies on having an explicit children structure */
for (k = 0; k < data->tree_type; k++) {
@@ -750,7 +750,7 @@ static void non_recursive_bvh_div_nodes_task_cb(void *__restrict userdata,
break;
}
}
- parent->totnode = (char)k;
+ parent->node_num = (char)k;
}
/**
@@ -774,7 +774,7 @@ static void non_recursive_bvh_div_nodes_task_cb(void *__restrict userdata,
static void non_recursive_bvh_div_nodes(const BVHTree *tree,
BVHNode *branches_array,
BVHNode **leafs_array,
- int num_leafs)
+ int leafs_num)
{
int i;
@@ -782,7 +782,7 @@ static void non_recursive_bvh_div_nodes(const BVHTree *tree,
/* this value is 0 (on binary trees) and negative on the others */
const int tree_offset = 2 - tree->tree_type;
- const int num_branches = implicit_needed_branches(tree_type, num_leafs);
+ const int branches_num = implicit_needed_branches(tree_type, leafs_num);
BVHBuildHelper data;
int depth;
@@ -794,10 +794,10 @@ static void non_recursive_bvh_div_nodes(const BVHTree *tree,
/* Most of bvhtree code relies on 1-leaf trees having at least one branch
* We handle that special case here */
- if (num_leafs == 1) {
- refit_kdop_hull(tree, root, 0, num_leafs);
+ if (leafs_num == 1) {
+ refit_kdop_hull(tree, root, 0, leafs_num);
root->main_axis = get_largest_axis(root->bv) / 2;
- root->totnode = 1;
+ root->node_num = 1;
root->children[0] = leafs_array[0];
root->children[0]->parent = root;
return;
@@ -819,10 +819,10 @@ static void non_recursive_bvh_div_nodes(const BVHTree *tree,
};
/* Loop tree levels (log N) loops */
- for (i = 1, depth = 1; i <= num_branches; i = i * tree_type + tree_offset, depth++) {
+ for (i = 1, depth = 1; i <= branches_num; i = i * tree_type + tree_offset, depth++) {
const int first_of_next_level = i * tree_type + tree_offset;
/* index of last branch on this level */
- const int i_stop = min_ii(first_of_next_level, num_branches + 1);
+ const int i_stop = min_ii(first_of_next_level, branches_num + 1);
/* Loop all branches on this level */
cb_data.first_of_next_level = first_of_next_level;
@@ -832,7 +832,7 @@ static void non_recursive_bvh_div_nodes(const BVHTree *tree,
if (true) {
TaskParallelSettings settings;
BLI_parallel_range_settings_defaults(&settings);
- settings.use_threading = (num_leafs > KDOPBVH_THREAD_LEAF_THRESHOLD);
+ settings.use_threading = (leafs_num > KDOPBVH_THREAD_LEAF_THRESHOLD);
BLI_task_parallel_range(i, i_stop, &cb_data, non_recursive_bvh_div_nodes_task_cb, &settings);
}
else {
@@ -940,21 +940,21 @@ void BLI_bvhtree_balance(BVHTree *tree)
/* This function should only be called once
* (some big bug goes here if its being called more than once per tree) */
- BLI_assert(tree->totbranch == 0);
+ BLI_assert(tree->branch_num == 0);
/* Build the implicit tree */
non_recursive_bvh_div_nodes(
- tree, tree->nodearray + (tree->totleaf - 1), leafs_array, tree->totleaf);
+ tree, tree->nodearray + (tree->leaf_num - 1), leafs_array, tree->leaf_num);
/* current code expects the branches to be linked to the nodes array
* we perform that linkage here */
- tree->totbranch = implicit_needed_branches(tree->tree_type, tree->totleaf);
- for (int i = 0; i < tree->totbranch; i++) {
- tree->nodes[tree->totleaf + i] = &tree->nodearray[tree->totleaf + i];
+ tree->branch_num = implicit_needed_branches(tree->tree_type, tree->leaf_num);
+ for (int i = 0; i < tree->branch_num; i++) {
+ tree->nodes[tree->leaf_num + i] = &tree->nodearray[tree->leaf_num + i];
}
#ifdef USE_SKIP_LINKS
- build_skip_links(tree, tree->nodes[tree->totleaf], NULL, NULL);
+ build_skip_links(tree, tree->nodes[tree->leaf_num], NULL, NULL);
#endif
#ifdef USE_VERIFY_TREE
@@ -980,12 +980,12 @@ void BLI_bvhtree_insert(BVHTree *tree, int index, const float co[3], int numpoin
{
BVHNode *node = NULL;
- /* insert should only possible as long as tree->totbranch is 0 */
- BLI_assert(tree->totbranch <= 0);
- BLI_assert((size_t)tree->totleaf < MEM_allocN_len(tree->nodes) / sizeof(*(tree->nodes)));
+ /* insert should only possible as long as tree->branch_num is 0 */
+ BLI_assert(tree->branch_num <= 0);
+ BLI_assert((size_t)tree->leaf_num < MEM_allocN_len(tree->nodes) / sizeof(*(tree->nodes)));
- node = tree->nodes[tree->totleaf] = &(tree->nodearray[tree->totleaf]);
- tree->totleaf++;
+ node = tree->nodes[tree->leaf_num] = &(tree->nodearray[tree->leaf_num]);
+ tree->leaf_num++;
create_kdop_hull(tree, node, co, numpoints, 0);
node->index = index;
@@ -1000,7 +1000,7 @@ bool BLI_bvhtree_update_node(
BVHNode *node = NULL;
/* check if index exists */
- if (index > tree->totleaf) {
+ if (index > tree->leaf_num) {
return false;
}
@@ -1024,8 +1024,8 @@ void BLI_bvhtree_update_tree(BVHTree *tree)
* TRICKY: the way we build the tree all the children have an index greater than the parent
* This allows us todo a bottom up update by starting on the bigger numbered branch. */
- BVHNode **root = tree->nodes + tree->totleaf;
- BVHNode **index = tree->nodes + tree->totleaf + tree->totbranch - 1;
+ BVHNode **root = tree->nodes + tree->leaf_num;
+ BVHNode **index = tree->nodes + tree->leaf_num + tree->branch_num - 1;
for (; index >= root; index--) {
node_join(tree, *index);
@@ -1033,7 +1033,7 @@ void BLI_bvhtree_update_tree(BVHTree *tree)
}
int BLI_bvhtree_get_len(const BVHTree *tree)
{
- return tree->totleaf;
+ return tree->leaf_num;
}
int BLI_bvhtree_get_tree_type(const BVHTree *tree)
@@ -1048,7 +1048,7 @@ float BLI_bvhtree_get_epsilon(const BVHTree *tree)
void BLI_bvhtree_get_bounding_box(BVHTree *tree, float r_bb_min[3], float r_bb_max[3])
{
- BVHNode *root = tree->nodes[tree->totleaf];
+ BVHNode *root = tree->nodes[tree->leaf_num];
if (root != NULL) {
const float bb_min[3] = {root->bv[0], root->bv[2], root->bv[4]};
const float bb_max[3] = {root->bv[1], root->bv[3], root->bv[5]};
@@ -1099,9 +1099,9 @@ static void tree_overlap_traverse(BVHOverlapData_Thread *data_thread,
if (tree_overlap_test(node1, node2, data->start_axis, data->stop_axis)) {
/* check if node1 is a leaf */
- if (!node1->totnode) {
+ if (!node1->node_num) {
/* check if node2 is a leaf */
- if (!node2->totnode) {
+ if (!node2->node_num) {
BVHTreeOverlap *overlap;
if (UNLIKELY(node1 == node2)) {
@@ -1143,9 +1143,9 @@ static void tree_overlap_traverse_cb(BVHOverlapData_Thread *data_thread,
if (tree_overlap_test(node1, node2, data->start_axis, data->stop_axis)) {
/* check if node1 is a leaf */
- if (!node1->totnode) {
+ if (!node1->node_num) {
/* check if node2 is a leaf */
- if (!node2->totnode) {
+ if (!node2->node_num) {
BVHTreeOverlap *overlap;
if (UNLIKELY(node1 == node2)) {
@@ -1190,9 +1190,9 @@ static bool tree_overlap_traverse_num(BVHOverlapData_Thread *data_thread,
if (tree_overlap_test(node1, node2, data->start_axis, data->stop_axis)) {
/* check if node1 is a leaf */
- if (!node1->totnode) {
+ if (!node1->node_num) {
/* check if node2 is a leaf */
- if (!node2->totnode) {
+ if (!node2->node_num) {
BVHTreeOverlap *overlap;
if (UNLIKELY(node1 == node2)) {
@@ -1212,7 +1212,7 @@ static bool tree_overlap_traverse_num(BVHOverlapData_Thread *data_thread,
}
}
else {
- for (j = 0; j < node2->totnode; j++) {
+ for (j = 0; j < node2->node_num; j++) {
if (tree_overlap_traverse_num(data_thread, node1, node2->children[j])) {
return true;
}
@@ -1221,7 +1221,7 @@ static bool tree_overlap_traverse_num(BVHOverlapData_Thread *data_thread,
}
else {
const uint max_interactions = data_thread->max_interactions;
- for (j = 0; j < node1->totnode; j++) {
+ for (j = 0; j < node1->node_num; j++) {
if (tree_overlap_traverse_num(data_thread, node1->children[j], node2)) {
data_thread->max_interactions = max_interactions;
}
@@ -1233,7 +1233,7 @@ static bool tree_overlap_traverse_num(BVHOverlapData_Thread *data_thread,
int BLI_bvhtree_overlap_thread_num(const BVHTree *tree)
{
- return (int)MIN2(tree->tree_type, tree->nodes[tree->totleaf]->totnode);
+ return (int)MIN2(tree->tree_type, tree->nodes[tree->leaf_num]->node_num);
}
static void bvhtree_overlap_task_cb(void *__restrict userdata,
@@ -1245,25 +1245,25 @@ static void bvhtree_overlap_task_cb(void *__restrict userdata,
if (data->max_interactions) {
tree_overlap_traverse_num(data,
- data_shared->tree1->nodes[data_shared->tree1->totleaf]->children[j],
- data_shared->tree2->nodes[data_shared->tree2->totleaf]);
+ data_shared->tree1->nodes[data_shared->tree1->leaf_num]->children[j],
+ data_shared->tree2->nodes[data_shared->tree2->leaf_num]);
}
else if (data_shared->callback) {
tree_overlap_traverse_cb(data,
- data_shared->tree1->nodes[data_shared->tree1->totleaf]->children[j],
- data_shared->tree2->nodes[data_shared->tree2->totleaf]);
+ data_shared->tree1->nodes[data_shared->tree1->leaf_num]->children[j],
+ data_shared->tree2->nodes[data_shared->tree2->leaf_num]);
}
else {
tree_overlap_traverse(data,
- data_shared->tree1->nodes[data_shared->tree1->totleaf]->children[j],
- data_shared->tree2->nodes[data_shared->tree2->totleaf]);
+ data_shared->tree1->nodes[data_shared->tree1->leaf_num]->children[j],
+ data_shared->tree2->nodes[data_shared->tree2->leaf_num]);
}
}
BVHTreeOverlap *BLI_bvhtree_overlap_ex(
const BVHTree *tree1,
const BVHTree *tree2,
- uint *r_overlap_tot,
+ uint *r_overlap_num,
/* optional callback to test the overlap before adding (must be thread-safe!) */
BVHTree_OverlapCallback callback,
void *userdata,
@@ -1272,7 +1272,7 @@ BVHTreeOverlap *BLI_bvhtree_overlap_ex(
{
bool overlap_pairs = (flag & BVH_OVERLAP_RETURN_PAIRS) != 0;
bool use_threading = (flag & BVH_OVERLAP_USE_THREADING) != 0 &&
- (tree1->totleaf > KDOPBVH_THREAD_LEAF_THRESHOLD);
+ (tree1->leaf_num > KDOPBVH_THREAD_LEAF_THRESHOLD);
/* 'RETURN_PAIRS' was not implemented without 'max_interactions'. */
BLI_assert(overlap_pairs || max_interactions);
@@ -1293,8 +1293,8 @@ BVHTreeOverlap *BLI_bvhtree_overlap_ex(
return NULL;
}
- const BVHNode *root1 = tree1->nodes[tree1->totleaf];
- const BVHNode *root2 = tree2->nodes[tree2->totleaf];
+ const BVHNode *root1 = tree1->nodes[tree1->leaf_num];
+ const BVHNode *root2 = tree2->nodes[tree2->leaf_num];
start_axis = min_axis(tree1->start_axis, tree2->start_axis);
stop_axis = min_axis(tree1->stop_axis, tree2->stop_axis);
@@ -1354,7 +1354,7 @@ BVHTreeOverlap *BLI_bvhtree_overlap_ex(
BLI_stack_free(data[j].overlap);
to += count;
}
- *r_overlap_tot = (uint)total;
+ *r_overlap_num = (uint)total;
}
return overlap;
@@ -1363,14 +1363,14 @@ BVHTreeOverlap *BLI_bvhtree_overlap_ex(
BVHTreeOverlap *BLI_bvhtree_overlap(
const BVHTree *tree1,
const BVHTree *tree2,
- uint *r_overlap_tot,
+ uint *r_overlap_num,
/* optional callback to test the overlap before adding (must be thread-safe!) */
BVHTree_OverlapCallback callback,
void *userdata)
{
return BLI_bvhtree_overlap_ex(tree1,
tree2,
- r_overlap_tot,
+ r_overlap_num,
callback,
userdata,
0,
@@ -1403,7 +1403,7 @@ static void bvhtree_intersect_plane_dfs_recursive(BVHIntersectPlaneData *__restr
{
if (tree_intersect_plane_test(node->bv, data->plane)) {
/* check if node is a leaf */
- if (!node->totnode) {
+ if (!node->node_num) {
int *intersect = BLI_stack_push_r(data->intersect);
*intersect = node->index;
}
@@ -1417,18 +1417,18 @@ static void bvhtree_intersect_plane_dfs_recursive(BVHIntersectPlaneData *__restr
}
}
-int *BLI_bvhtree_intersect_plane(BVHTree *tree, float plane[4], uint *r_intersect_tot)
+int *BLI_bvhtree_intersect_plane(BVHTree *tree, float plane[4], uint *r_intersect_num)
{
int *intersect = NULL;
size_t total = 0;
- if (tree->totleaf) {
+ if (tree->leaf_num) {
BVHIntersectPlaneData data;
data.tree = tree;
copy_v4_v4(data.plane, plane);
data.intersect = BLI_stack_new(sizeof(int), __func__);
- BVHNode *root = tree->nodes[tree->totleaf];
+ BVHNode *root = tree->nodes[tree->leaf_num];
bvhtree_intersect_plane_dfs_recursive(&data, root);
total = BLI_stack_count(data.intersect);
@@ -1438,7 +1438,7 @@ int *BLI_bvhtree_intersect_plane(BVHTree *tree, float plane[4], uint *r_intersec
}
BLI_stack_free(data.intersect);
}
- *r_intersect_tot = (uint)total;
+ *r_intersect_num = (uint)total;
return intersect;
}
@@ -1473,7 +1473,7 @@ static float calc_nearest_point_squared(const float proj[3], BVHNode *node, floa
/* Depth first search method */
static void dfs_find_nearest_dfs(BVHNearestData *data, BVHNode *node)
{
- if (node->totnode == 0) {
+ if (node->node_num == 0) {
if (data->callback) {
data->callback(data->userdata, node->index, data->co, &data->nearest);
}
@@ -1489,7 +1489,7 @@ static void dfs_find_nearest_dfs(BVHNearestData *data, BVHNode *node)
if (data->proj[node->main_axis] <= node->children[0]->bv[node->main_axis * 2 + 1]) {
- for (i = 0; i != node->totnode; i++) {
+ for (i = 0; i != node->node_num; i++) {
if (calc_nearest_point_squared(data->proj, node->children[i], nearest) >=
data->nearest.dist_sq) {
continue;
@@ -1498,7 +1498,7 @@ static void dfs_find_nearest_dfs(BVHNearestData *data, BVHNode *node)
}
}
else {
- for (i = node->totnode - 1; i >= 0; i--) {
+ for (i = node->node_num - 1; i >= 0; i--) {
if (calc_nearest_point_squared(data->proj, node->children[i], nearest) >=
data->nearest.dist_sq) {
continue;
@@ -1522,7 +1522,7 @@ static void dfs_find_nearest_begin(BVHNearestData *data, BVHNode *node)
/* Priority queue method */
static void heap_find_nearest_inner(BVHNearestData *data, HeapSimple *heap, BVHNode *node)
{
- if (node->totnode == 0) {
+ if (node->node_num == 0) {
if (data->callback) {
data->callback(data->userdata, node->index, data->co, &data->nearest);
}
@@ -1534,7 +1534,7 @@ static void heap_find_nearest_inner(BVHNearestData *data, HeapSimple *heap, BVHN
else {
float nearest[3];
- for (int i = 0; i != node->totnode; i++) {
+ for (int i = 0; i != node->node_num; i++) {
float dist_sq = calc_nearest_point_squared(data->proj, node->children[i], nearest);
if (dist_sq < data->nearest.dist_sq) {
@@ -1574,7 +1574,7 @@ int BLI_bvhtree_find_nearest_ex(BVHTree *tree,
axis_t axis_iter;
BVHNearestData data;
- BVHNode *root = tree->nodes[tree->totleaf];
+ BVHNode *root = tree->nodes[tree->leaf_num];
/* init data to search */
data.tree = tree;
@@ -1642,7 +1642,7 @@ static bool isect_aabb_v3(BVHNode *node, const float co[3])
static bool dfs_find_duplicate_fast_dfs(BVHNearestData *data, BVHNode *node)
{
- if (node->totnode == 0) {
+ if (node->node_num == 0) {
if (isect_aabb_v3(node, data->co)) {
if (data->callback) {
const float dist_sq = data->nearest.dist_sq;
@@ -1658,7 +1658,7 @@ static bool dfs_find_duplicate_fast_dfs(BVHNearestData *data, BVHNode *node)
int i;
if (data->proj[node->main_axis] <= node->children[0]->bv[node->main_axis * 2 + 1]) {
- for (i = 0; i != node->totnode; i++) {
+ for (i = 0; i != node->node_num; i++) {
if (isect_aabb_v3(node->children[i], data->co)) {
if (dfs_find_duplicate_fast_dfs(data, node->children[i])) {
return true;
@@ -1667,7 +1667,7 @@ static bool dfs_find_duplicate_fast_dfs(BVHNearestData *data, BVHNode *node)
}
}
else {
- for (i = node->totnode; i--;) {
+ for (i = node->node_num; i--;) {
if (isect_aabb_v3(node->children[i], data->co)) {
if (dfs_find_duplicate_fast_dfs(data, node->children[i])) {
return true;
@@ -1686,7 +1686,7 @@ int BLI_bvhtree_find_nearest_first(BVHTree *tree,
void *userdata)
{
BVHNearestData data;
- BVHNode *root = tree->nodes[tree->totleaf];
+ BVHNode *root = tree->nodes[tree->leaf_num];
/* init data to search */
data.tree = tree;
@@ -1796,7 +1796,7 @@ static void dfs_raycast(BVHRayCastData *data, BVHNode *node)
return;
}
- if (node->totnode == 0) {
+ if (node->node_num == 0) {
if (data->callback) {
data->callback(data->userdata, node->index, &data->ray, &data->hit);
}
@@ -1809,12 +1809,12 @@ static void dfs_raycast(BVHRayCastData *data, BVHNode *node)
else {
/* pick loop direction to dive into the tree (based on ray direction and split axis) */
if (data->ray_dot_axis[node->main_axis] > 0.0f) {
- for (i = 0; i != node->totnode; i++) {
+ for (i = 0; i != node->node_num; i++) {
dfs_raycast(data, node->children[i]);
}
}
else {
- for (i = node->totnode - 1; i >= 0; i--) {
+ for (i = node->node_num - 1; i >= 0; i--) {
dfs_raycast(data, node->children[i]);
}
}
@@ -1837,7 +1837,7 @@ static void dfs_raycast_all(BVHRayCastData *data, BVHNode *node)
return;
}
- if (node->totnode == 0) {
+ if (node->node_num == 0) {
/* no need to check for 'data->callback' (using 'all' only makes sense with a callback). */
dist = data->hit.dist;
data->callback(data->userdata, node->index, &data->ray, &data->hit);
@@ -1847,12 +1847,12 @@ static void dfs_raycast_all(BVHRayCastData *data, BVHNode *node)
else {
/* pick loop direction to dive into the tree (based on ray direction and split axis) */
if (data->ray_dot_axis[node->main_axis] > 0.0f) {
- for (i = 0; i != node->totnode; i++) {
+ for (i = 0; i != node->node_num; i++) {
dfs_raycast_all(data, node->children[i]);
}
}
else {
- for (i = node->totnode - 1; i >= 0; i--) {
+ for (i = node->node_num - 1; i >= 0; i--) {
dfs_raycast_all(data, node->children[i]);
}
}
@@ -1904,7 +1904,7 @@ int BLI_bvhtree_ray_cast_ex(BVHTree *tree,
int flag)
{
BVHRayCastData data;
- BVHNode *root = tree->nodes[tree->totleaf];
+ BVHNode *root = tree->nodes[tree->leaf_num];
BLI_ASSERT_UNIT_V3(dir);
@@ -1988,7 +1988,7 @@ void BLI_bvhtree_ray_cast_all_ex(BVHTree *tree,
int flag)
{
BVHRayCastData data;
- BVHNode *root = tree->nodes[tree->totleaf];
+ BVHNode *root = tree->nodes[tree->leaf_num];
BLI_ASSERT_UNIT_V3(dir);
BLI_assert(callback != NULL);
@@ -2048,7 +2048,7 @@ typedef struct RangeQueryData {
static void dfs_range_query(RangeQueryData *data, BVHNode *node)
{
- if (node->totnode == 0) {
+ if (node->node_num == 0) {
#if 0 /*UNUSED*/
/* Calculate the node min-coords
* (if the node was a point then this is the point coordinates) */
@@ -2060,12 +2060,12 @@ static void dfs_range_query(RangeQueryData *data, BVHNode *node)
}
else {
int i;
- for (i = 0; i != node->totnode; i++) {
+ for (i = 0; i != node->node_num; i++) {
float nearest[3];
float dist_sq = calc_nearest_point_squared(data->center, node->children[i], nearest);
if (dist_sq < data->radius_sq) {
/* Its a leaf.. call the callback */
- if (node->children[i]->totnode == 0) {
+ if (node->children[i]->node_num == 0) {
data->hits++;
data->callback(data->userdata, node->children[i]->index, data->center, dist_sq);
}
@@ -2080,7 +2080,7 @@ static void dfs_range_query(RangeQueryData *data, BVHNode *node)
int BLI_bvhtree_range_query(
BVHTree *tree, const float co[3], float radius, BVHTree_RangeQuery callback, void *userdata)
{
- BVHNode *root = tree->nodes[tree->totleaf];
+ BVHNode *root = tree->nodes[tree->leaf_num];
RangeQueryData data;
data.tree = tree;
@@ -2096,7 +2096,7 @@ int BLI_bvhtree_range_query(
float dist_sq = calc_nearest_point_squared(data.center, root, nearest);
if (dist_sq < data.radius_sq) {
/* Its a leaf.. call the callback */
- if (root->totnode == 0) {
+ if (root->node_num == 0) {
data.hits++;
data.callback(data.userdata, root->index, co, dist_sq);
}
@@ -2118,7 +2118,7 @@ int BLI_bvhtree_range_query(
static void bvhtree_nearest_projected_dfs_recursive(BVHNearestProjectedData *__restrict data,
const BVHNode *node)
{
- if (node->totnode == 0) {
+ if (node->node_num == 0) {
if (data->callback) {
data->callback(data->userdata, node->index, &data->precalc, NULL, 0, &data->nearest);
}
@@ -2134,7 +2134,7 @@ static void bvhtree_nearest_projected_dfs_recursive(BVHNearestProjectedData *__r
else {
/* First pick the closest node to recurse into */
if (data->closest_axis[node->main_axis]) {
- for (int i = 0; i != node->totnode; i++) {
+ for (int i = 0; i != node->node_num; i++) {
const float *bv = node->children[i]->bv;
if (dist_squared_to_projected_aabb(&data->precalc,
@@ -2146,7 +2146,7 @@ static void bvhtree_nearest_projected_dfs_recursive(BVHNearestProjectedData *__r
}
}
else {
- for (int i = node->totnode; i--;) {
+ for (int i = node->node_num; i--;) {
const float *bv = node->children[i]->bv;
if (dist_squared_to_projected_aabb(&data->precalc,
@@ -2163,7 +2163,7 @@ static void bvhtree_nearest_projected_dfs_recursive(BVHNearestProjectedData *__r
static void bvhtree_nearest_projected_with_clipplane_test_dfs_recursive(
BVHNearestProjectedData *__restrict data, const BVHNode *node)
{
- if (node->totnode == 0) {
+ if (node->node_num == 0) {
if (data->callback) {
data->callback(data->userdata,
node->index,
@@ -2184,7 +2184,7 @@ static void bvhtree_nearest_projected_with_clipplane_test_dfs_recursive(
else {
/* First pick the closest node to recurse into */
if (data->closest_axis[node->main_axis]) {
- for (int i = 0; i != node->totnode; i++) {
+ for (int i = 0; i != node->node_num; i++) {
const float *bv = node->children[i]->bv;
const float bb_min[3] = {bv[0], bv[2], bv[4]};
const float bb_max[3] = {bv[1], bv[3], bv[5]};
@@ -2206,7 +2206,7 @@ static void bvhtree_nearest_projected_with_clipplane_test_dfs_recursive(
}
}
else {
- for (int i = node->totnode; i--;) {
+ for (int i = node->node_num; i--;) {
const float *bv = node->children[i]->bv;
const float bb_min[3] = {bv[0], bv[2], bv[4]};
const float bb_max[3] = {bv[1], bv[3], bv[5]};
@@ -2240,7 +2240,7 @@ int BLI_bvhtree_find_nearest_projected(BVHTree *tree,
BVHTree_NearestProjectedCallback callback,
void *userdata)
{
- BVHNode *root = tree->nodes[tree->totleaf];
+ BVHNode *root = tree->nodes[tree->leaf_num];
if (root != NULL) {
BVHNearestProjectedData data;
dist_squared_to_projected_aabb_precalc(&data.precalc, projmat, winsize, mval);
@@ -2314,7 +2314,7 @@ typedef struct BVHTree_WalkData {
*/
static bool bvhtree_walk_dfs_recursive(BVHTree_WalkData *walk_data, const BVHNode *node)
{
- if (node->totnode == 0) {
+ if (node->node_num == 0) {
return walk_data->walk_leaf_cb(
(const BVHTreeAxisRange *)node->bv, node->index, walk_data->userdata);
}
@@ -2322,7 +2322,7 @@ static bool bvhtree_walk_dfs_recursive(BVHTree_WalkData *walk_data, const BVHNod
/* First pick the closest node to recurse into */
if (walk_data->walk_order_cb(
(const BVHTreeAxisRange *)node->bv, node->main_axis, walk_data->userdata)) {
- for (int i = 0; i != node->totnode; i++) {
+ for (int i = 0; i != node->node_num; i++) {
if (walk_data->walk_parent_cb((const BVHTreeAxisRange *)node->children[i]->bv,
walk_data->userdata)) {
if (!bvhtree_walk_dfs_recursive(walk_data, node->children[i])) {
@@ -2332,7 +2332,7 @@ static bool bvhtree_walk_dfs_recursive(BVHTree_WalkData *walk_data, const BVHNod
}
}
else {
- for (int i = node->totnode - 1; i >= 0; i--) {
+ for (int i = node->node_num - 1; i >= 0; i--) {
if (walk_data->walk_parent_cb((const BVHTreeAxisRange *)node->children[i]->bv,
walk_data->userdata)) {
if (!bvhtree_walk_dfs_recursive(walk_data, node->children[i])) {
@@ -2350,7 +2350,7 @@ void BLI_bvhtree_walk_dfs(BVHTree *tree,
BVHTree_WalkOrderCallback walk_order_cb,
void *userdata)
{
- const BVHNode *root = tree->nodes[tree->totleaf];
+ const BVHNode *root = tree->nodes[tree->leaf_num];
if (root != NULL) {
BVHTree_WalkData walk_data = {walk_parent_cb, walk_leaf_cb, walk_order_cb, userdata};
/* first make sure the bv of root passes in the test too */
diff --git a/source/blender/blenlib/intern/BLI_mempool.c b/source/blender/blenlib/intern/BLI_mempool.c
index 76a82e505e3..f70b5ddd766 100644
--- a/source/blender/blenlib/intern/BLI_mempool.c
+++ b/source/blender/blenlib/intern/BLI_mempool.c
@@ -159,9 +159,9 @@ BLI_INLINE BLI_mempool_chunk *mempool_chunk_find(BLI_mempool_chunk *head, uint i
* \note for small pools 1 is a good default, the elements need to be initialized,
* adding overhead on creation which is redundant if they aren't used.
*/
-BLI_INLINE uint mempool_maxchunks(const uint totelem, const uint pchunk)
+BLI_INLINE uint mempool_maxchunks(const uint elem_num, const uint pchunk)
{
- return (totelem <= pchunk) ? 1 : ((totelem / pchunk) + 1);
+ return (elem_num <= pchunk) ? 1 : ((elem_num / pchunk) + 1);
}
static BLI_mempool_chunk *mempool_chunk_alloc(BLI_mempool *pool)
@@ -250,7 +250,7 @@ static void mempool_chunk_free_all(BLI_mempool_chunk *mpchunk)
}
}
-BLI_mempool *BLI_mempool_create(uint esize, uint totelem, uint pchunk, uint flag)
+BLI_mempool *BLI_mempool_create(uint esize, uint elem_num, uint pchunk, uint flag)
{
BLI_mempool *pool;
BLI_freenode *last_tail = NULL;
@@ -268,7 +268,7 @@ BLI_mempool *BLI_mempool_create(uint esize, uint totelem, uint pchunk, uint flag
esize = MAX2(esize, (uint)sizeof(BLI_freenode));
}
- maxchunks = mempool_maxchunks(totelem, pchunk);
+ maxchunks = mempool_maxchunks(elem_num, pchunk);
pool->chunks = NULL;
pool->chunk_tail = NULL;
@@ -301,7 +301,7 @@ BLI_mempool *BLI_mempool_create(uint esize, uint totelem, uint pchunk, uint flag
#endif
pool->totused = 0;
- if (totelem) {
+ if (elem_num) {
/* Allocate the actual chunks. */
for (i = 0; i < maxchunks; i++) {
BLI_mempool_chunk *mpchunk = mempool_chunk_alloc(pool);
@@ -510,18 +510,18 @@ static void mempool_threadsafe_iternew(BLI_mempool *pool, BLI_mempool_threadsafe
ts_iter->curchunk_threaded_shared = NULL;
}
-ParallelMempoolTaskData *mempool_iter_threadsafe_create(BLI_mempool *pool, const size_t num_iter)
+ParallelMempoolTaskData *mempool_iter_threadsafe_create(BLI_mempool *pool, const size_t iter_num)
{
BLI_assert(pool->flag & BLI_MEMPOOL_ALLOW_ITER);
- ParallelMempoolTaskData *iter_arr = MEM_mallocN(sizeof(*iter_arr) * num_iter, __func__);
+ ParallelMempoolTaskData *iter_arr = MEM_mallocN(sizeof(*iter_arr) * iter_num, __func__);
BLI_mempool_chunk **curchunk_threaded_shared = MEM_mallocN(sizeof(void *), __func__);
mempool_threadsafe_iternew(pool, &iter_arr->ts_iter);
*curchunk_threaded_shared = iter_arr->ts_iter.iter.curchunk;
iter_arr->ts_iter.curchunk_threaded_shared = curchunk_threaded_shared;
- for (size_t i = 1; i < num_iter; i++) {
+ for (size_t i = 1; i < iter_num; i++) {
iter_arr[i].ts_iter = iter_arr[0].ts_iter;
*curchunk_threaded_shared = iter_arr[i].ts_iter.iter.curchunk =
((*curchunk_threaded_shared) ? (*curchunk_threaded_shared)->next : NULL);
diff --git a/source/blender/blenlib/intern/BLI_mempool_private.h b/source/blender/blenlib/intern/BLI_mempool_private.h
index 5e17d4af05a..042b39c2e7f 100644
--- a/source/blender/blenlib/intern/BLI_mempool_private.h
+++ b/source/blender/blenlib/intern/BLI_mempool_private.h
@@ -39,7 +39,7 @@ typedef struct ParallelMempoolTaskData {
* See #BLI_task_parallel_mempool implementation for detailed usage example.
*/
ParallelMempoolTaskData *mempool_iter_threadsafe_create(BLI_mempool *pool,
- size_t num_iter) ATTR_WARN_UNUSED_RESULT
+ size_t iter_num) ATTR_WARN_UNUSED_RESULT
ATTR_NONNULL();
void mempool_iter_threadsafe_destroy(ParallelMempoolTaskData *iter_arr) ATTR_NONNULL();
diff --git a/source/blender/blenlib/intern/DLRB_tree.c b/source/blender/blenlib/intern/DLRB_tree.c
index 0965d8ba05e..c672bb1f2ce 100644
--- a/source/blender/blenlib/intern/DLRB_tree.c
+++ b/source/blender/blenlib/intern/DLRB_tree.c
@@ -578,7 +578,7 @@ DLRBT_Node *BLI_dlrbTree_add(DLRBT_Tree *tree,
}
default: /* update the duplicate node as appropriate */
{
- /* Return the updated node after calling the callback. */
+ /* Return the updated node after calling the callback. */
node = parNode;
if (update_cb) {
update_cb(node, data);
diff --git a/source/blender/blenlib/intern/bitmap.c b/source/blender/blenlib/intern/bitmap.c
index dd022986e14..7fcbc31c066 100644
--- a/source/blender/blenlib/intern/bitmap.c
+++ b/source/blender/blenlib/intern/bitmap.c
@@ -20,8 +20,8 @@ void BLI_bitmap_set_all(BLI_bitmap *bitmap, bool set, size_t bits)
void BLI_bitmap_flip_all(BLI_bitmap *bitmap, size_t bits)
{
- size_t num_blocks = _BITMAP_NUM_BLOCKS(bits);
- for (size_t i = 0; i < num_blocks; i++) {
+ size_t blocks_num = _BITMAP_NUM_BLOCKS(bits);
+ for (size_t i = 0; i < blocks_num; i++) {
bitmap[i] ^= ~(BLI_bitmap)0;
}
}
@@ -33,16 +33,16 @@ void BLI_bitmap_copy_all(BLI_bitmap *dst, const BLI_bitmap *src, size_t bits)
void BLI_bitmap_and_all(BLI_bitmap *dst, const BLI_bitmap *src, size_t bits)
{
- size_t num_blocks = _BITMAP_NUM_BLOCKS(bits);
- for (size_t i = 0; i < num_blocks; i++) {
+ size_t blocks_num = _BITMAP_NUM_BLOCKS(bits);
+ for (size_t i = 0; i < blocks_num; i++) {
dst[i] &= src[i];
}
}
void BLI_bitmap_or_all(BLI_bitmap *dst, const BLI_bitmap *src, size_t bits)
{
- size_t num_blocks = _BITMAP_NUM_BLOCKS(bits);
- for (size_t i = 0; i < num_blocks; i++) {
+ size_t blocks_num = _BITMAP_NUM_BLOCKS(bits);
+ for (size_t i = 0; i < blocks_num; i++) {
dst[i] |= src[i];
}
}
diff --git a/source/blender/blenlib/intern/convexhull_2d.c b/source/blender/blenlib/intern/convexhull_2d.c
index d1daa511b1a..33d1a68a76e 100644
--- a/source/blender/blenlib/intern/convexhull_2d.c
+++ b/source/blender/blenlib/intern/convexhull_2d.c
@@ -165,7 +165,7 @@ int BLI_convexhull_2d(const float (*points)[2], const int n, int r_points[])
struct PointRef *points_ref = MEM_mallocN(sizeof(*points_ref) * (size_t)n, __func__);
float(*points_sort)[2] = MEM_mallocN(sizeof(*points_sort) * (size_t)n, __func__);
int *points_map;
- int tot, i;
+ int points_hull_num, i;
for (i = 0; i < n; i++) {
points_ref[i].pt = points[i];
@@ -178,20 +178,20 @@ int BLI_convexhull_2d(const float (*points)[2], const int n, int r_points[])
memcpy(points_sort[i], points_ref[i].pt, sizeof(float[2]));
}
- tot = BLI_convexhull_2d_sorted(points_sort, n, r_points);
+ points_hull_num = BLI_convexhull_2d_sorted(points_sort, n, r_points);
/* map back to the original index values */
points_map = (int *)points_sort; /* abuse float array for temp storage */
- for (i = 0; i < tot; i++) {
+ for (i = 0; i < points_hull_num; i++) {
points_map[i] = (int)((const float(*)[2])points_ref[r_points[i]].pt - points);
}
- memcpy(r_points, points_map, (size_t)tot * sizeof(*points_map));
+ memcpy(r_points, points_map, (size_t)points_hull_num * sizeof(*points_map));
MEM_freeN(points_ref);
MEM_freeN(points_sort);
- return tot;
+ return points_hull_num;
}
/** \} */
@@ -252,24 +252,24 @@ float BLI_convexhull_aabb_fit_hull_2d(const float (*points_hull)[2], unsigned in
float BLI_convexhull_aabb_fit_points_2d(const float (*points)[2], unsigned int n)
{
int *index_map;
- int tot;
+ int points_hull_num;
float angle;
index_map = MEM_mallocN(sizeof(*index_map) * n * 2, __func__);
- tot = BLI_convexhull_2d(points, (int)n, index_map);
+ points_hull_num = BLI_convexhull_2d(points, (int)n, index_map);
- if (tot) {
+ if (points_hull_num) {
float(*points_hull)[2];
int j;
- points_hull = MEM_mallocN(sizeof(*points_hull) * (size_t)tot, __func__);
- for (j = 0; j < tot; j++) {
+ points_hull = MEM_mallocN(sizeof(*points_hull) * (size_t)points_hull_num, __func__);
+ for (j = 0; j < points_hull_num; j++) {
copy_v2_v2(points_hull[j], points[index_map[j]]);
}
- angle = BLI_convexhull_aabb_fit_hull_2d(points_hull, (unsigned int)tot);
+ angle = BLI_convexhull_aabb_fit_hull_2d(points_hull, (unsigned int)points_hull_num);
MEM_freeN(points_hull);
}
else {
diff --git a/source/blender/blenlib/intern/delaunay_2d.cc b/source/blender/blenlib/intern/delaunay_2d.cc
index e6164c98402..804ba5c3c80 100644
--- a/source/blender/blenlib/intern/delaunay_2d.cc
+++ b/source/blender/blenlib/intern/delaunay_2d.cc
@@ -245,7 +245,7 @@ template<typename Arith_t> struct CDTArrangement {
/** Hint to how much space to reserve in the Vectors of the arrangement,
* based on these counts of input elements. */
- void reserve(int num_verts, int num_edges, int num_faces);
+ void reserve(int verts_num, int edges_num, int faces_num);
/**
* Add a new vertex to the arrangement, with the given 2D coordinate.
@@ -318,7 +318,7 @@ template<typename T> class CDT_state {
public:
CDTArrangement<T> cdt;
/** How many verts were in input (will be first in vert_array). */
- int input_vert_tot;
+ int input_vert_num;
/** Used for visiting things without having to initialized their visit fields. */
int visit_count;
/**
@@ -332,7 +332,7 @@ template<typename T> class CDT_state {
bool need_ids;
explicit CDT_state(
- int num_input_verts, int num_input_edges, int num_input_faces, T epsilon, bool need_ids);
+ int input_verts_num, int input_edges_num, int input_faces_num, T epsilon, bool need_ids);
};
template<typename T> CDTArrangement<T>::~CDTArrangement()
@@ -859,20 +859,20 @@ template<typename T> CDTFace<T> *CDTArrangement<T>::add_face()
return f;
}
-template<typename T> void CDTArrangement<T>::reserve(int num_verts, int num_edges, int num_faces)
+template<typename T> void CDTArrangement<T>::reserve(int verts_num, int edges_num, int faces_num)
{
/* These reserves are just guesses; OK if they aren't exactly right since vectors will resize. */
- this->verts.reserve(2 * num_verts);
- this->edges.reserve(3 * num_verts + 2 * num_edges + 3 * 2 * num_faces);
- this->faces.reserve(2 * num_verts + 2 * num_edges + 2 * num_faces);
+ this->verts.reserve(2 * verts_num);
+ this->edges.reserve(3 * verts_num + 2 * edges_num + 3 * 2 * faces_num);
+ this->faces.reserve(2 * verts_num + 2 * edges_num + 2 * faces_num);
}
template<typename T>
CDT_state<T>::CDT_state(
- int num_input_verts, int num_input_edges, int num_input_faces, T epsilon, bool need_ids)
+ int input_verts_num, int input_edges_num, int input_faces_num, T epsilon, bool need_ids)
{
- this->input_vert_tot = num_input_verts;
- this->cdt.reserve(num_input_verts, num_input_edges, num_input_faces);
+ this->input_vert_num = input_verts_num;
+ this->cdt.reserve(input_verts_num, input_edges_num, input_faces_num);
this->cdt.outer_face = this->cdt.add_face();
this->epsilon = epsilon;
this->need_ids = need_ids;
@@ -919,7 +919,7 @@ template<typename T> inline bool is_deleted_edge(const CDTEdge<T> *e)
template<typename T> inline bool is_original_vert(const CDTVert<T> *v, CDT_state<T> *cdt)
{
- return (v->index < cdt->input_vert_tot);
+ return (v->index < cdt->input_vert_num);
}
/**
@@ -2188,17 +2188,19 @@ static int power_of_10_greater_equal_to(int x)
}
/**
- Incrementally each edge of each input face as an edge constraint.
+ * Incrementally each edge of each input face as an edge constraint.
* The code will ensure that the #CDTEdge's created will have ids that tie them
* back to the original face edge (using a numbering system for those edges
* that starts with cdt->face_edge_offset, and continues with the edges in
* order around each face in turn. And then the next face starts at
* cdt->face_edge_offset beyond the start for the previous face.
+ * Return the number of faces added, which may be less than input.face.size()
+ * in the case that some faces have less than 3 sides.
*/
template<typename T>
-void add_face_constraints(CDT_state<T> *cdt_state,
- const CDT_input<T> &input,
- CDT_output_type output_type)
+int add_face_constraints(CDT_state<T> *cdt_state,
+ const CDT_input<T> &input,
+ CDT_output_type output_type)
{
int nv = input.vert.size();
int nf = input.face.size();
@@ -2216,6 +2218,7 @@ void add_face_constraints(CDT_state<T> *cdt_state,
* together the are >= INT_MAX, then the Delaunay calculation will take unreasonably long anyway.
*/
BLI_assert(INT_MAX / cdt_state->face_edge_offset > nf);
+ int faces_added = 0;
for (int f = 0; f < nf; f++) {
int flen = input.face[f].size();
if (flen <= 2) {
@@ -2231,6 +2234,7 @@ void add_face_constraints(CDT_state<T> *cdt_state,
/* Ignore face edges with invalid vertices. */
continue;
}
+ ++faces_added;
CDTVert<T> *v1 = cdt->get_vert_resolve_merge(iv1);
CDTVert<T> *v2 = cdt->get_vert_resolve_merge(iv2);
LinkNode *edge_list;
@@ -2265,6 +2269,7 @@ void add_face_constraints(CDT_state<T> *cdt_state,
}
}
}
+ return faces_added;
}
/* Delete_edge but try not to mess up outer face.
@@ -2642,7 +2647,8 @@ CDT_result<T> get_cdt_output(CDT_state<T> *cdt_state,
const CDT_input<T> UNUSED(input),
CDT_output_type output_type)
{
- prepare_cdt_for_output(cdt_state, output_type);
+ CDT_output_type oty = output_type;
+ prepare_cdt_for_output(cdt_state, oty);
CDT_result<T> result;
CDTArrangement<T> *cdt = &cdt_state->cdt;
result.face_edge_offset = cdt_state->face_edge_offset;
@@ -2672,7 +2678,7 @@ CDT_result<T> get_cdt_output(CDT_state<T> *cdt_state,
CDTVert<T> *v = cdt->verts[i];
if (v->merge_to_index != -1) {
if (cdt_state->need_ids) {
- if (i < cdt_state->input_vert_tot) {
+ if (i < cdt_state->input_vert_num) {
add_to_input_ids(cdt->verts[v->merge_to_index]->input_ids, i);
}
}
@@ -2690,7 +2696,7 @@ CDT_result<T> get_cdt_output(CDT_state<T> *cdt_state,
if (v->merge_to_index == -1) {
result.vert[i_out] = v->co.exact;
if (cdt_state->need_ids) {
- if (i < cdt_state->input_vert_tot) {
+ if (i < cdt_state->input_vert_num) {
result.vert_orig[i_out].append(i);
}
for (int vert : v->input_ids) {
@@ -2759,7 +2765,7 @@ CDT_result<T> get_cdt_output(CDT_state<T> *cdt_state,
*/
template<typename T> void add_input_verts(CDT_state<T> *cdt_state, const CDT_input<T> &input)
{
- for (int i = 0; i < cdt_state->input_vert_tot; ++i) {
+ for (int i = 0; i < cdt_state->input_vert_num; ++i) {
cdt_state->cdt.add_vert(input.vert[i]);
}
}
@@ -2774,7 +2780,11 @@ CDT_result<T> delaunay_calc(const CDT_input<T> &input, CDT_output_type output_ty
add_input_verts(&cdt_state, input);
initial_triangulation(&cdt_state.cdt);
add_edge_constraints(&cdt_state, input);
- add_face_constraints(&cdt_state, input, output_type);
+ int actual_nf = add_face_constraints(&cdt_state, input, output_type);
+ if (actual_nf == 0 && !ELEM(output_type, CDT_FULL, CDT_INSIDE, CDT_CONSTRAINTS)) {
+ /* Can't look for faces or holes if there were no valid input faces. */
+ output_type = CDT_INSIDE;
+ }
return get_cdt_output(&cdt_state, input, output_type);
}
diff --git a/source/blender/blenlib/intern/filereader_zstd.c b/source/blender/blenlib/intern/filereader_zstd.c
index 0a04a443e76..5f114f24fb0 100644
--- a/source/blender/blenlib/intern/filereader_zstd.c
+++ b/source/blender/blenlib/intern/filereader_zstd.c
@@ -25,7 +25,7 @@ typedef struct {
size_t in_buf_max_size;
struct {
- int num_frames;
+ int frames_num;
size_t *compressed_ofs;
size_t *uncompressed_ofs;
@@ -69,21 +69,21 @@ static bool zstd_read_seek_table(ZstdReader *zstd)
return false;
}
- uint32_t num_frames;
- if (base->seek(base, -9, SEEK_END) < 0 || !zstd_read_u32(base, &num_frames)) {
+ uint32_t frames_num;
+ if (base->seek(base, -9, SEEK_END) < 0 || !zstd_read_u32(base, &frames_num)) {
return false;
}
/* Each frame has either 2 or 3 uint32_t, and after that we have
- * num_frames, flags and magic for another 9 bytes. */
- uint32_t expected_frame_length = num_frames * (has_checksums ? 12 : 8) + 9;
+ * frames_num, flags and magic for another 9 bytes. */
+ uint32_t expected_frame_length = frames_num * (has_checksums ? 12 : 8) + 9;
/* The frame starts with another magic number and its length, but these
* two fields are not included when counting length. */
off64_t frame_start_ofs = 8 + expected_frame_length;
/* Sanity check: Before the start of the seek table frame,
- * there must be num_frames frames, each of which at least 8 bytes long. */
+ * there must be frames_num frames, each of which at least 8 bytes long. */
off64_t seek_frame_start = base->seek(base, -frame_start_ofs, SEEK_END);
- if (seek_frame_start < num_frames * 8) {
+ if (seek_frame_start < frames_num * 8) {
return false;
}
@@ -96,13 +96,13 @@ static bool zstd_read_seek_table(ZstdReader *zstd)
return false;
}
- zstd->seek.num_frames = num_frames;
- zstd->seek.compressed_ofs = MEM_malloc_arrayN(num_frames + 1, sizeof(size_t), __func__);
- zstd->seek.uncompressed_ofs = MEM_malloc_arrayN(num_frames + 1, sizeof(size_t), __func__);
+ zstd->seek.frames_num = frames_num;
+ zstd->seek.compressed_ofs = MEM_malloc_arrayN(frames_num + 1, sizeof(size_t), __func__);
+ zstd->seek.uncompressed_ofs = MEM_malloc_arrayN(frames_num + 1, sizeof(size_t), __func__);
size_t compressed_ofs = 0;
size_t uncompressed_ofs = 0;
- for (int i = 0; i < num_frames; i++) {
+ for (int i = 0; i < frames_num; i++) {
uint32_t compressed_size, uncompressed_size;
if (!zstd_read_u32(base, &compressed_size) || !zstd_read_u32(base, &uncompressed_size)) {
break;
@@ -115,8 +115,8 @@ static bool zstd_read_seek_table(ZstdReader *zstd)
compressed_ofs += compressed_size;
uncompressed_ofs += uncompressed_size;
}
- zstd->seek.compressed_ofs[num_frames] = compressed_ofs;
- zstd->seek.uncompressed_ofs[num_frames] = uncompressed_ofs;
+ zstd->seek.compressed_ofs[frames_num] = compressed_ofs;
+ zstd->seek.uncompressed_ofs[frames_num] = uncompressed_ofs;
/* Seek to the end of the previous frame for the following #BHead frame detection. */
if (seek_frame_start != compressed_ofs || base->seek(base, seek_frame_start, SEEK_SET) < 0) {
@@ -135,9 +135,9 @@ static bool zstd_read_seek_table(ZstdReader *zstd)
* Basically just bisection. */
static int zstd_frame_from_pos(ZstdReader *zstd, size_t pos)
{
- int low = 0, high = zstd->seek.num_frames;
+ int low = 0, high = zstd->seek.frames_num;
- if (pos >= zstd->seek.uncompressed_ofs[zstd->seek.num_frames]) {
+ if (pos >= zstd->seek.uncompressed_ofs[zstd->seek.frames_num]) {
return -1;
}
@@ -229,13 +229,13 @@ static off64_t zstd_seek(FileReader *reader, off64_t offset, int whence)
new_pos = offset;
}
else if (whence == SEEK_END) {
- new_pos = zstd->seek.uncompressed_ofs[zstd->seek.num_frames] + offset;
+ new_pos = zstd->seek.uncompressed_ofs[zstd->seek.frames_num] + offset;
}
else {
new_pos = zstd->reader.offset + offset;
}
- if (new_pos < 0 || new_pos > zstd->seek.uncompressed_ofs[zstd->seek.num_frames]) {
+ if (new_pos < 0 || new_pos > zstd->seek.uncompressed_ofs[zstd->seek.frames_num]) {
return -1;
}
zstd->reader.offset = new_pos;
diff --git a/source/blender/blenlib/intern/gsqueue.c b/source/blender/blenlib/intern/gsqueue.c
index 4bf4e15d864..b09f5113be7 100644
--- a/source/blender/blenlib/intern/gsqueue.c
+++ b/source/blender/blenlib/intern/gsqueue.c
@@ -33,7 +33,7 @@ struct _GSQueue {
size_t chunk_last_index; /* index into 'chunk_last' */
size_t chunk_elem_max; /* number of elements per chunk */
size_t elem_size; /* memory size of elements */
- size_t totelem; /* total number of elements */
+ size_t elem_num; /* total number of elements */
};
static void *queue_get_first_elem(GSQueue *queue)
@@ -97,7 +97,7 @@ void BLI_gsqueue_free(GSQueue *queue)
void BLI_gsqueue_push(GSQueue *queue, const void *item)
{
queue->chunk_last_index++;
- queue->totelem++;
+ queue->elem_num++;
if (UNLIKELY(queue->chunk_last_index == queue->chunk_elem_max)) {
struct QueueChunk *chunk;
@@ -134,9 +134,9 @@ void BLI_gsqueue_pop(GSQueue *queue, void *r_item)
memcpy(r_item, queue_get_first_elem(queue), queue->elem_size);
queue->chunk_first_index++;
- queue->totelem--;
+ queue->elem_num--;
- if (UNLIKELY(queue->chunk_first_index == queue->chunk_elem_max || queue->totelem == 0)) {
+ if (UNLIKELY(queue->chunk_first_index == queue->chunk_elem_max || queue->elem_num == 0)) {
struct QueueChunk *chunk_free = queue->chunk_first;
queue->chunk_first = queue->chunk_first->next;
@@ -153,7 +153,7 @@ void BLI_gsqueue_pop(GSQueue *queue, void *r_item)
size_t BLI_gsqueue_len(const GSQueue *queue)
{
- return queue->totelem;
+ return queue->elem_num;
}
bool BLI_gsqueue_is_empty(const GSQueue *queue)
diff --git a/source/blender/blenlib/intern/jitter_2d.c b/source/blender/blenlib/intern/jitter_2d.c
index 5e840e8178e..8fa0f2c1e15 100644
--- a/source/blender/blenlib/intern/jitter_2d.c
+++ b/source/blender/blenlib/intern/jitter_2d.c
@@ -126,7 +126,7 @@ void BLI_jitterate2(float (*jit1)[2], float (*jit2)[2], int num, float radius2)
void BLI_jitter_init(float (*jitarr)[2], int num)
{
float(*jit2)[2];
- float num_fl, num_fl_sqrt;
+ float number_fl, number_fl_sqrt;
float x, rad1, rad2, rad3;
RNG *rng;
int i;
@@ -135,20 +135,20 @@ void BLI_jitter_init(float (*jitarr)[2], int num)
return;
}
- num_fl = (float)num;
- num_fl_sqrt = sqrtf(num_fl);
+ number_fl = (float)num;
+ number_fl_sqrt = sqrtf(number_fl);
jit2 = MEM_mallocN(12 + (unsigned int)num * sizeof(float[2]), "initjit");
- rad1 = 1.0f / num_fl_sqrt;
- rad2 = 1.0f / num_fl;
- rad3 = num_fl_sqrt / num_fl;
+ rad1 = 1.0f / number_fl_sqrt;
+ rad2 = 1.0f / number_fl;
+ rad3 = number_fl_sqrt / number_fl;
rng = BLI_rng_new(31415926 + (unsigned int)num);
x = 0;
for (i = 0; i < num; i++) {
jitarr[i][0] = x + rad1 * (float)(0.5 - BLI_rng_get_double(rng));
- jitarr[i][1] = (float)i / num_fl + rad1 * (float)(0.5 - BLI_rng_get_double(rng));
+ jitarr[i][1] = (float)i / number_fl + rad1 * (float)(0.5 - BLI_rng_get_double(rng));
x += rad3;
x -= floorf(x);
}
diff --git a/source/blender/blenlib/intern/length_parameterize.cc b/source/blender/blenlib/intern/length_parameterize.cc
new file mode 100644
index 00000000000..d6862b96944
--- /dev/null
+++ b/source/blender/blenlib/intern/length_parameterize.cc
@@ -0,0 +1,80 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#include "BLI_length_parameterize.hh"
+
+namespace blender::length_parameterize {
+
+void create_uniform_samples(const Span<float> lengths,
+ const bool cyclic,
+ MutableSpan<int> indices,
+ MutableSpan<float> factors)
+{
+ const int count = indices.size();
+ BLI_assert(count > 0);
+ BLI_assert(lengths.size() >= 1);
+ BLI_assert(std::is_sorted(lengths.begin(), lengths.end()));
+ const int segments_num = lengths.size();
+ const int points_num = cyclic ? segments_num : segments_num + 1;
+
+ indices.first() = 0;
+ factors.first() = 0.0f;
+ if (count == 1) {
+ return;
+ }
+
+ const float total_length = lengths.last();
+ if (total_length == 0.0f) {
+ indices.fill(0);
+ factors.fill(0.0f);
+ return;
+ }
+
+ const float step_length = total_length / (count - (cyclic ? 0 : 1));
+ const float step_length_inv = 1.0f / step_length;
+
+ int i_dst = 1;
+ /* Store the length at the previous point in a variable so it can start out at zero
+ * (the lengths array doesn't contain 0 for the first point). */
+ float prev_length = 0.0f;
+ for (const int i_src : IndexRange(points_num - 1)) {
+ const float next_length = lengths[i_src];
+ const float segment_length = next_length - prev_length;
+ if (segment_length == 0.0f) {
+ continue;
+ }
+ /* Add every sample that fits in this segment. */
+ const float segment_length_inv = 1.0f / segment_length;
+ const int segment_samples_num = std::ceil(next_length * step_length_inv - i_dst);
+ indices.slice(i_dst, segment_samples_num).fill(i_src);
+
+ for (const int i : factors.index_range().slice(i_dst, segment_samples_num)) {
+ const float length_in_segment = step_length * i - prev_length;
+ factors[i] = length_in_segment * segment_length_inv;
+ }
+
+ i_dst += segment_samples_num;
+
+ prev_length = next_length;
+ }
+
+ /* Add the samples on the last cyclic segment if necessary, and also the samples
+ * that weren't created in the previous loop due to floating point inaccuracy. */
+ if (cyclic && lengths.size() > 1) {
+ indices.drop_front(i_dst).fill(points_num - 1);
+ const float segment_length = lengths.last() - lengths.last(1);
+ if (segment_length == 0.0f) {
+ return;
+ }
+ const float segment_length_inv = 1.0f / segment_length;
+ for (const int i : indices.index_range().drop_front(i_dst)) {
+ const float length_in_segment = step_length * i - prev_length;
+ factors[i] = length_in_segment * segment_length_inv;
+ }
+ }
+ else {
+ indices.drop_front(i_dst).fill(points_num - 2);
+ factors.drop_front(i_dst).fill(1.0f);
+ }
+}
+
+} // namespace blender::length_parameterize
diff --git a/source/blender/blenlib/intern/math_geom.c b/source/blender/blenlib/intern/math_geom.c
index e1ec22063e0..1b13493e00c 100644
--- a/source/blender/blenlib/intern/math_geom.c
+++ b/source/blender/blenlib/intern/math_geom.c
@@ -3404,7 +3404,7 @@ bool clip_segment_v3_plane(
bool clip_segment_v3_plane_n(const float p1[3],
const float p2[3],
const float plane_array[][4],
- const int plane_tot,
+ const int plane_num,
float r_p1[3],
float r_p2[3])
{
@@ -3414,7 +3414,7 @@ bool clip_segment_v3_plane_n(const float p1[3],
float dp[3];
sub_v3_v3v3(dp, p2, p1);
- for (int i = 0; i < plane_tot; i++) {
+ for (int i = 0; i < plane_num; i++) {
const float *plane = plane_array[i];
const float div = dot_v3v3(dp, plane);
diff --git a/source/blender/blenlib/intern/mesh_boolean.cc b/source/blender/blenlib/intern/mesh_boolean.cc
index 70030fc2bdf..700c126ca4c 100644
--- a/source/blender/blenlib/intern/mesh_boolean.cc
+++ b/source/blender/blenlib/intern/mesh_boolean.cc
@@ -171,9 +171,9 @@ TriMeshTopology::TriMeshTopology(const IMesh &tm)
/* If everything were manifold, `F+V-E=2` and `E=3F/2`.
* So an likely overestimate, allowing for non-manifoldness, is `E=2F` and `V=F`. */
const int estimate_num_edges = 2 * tm.face_size();
- const int estimate_num_verts = tm.face_size();
+ const int estimate_verts_num = tm.face_size();
edge_tri_.reserve(estimate_num_edges);
- vert_edges_.reserve(estimate_num_verts);
+ vert_edges_.reserve(estimate_verts_num);
for (int t : tm.face_index_range()) {
const Face &tri = *tm.face(t);
BLI_assert(tri.is_tri());
@@ -2607,18 +2607,18 @@ static void test_tri_inside_shapes(const IMesh &tm,
* Perturb their directions slightly to make it less likely to hit a seam.
* Ray-cast assumes they have unit length, so use r1 near 1 and
* ra near 0.5, and rb near .01, but normalized so `sqrt(r1^2 + ra^2 + rb^2) == 1`. */
- constexpr int num_rays = 6;
+ constexpr int rays_num = 6;
constexpr float r1 = 0.9987025295199663f;
constexpr float ra = 0.04993512647599832f;
constexpr float rb = 0.009987025295199663f;
- const float test_rays[num_rays][3] = {
+ const float test_rays[rays_num][3] = {
{r1, ra, rb}, {-r1, -ra, -rb}, {rb, r1, ra}, {-rb, -r1, -ra}, {ra, rb, r1}, {-ra, -rb, -r1}};
InsideShapeTestData data(tm, shape_fn, nshapes);
data.hit_parity = Array<int>(nshapes, 0);
Array<int> count_insides(nshapes, 0);
const float co[3] = {
float(offset_test_point[0]), float(offset_test_point[1]), float(offset_test_point[2])};
- for (int i = 0; i < num_rays; ++i) {
+ for (int i = 0; i < rays_num; ++i) {
if (dbg_level > 0) {
std::cout << "shoot ray " << i << "(" << test_rays[i][0] << "," << test_rays[i][1] << ","
<< test_rays[i][2] << ")\n";
@@ -2643,7 +2643,7 @@ static void test_tri_inside_shapes(const IMesh &tm,
in_shape[j] = 1.0f; /* Let's say a shape is always inside itself. */
}
else {
- in_shape[j] = float(count_insides[j]) / float(num_rays);
+ in_shape[j] = float(count_insides[j]) / float(rays_num);
}
if (dbg_level > 0) {
std::cout << "shape " << j << " inside = " << in_shape[j] << "\n";
@@ -3400,19 +3400,19 @@ static void dissolve_verts(IMesh *imesh, const Array<bool> dissolve, IMeshArena
for (int f : imesh->face_index_range()) {
const Face &face = *imesh->face(f);
face_pos_erase.clear();
- int num_erase = 0;
+ int erase_num = 0;
for (const Vert *v : face) {
int v_index = imesh->lookup_vert(v);
BLI_assert(v_index != NO_INDEX);
if (dissolve[v_index]) {
face_pos_erase.append(true);
- ++num_erase;
+ ++erase_num;
}
else {
face_pos_erase.append(false);
}
}
- if (num_erase > 0) {
+ if (erase_num > 0) {
any_faces_erased |= imesh->erase_face_positions(f, face_pos_erase, arena);
}
}
@@ -3475,8 +3475,8 @@ static IMesh polymesh_from_trimesh_with_dissolve(const IMesh &tm_out,
if (dbg_level > 1) {
std::cout << "merge tris for face " << in_f << "\n";
}
- int num_out_tris_for_face = face_output_tris.size();
- if (num_out_tris_for_face == 0) {
+ int out_tris_for_face_num = face_output_tris.size();
+ if (out_tris_for_face_num == 0) {
continue;
}
face_output_face[in_f] = merge_tris_for_face(face_output_tris[in_f], tm_out, imesh_in, arena);
diff --git a/source/blender/blenlib/intern/mesh_intersect.cc b/source/blender/blenlib/intern/mesh_intersect.cc
index 96ae0750899..d5585f953ec 100644
--- a/source/blender/blenlib/intern/mesh_intersect.cc
+++ b/source/blender/blenlib/intern/mesh_intersect.cc
@@ -635,8 +635,8 @@ void IMesh::populate_vert()
/* This is likely an overestimate, since verts are shared between
* faces. It is ok if estimate is over or even under. */
constexpr int ESTIMATE_VERTS_PER_FACE = 4;
- int estimate_num_verts = ESTIMATE_VERTS_PER_FACE * face_.size();
- populate_vert(estimate_num_verts);
+ int estimate_verts_num = ESTIMATE_VERTS_PER_FACE * face_.size();
+ populate_vert(estimate_verts_num);
}
void IMesh::populate_vert(int max_verts)
@@ -693,16 +693,16 @@ bool IMesh::erase_face_positions(int f_index, Span<bool> face_pos_erase, IMeshAr
{
const Face *cur_f = this->face(f_index);
int cur_len = cur_f->size();
- int num_to_erase = 0;
+ int to_erase_num = 0;
for (int i : cur_f->index_range()) {
if (face_pos_erase[i]) {
- ++num_to_erase;
+ ++to_erase_num;
}
}
- if (num_to_erase == 0) {
+ if (to_erase_num == 0) {
return false;
}
- int new_len = cur_len - num_to_erase;
+ int new_len = cur_len - to_erase_num;
if (new_len < 3) {
/* This erase causes removal of whole face.
* Because this may be called from a loop over the face array,
@@ -2324,7 +2324,7 @@ class TriOverlaps {
BVHTree *tree_b_{nullptr};
BVHTreeOverlap *overlap_{nullptr};
Array<int> first_overlap_;
- uint overlap_tot_{0};
+ uint overlap_num_{0};
struct CBData {
const IMesh &tm;
@@ -2386,16 +2386,16 @@ class TriOverlaps {
if (two_trees_no_self) {
BLI_bvhtree_balance(tree_b_);
/* Don't expect a lot of trivial intersects in this case. */
- overlap_ = BLI_bvhtree_overlap(tree_, tree_b_, &overlap_tot_, nullptr, nullptr);
+ overlap_ = BLI_bvhtree_overlap(tree_, tree_b_, &overlap_num_, nullptr, nullptr);
}
else {
CBData cbdata{tm, shape_fn, nshapes, use_self};
if (nshapes == 1) {
- overlap_ = BLI_bvhtree_overlap(tree_, tree_, &overlap_tot_, nullptr, nullptr);
+ overlap_ = BLI_bvhtree_overlap(tree_, tree_, &overlap_num_, nullptr, nullptr);
}
else {
overlap_ = BLI_bvhtree_overlap(
- tree_, tree_, &overlap_tot_, only_different_shapes, &cbdata);
+ tree_, tree_, &overlap_num_, only_different_shapes, &cbdata);
}
}
/* The rest of the code is simpler and easier to parallelize if, in the two-trees case,
@@ -2403,23 +2403,23 @@ class TriOverlaps {
* in the repeated part, sorting will then bring things with indexB together. */
if (two_trees_no_self) {
overlap_ = static_cast<BVHTreeOverlap *>(
- MEM_reallocN(overlap_, 2 * overlap_tot_ * sizeof(overlap_[0])));
- for (uint i = 0; i < overlap_tot_; ++i) {
- overlap_[overlap_tot_ + i].indexA = overlap_[i].indexB;
- overlap_[overlap_tot_ + i].indexB = overlap_[i].indexA;
+ MEM_reallocN(overlap_, 2 * overlap_num_ * sizeof(overlap_[0])));
+ for (uint i = 0; i < overlap_num_; ++i) {
+ overlap_[overlap_num_ + i].indexA = overlap_[i].indexB;
+ overlap_[overlap_num_ + i].indexB = overlap_[i].indexA;
}
- overlap_tot_ += overlap_tot_;
+ overlap_num_ += overlap_num_;
}
/* Sort the overlaps to bring all the intersects with a given indexA together. */
- std::sort(overlap_, overlap_ + overlap_tot_, bvhtreeverlap_cmp);
+ std::sort(overlap_, overlap_ + overlap_num_, bvhtreeverlap_cmp);
if (dbg_level > 0) {
- std::cout << overlap_tot_ << " overlaps found:\n";
+ std::cout << overlap_num_ << " overlaps found:\n";
for (BVHTreeOverlap ov : overlap()) {
std::cout << "A: " << ov.indexA << ", B: " << ov.indexB << "\n";
}
}
first_overlap_ = Array<int>(tm.face_size(), -1);
- for (int i = 0; i < static_cast<int>(overlap_tot_); ++i) {
+ for (int i = 0; i < static_cast<int>(overlap_num_); ++i) {
int t = overlap_[i].indexA;
if (first_overlap_[t] == -1) {
first_overlap_[t] = i;
@@ -2442,7 +2442,7 @@ class TriOverlaps {
Span<BVHTreeOverlap> overlap() const
{
- return Span<BVHTreeOverlap>(overlap_, overlap_tot_);
+ return Span<BVHTreeOverlap>(overlap_, overlap_num_);
}
int first_overlap_index(int t) const
@@ -2557,13 +2557,13 @@ static void calc_subdivided_non_cluster_tris(Array<IMesh> &r_tri_subdivided,
int len;
};
Vector<OverlapTriRange> overlap_tri_range;
- int overlap_tot = overlap.size();
- overlap_tri_range.reserve(overlap_tot);
+ int overlap_num = overlap.size();
+ overlap_tri_range.reserve(overlap_num);
int overlap_index = 0;
- while (overlap_index < overlap_tot) {
+ while (overlap_index < overlap_num) {
int t = overlap[overlap_index].indexA;
int i = overlap_index;
- while (i + 1 < overlap_tot && overlap[i + 1].indexA == t) {
+ while (i + 1 < overlap_num && overlap[i + 1].indexA == t) {
++i;
}
/* Now overlap[overlap_index] to overlap[i] have indexA == t.
@@ -2581,8 +2581,8 @@ static void calc_subdivided_non_cluster_tris(Array<IMesh> &r_tri_subdivided,
}
overlap_index = i + 1;
}
- int overlap_tri_range_tot = overlap_tri_range.size();
- Array<CDT_data> cd_data(overlap_tri_range_tot);
+ int overlap_tri_range_num = overlap_tri_range.size();
+ Array<CDT_data> cd_data(overlap_tri_range_num);
int grain_size = 64;
threading::parallel_for(overlap_tri_range.index_range(), grain_size, [&](IndexRange range) {
for (int otr_index : range) {
diff --git a/source/blender/blenlib/intern/path_util.c b/source/blender/blenlib/intern/path_util.c
index 6c576627fa0..5a96221c8d1 100644
--- a/source/blender/blenlib/intern/path_util.c
+++ b/source/blender/blenlib/intern/path_util.c
@@ -53,7 +53,7 @@ static bool BLI_path_is_abs(const char *name);
/* implementation */
-int BLI_path_sequence_decode(const char *string, char *head, char *tail, ushort *r_num_len)
+int BLI_path_sequence_decode(const char *string, char *head, char *tail, ushort *r_digits_len)
{
uint nums = 0, nume = 0;
int i;
@@ -98,8 +98,8 @@ int BLI_path_sequence_decode(const char *string, char *head, char *tail, ushort
strcpy(head, string);
head[nums] = 0;
}
- if (r_num_len) {
- *r_num_len = nume - nums + 1;
+ if (r_digits_len) {
+ *r_digits_len = nume - nums + 1;
}
return (int)ret;
}
@@ -114,8 +114,8 @@ int BLI_path_sequence_decode(const char *string, char *head, char *tail, ushort
*/
BLI_strncpy(head, string, name_end + 1);
}
- if (r_num_len) {
- *r_num_len = 0;
+ if (r_digits_len) {
+ *r_digits_len = 0;
}
return 0;
}
@@ -750,14 +750,14 @@ bool BLI_path_frame_range(char *path, int sta, int end, int digits)
return false;
}
-bool BLI_path_frame_get(char *path, int *r_frame, int *r_numdigits)
+bool BLI_path_frame_get(char *path, int *r_frame, int *r_digits_len)
{
if (*path) {
char *file = (char *)BLI_path_slash_rfind(path);
char *c;
- int len, numdigits;
+ int len, digits_len;
- numdigits = *r_numdigits = 0;
+ digits_len = *r_digits_len = 0;
if (file == NULL) {
file = path;
@@ -779,21 +779,21 @@ bool BLI_path_frame_get(char *path, int *r_frame, int *r_numdigits)
/* find start of number */
while (c != (file - 1) && isdigit(*c)) {
c--;
- numdigits++;
+ digits_len++;
}
- if (numdigits) {
+ if (digits_len) {
char prevchar;
c++;
- prevchar = c[numdigits];
- c[numdigits] = 0;
+ prevchar = c[digits_len];
+ c[digits_len] = 0;
/* was the number really an extension? */
*r_frame = atoi(c);
- c[numdigits] = prevchar;
+ c[digits_len] = prevchar;
- *r_numdigits = numdigits;
+ *r_digits_len = digits_len;
return true;
}
@@ -812,7 +812,7 @@ void BLI_path_frame_strip(char *path, char *r_ext)
char *file = (char *)BLI_path_slash_rfind(path);
char *c, *suffix;
int len;
- int numdigits = 0;
+ int digits_len = 0;
if (file == NULL) {
file = path;
@@ -836,7 +836,7 @@ void BLI_path_frame_strip(char *path, char *r_ext)
/* find start of number */
while (c != (file - 1) && isdigit(*c)) {
c--;
- numdigits++;
+ digits_len++;
}
c++;
@@ -845,7 +845,7 @@ void BLI_path_frame_strip(char *path, char *r_ext)
BLI_strncpy(r_ext, suffix, suffix_length + 1);
/* replace the number with the suffix and terminate the string */
- while (numdigits--) {
+ while (digits_len--) {
*c++ = '#';
}
*c = '\0';
diff --git a/source/blender/blenlib/intern/polyfill_2d.c b/source/blender/blenlib/intern/polyfill_2d.c
index 76cf7880c7a..eed87eda436 100644
--- a/source/blender/blenlib/intern/polyfill_2d.c
+++ b/source/blender/blenlib/intern/polyfill_2d.c
@@ -100,7 +100,7 @@ struct KDTree2D {
KDTreeNode2D *nodes;
const float (*coords)[2];
uint root;
- uint totnode;
+ uint node_num;
uint *nodes_map; /* index -> node lookup */
};
@@ -119,14 +119,14 @@ typedef struct PolyFill {
struct PolyIndex *indices; /* vertex aligned */
const float (*coords)[2];
- uint coords_tot;
+ uint coords_num;
#ifdef USE_CONVEX_SKIP
- uint coords_tot_concave;
+ uint coords_num_concave;
#endif
/* A polygon with n vertices has a triangulation of n-2 triangles. */
uint (*tris)[3];
- uint tris_tot;
+ uint tris_num;
#ifdef USE_KDTREE
struct KDTree2D kdtree;
@@ -202,18 +202,18 @@ static void kdtree2d_new(struct KDTree2D *tree, uint tot, const float (*coords)[
// tree->nodes = nodes;
tree->coords = coords;
tree->root = KDNODE_UNSET;
- tree->totnode = tot;
+ tree->node_num = tot;
}
/**
* no need for kdtree2d_insert, since we know the coords array.
*/
-static void kdtree2d_init(struct KDTree2D *tree, const uint coords_tot, const PolyIndex *indices)
+static void kdtree2d_init(struct KDTree2D *tree, const uint coords_num, const PolyIndex *indices)
{
KDTreeNode2D *node;
uint i;
- for (i = 0, node = tree->nodes; i < coords_tot; i++) {
+ for (i = 0, node = tree->nodes; i < coords_num; i++) {
if (indices[i].sign != CONVEX) {
node->neg = node->pos = KDNODE_UNSET;
node->index = indices[i].index;
@@ -223,26 +223,26 @@ static void kdtree2d_init(struct KDTree2D *tree, const uint coords_tot, const Po
}
}
- BLI_assert(tree->totnode == (uint)(node - tree->nodes));
+ BLI_assert(tree->node_num == (uint)(node - tree->nodes));
}
static uint kdtree2d_balance_recursive(
- KDTreeNode2D *nodes, uint totnode, axis_t axis, const float (*coords)[2], const uint ofs)
+ KDTreeNode2D *nodes, uint node_num, axis_t axis, const float (*coords)[2], const uint ofs)
{
KDTreeNode2D *node;
uint neg, pos, median, i, j;
- if (totnode <= 0) {
+ if (node_num <= 0) {
return KDNODE_UNSET;
}
- if (totnode == 1) {
+ if (node_num == 1) {
return 0 + ofs;
}
/* Quick-sort style sorting around median. */
neg = 0;
- pos = totnode - 1;
- median = totnode / 2;
+ pos = node_num - 1;
+ median = node_num / 2;
while (pos > neg) {
const float co = coords[nodes[pos].index][axis];
@@ -276,14 +276,14 @@ static uint kdtree2d_balance_recursive(
axis = !axis;
node->neg = kdtree2d_balance_recursive(nodes, median, axis, coords, ofs);
node->pos = kdtree2d_balance_recursive(
- &nodes[median + 1], (totnode - (median + 1)), axis, coords, (median + 1) + ofs);
+ &nodes[median + 1], (node_num - (median + 1)), axis, coords, (median + 1) + ofs);
return median + ofs;
}
static void kdtree2d_balance(struct KDTree2D *tree)
{
- tree->root = kdtree2d_balance_recursive(tree->nodes, tree->totnode, 0, tree->coords, 0);
+ tree->root = kdtree2d_balance_recursive(tree->nodes, tree->node_num, 0, tree->coords, 0);
}
static void kdtree2d_init_mapping(struct KDTree2D *tree)
@@ -291,7 +291,7 @@ static void kdtree2d_init_mapping(struct KDTree2D *tree)
uint i;
KDTreeNode2D *node;
- for (i = 0, node = tree->nodes; i < tree->totnode; i++, node++) {
+ for (i = 0, node = tree->nodes; i < tree->node_num; i++, node++) {
if (node->neg != KDNODE_UNSET) {
tree->nodes[node->neg].parent = i;
}
@@ -319,7 +319,7 @@ static void kdtree2d_node_remove(struct KDTree2D *tree, uint index)
tree->nodes_map[index] = KDNODE_UNSET;
node = &tree->nodes[node_index];
- tree->totnode -= 1;
+ tree->node_num -= 1;
BLI_assert((node->flag & KDNODE_FLAG_REMOVED) == 0);
node->flag |= KDNODE_FLAG_REMOVED;
@@ -435,14 +435,14 @@ static bool kdtree2d_isect_tri(struct KDTree2D *tree, const uint ind[3])
static uint *pf_tri_add(PolyFill *pf)
{
- return pf->tris[pf->tris_tot++];
+ return pf->tris[pf->tris_num++];
}
static void pf_coord_remove(PolyFill *pf, PolyIndex *pi)
{
#ifdef USE_KDTREE
/* avoid double lookups, since convex coords are ignored when testing intersections */
- if (pf->kdtree.totnode) {
+ if (pf->kdtree.node_num) {
kdtree2d_node_remove(&pf->kdtree, pi->index);
}
#endif
@@ -458,7 +458,7 @@ static void pf_coord_remove(PolyFill *pf, PolyIndex *pi)
pi->next = pi->prev = NULL;
#endif
- pf->coords_tot -= 1;
+ pf->coords_num -= 1;
}
static void pf_triangulate(PolyFill *pf)
@@ -473,7 +473,7 @@ static void pf_triangulate(PolyFill *pf)
bool reverse = false;
#endif
- while (pf->coords_tot > 3) {
+ while (pf->coords_num > 3) {
PolyIndex *pi_prev, *pi_next;
eSign sign_orig_prev, sign_orig_next;
@@ -490,7 +490,7 @@ static void pf_triangulate(PolyFill *pf)
#ifdef USE_CONVEX_SKIP
if (pi_ear->sign != CONVEX) {
- pf->coords_tot_concave -= 1;
+ pf->coords_num_concave -= 1;
}
#endif
@@ -509,7 +509,7 @@ static void pf_triangulate(PolyFill *pf)
pf_coord_sign_calc(pf, pi_prev);
#ifdef USE_CONVEX_SKIP
if (pi_prev->sign == CONVEX) {
- pf->coords_tot_concave -= 1;
+ pf->coords_num_concave -= 1;
# ifdef USE_KDTREE
kdtree2d_node_remove(&pf->kdtree, pi_prev->index);
# endif
@@ -520,7 +520,7 @@ static void pf_triangulate(PolyFill *pf)
pf_coord_sign_calc(pf, pi_next);
#ifdef USE_CONVEX_SKIP
if (pi_next->sign == CONVEX) {
- pf->coords_tot_concave -= 1;
+ pf->coords_num_concave -= 1;
# ifdef USE_KDTREE
kdtree2d_node_remove(&pf->kdtree, pi_next->index);
# endif
@@ -551,7 +551,7 @@ static void pf_triangulate(PolyFill *pf)
#endif
}
- if (pf->coords_tot == 3) {
+ if (pf->coords_num == 3) {
uint *tri = pf_tri_add(pf);
pi_ear = pf->indices;
tri[0] = pi_ear->index;
@@ -585,7 +585,7 @@ static PolyIndex *pf_ear_tip_find(PolyFill *pf
)
{
/* localize */
- const uint coords_tot = pf->coords_tot;
+ const uint coords_num = pf->coords_num;
PolyIndex *pi_ear;
uint i;
@@ -596,7 +596,7 @@ static PolyIndex *pf_ear_tip_find(PolyFill *pf
pi_ear = pf->indices;
#endif
- i = coords_tot;
+ i = coords_num;
while (i--) {
if (pf_ear_tip_check(pf, pi_ear)) {
return pi_ear;
@@ -626,7 +626,7 @@ static PolyIndex *pf_ear_tip_find(PolyFill *pf
pi_ear = pf->indices;
#endif
- i = coords_tot;
+ i = coords_num;
while (i--) {
if (pi_ear->sign != CONCAVE) {
return pi_ear;
@@ -649,7 +649,7 @@ static bool pf_ear_tip_check(PolyFill *pf, PolyIndex *pi_ear_tip)
#endif
#if defined(USE_CONVEX_SKIP) && !defined(USE_KDTREE)
- uint coords_tot_concave_checked = 0;
+ uint coords_num_concave_checked = 0;
#endif
#ifdef USE_CONVEX_SKIP
@@ -657,19 +657,19 @@ static bool pf_ear_tip_check(PolyFill *pf, PolyIndex *pi_ear_tip)
# ifdef USE_CONVEX_SKIP_TEST
/* check if counting is wrong */
{
- uint coords_tot_concave_test = 0;
+ uint coords_num_concave_test = 0;
PolyIndex *pi_iter = pi_ear_tip;
do {
if (pi_iter->sign != CONVEX) {
- coords_tot_concave_test += 1;
+ coords_num_concave_test += 1;
}
} while ((pi_iter = pi_iter->next) != pi_ear_tip);
- BLI_assert(coords_tot_concave_test == pf->coords_tot_concave);
+ BLI_assert(coords_num_concave_test == pf->coords_num_concave);
}
# endif
/* fast-path for circles */
- if (pf->coords_tot_concave == 0) {
+ if (pf->coords_num_concave == 0) {
return true;
}
#endif
@@ -715,8 +715,8 @@ static bool pf_ear_tip_check(PolyFill *pf, PolyIndex *pi_ear_tip)
}
# ifdef USE_CONVEX_SKIP
- coords_tot_concave_checked += 1;
- if (coords_tot_concave_checked == pf->coords_tot_concave) {
+ coords_num_concave_checked += 1;
+ if (coords_num_concave_checked == pf->coords_num_concave) {
break;
}
# endif
@@ -743,7 +743,7 @@ static void pf_ear_tip_cut(PolyFill *pf, PolyIndex *pi_ear_tip)
*/
static void polyfill_prepare(PolyFill *pf,
const float (*coords)[2],
- const uint coords_tot,
+ const uint coords_num,
int coords_sign,
uint (*r_tris)[3],
PolyIndex *r_indices)
@@ -756,32 +756,32 @@ static void polyfill_prepare(PolyFill *pf,
/* assign all polyfill members here */
pf->indices = r_indices;
pf->coords = coords;
- pf->coords_tot = coords_tot;
+ pf->coords_num = coords_num;
#ifdef USE_CONVEX_SKIP
- pf->coords_tot_concave = 0;
+ pf->coords_num_concave = 0;
#endif
pf->tris = r_tris;
- pf->tris_tot = 0;
+ pf->tris_num = 0;
if (coords_sign == 0) {
- coords_sign = (cross_poly_v2(coords, coords_tot) >= 0.0f) ? 1 : -1;
+ coords_sign = (cross_poly_v2(coords, coords_num) >= 0.0f) ? 1 : -1;
}
else {
/* check we're passing in correct args */
#ifdef USE_STRICT_ASSERT
# ifndef NDEBUG
if (coords_sign == 1) {
- BLI_assert(cross_poly_v2(coords, coords_tot) >= 0.0f);
+ BLI_assert(cross_poly_v2(coords, coords_num) >= 0.0f);
}
else {
- BLI_assert(cross_poly_v2(coords, coords_tot) <= 0.0f);
+ BLI_assert(cross_poly_v2(coords, coords_num) <= 0.0f);
}
# endif
#endif
}
if (coords_sign == 1) {
- for (i = 0; i < coords_tot; i++) {
+ for (i = 0; i < coords_num; i++) {
indices[i].next = &indices[i + 1];
indices[i].prev = &indices[i - 1];
indices[i].index = i;
@@ -789,22 +789,22 @@ static void polyfill_prepare(PolyFill *pf,
}
else {
/* reversed */
- uint n = coords_tot - 1;
- for (i = 0; i < coords_tot; i++) {
+ uint n = coords_num - 1;
+ for (i = 0; i < coords_num; i++) {
indices[i].next = &indices[i + 1];
indices[i].prev = &indices[i - 1];
indices[i].index = (n - i);
}
}
- indices[0].prev = &indices[coords_tot - 1];
- indices[coords_tot - 1].next = &indices[0];
+ indices[0].prev = &indices[coords_num - 1];
+ indices[coords_num - 1].next = &indices[0];
- for (i = 0; i < coords_tot; i++) {
+ for (i = 0; i < coords_num; i++) {
PolyIndex *pi = &indices[i];
pf_coord_sign_calc(pf, pi);
#ifdef USE_CONVEX_SKIP
if (pi->sign != CONVEX) {
- pf->coords_tot_concave += 1;
+ pf->coords_num_concave += 1;
}
#endif
}
@@ -814,11 +814,11 @@ static void polyfill_calc(PolyFill *pf)
{
#ifdef USE_KDTREE
# ifdef USE_CONVEX_SKIP
- if (pf->coords_tot_concave)
+ if (pf->coords_num_concave)
# endif
{
- kdtree2d_new(&pf->kdtree, pf->coords_tot_concave, pf->coords);
- kdtree2d_init(&pf->kdtree, pf->coords_tot, pf->indices);
+ kdtree2d_new(&pf->kdtree, pf->coords_num_concave, pf->coords);
+ kdtree2d_init(&pf->kdtree, pf->coords_num, pf->indices);
kdtree2d_balance(&pf->kdtree);
kdtree2d_init_mapping(&pf->kdtree);
}
@@ -828,14 +828,14 @@ static void polyfill_calc(PolyFill *pf)
}
void BLI_polyfill_calc_arena(const float (*coords)[2],
- const uint coords_tot,
+ const uint coords_num,
const int coords_sign,
uint (*r_tris)[3],
struct MemArena *arena)
{
PolyFill pf;
- PolyIndex *indices = BLI_memarena_alloc(arena, sizeof(*indices) * coords_tot);
+ PolyIndex *indices = BLI_memarena_alloc(arena, sizeof(*indices) * coords_num);
#ifdef DEBUG_TIME
TIMEIT_START(polyfill2d);
@@ -843,22 +843,22 @@ void BLI_polyfill_calc_arena(const float (*coords)[2],
polyfill_prepare(&pf,
coords,
- coords_tot,
+ coords_num,
coords_sign,
r_tris,
/* cache */
indices);
#ifdef USE_KDTREE
- if (pf.coords_tot_concave) {
- pf.kdtree.nodes = BLI_memarena_alloc(arena, sizeof(*pf.kdtree.nodes) * pf.coords_tot_concave);
+ if (pf.coords_num_concave) {
+ pf.kdtree.nodes = BLI_memarena_alloc(arena, sizeof(*pf.kdtree.nodes) * pf.coords_num_concave);
pf.kdtree.nodes_map = memset(
- BLI_memarena_alloc(arena, sizeof(*pf.kdtree.nodes_map) * coords_tot),
+ BLI_memarena_alloc(arena, sizeof(*pf.kdtree.nodes_map) * coords_num),
0xff,
- sizeof(*pf.kdtree.nodes_map) * coords_tot);
+ sizeof(*pf.kdtree.nodes_map) * coords_num);
}
else {
- pf.kdtree.totnode = 0;
+ pf.kdtree.node_num = 0;
}
#endif
@@ -873,25 +873,25 @@ void BLI_polyfill_calc_arena(const float (*coords)[2],
}
void BLI_polyfill_calc(const float (*coords)[2],
- const uint coords_tot,
+ const uint coords_num,
const int coords_sign,
uint (*r_tris)[3])
{
/* Fallback to heap memory for large allocations.
* Avoid running out of stack memory on systems with 512kb stack (macOS).
* This happens at around 13,000 points, use a much lower value to be safe. */
- if (UNLIKELY(coords_tot > 8192)) {
+ if (UNLIKELY(coords_num > 8192)) {
/* The buffer size only accounts for the index allocation,
* worst case we do two allocations when concave, while we should try to be efficient,
* any caller that relies on this frequently should use #BLI_polyfill_calc_arena directly. */
- MemArena *arena = BLI_memarena_new(sizeof(PolyIndex) * coords_tot, __func__);
- BLI_polyfill_calc_arena(coords, coords_tot, coords_sign, r_tris, arena);
+ MemArena *arena = BLI_memarena_new(sizeof(PolyIndex) * coords_num, __func__);
+ BLI_polyfill_calc_arena(coords, coords_num, coords_sign, r_tris, arena);
BLI_memarena_free(arena);
return;
}
PolyFill pf;
- PolyIndex *indices = BLI_array_alloca(indices, coords_tot);
+ PolyIndex *indices = BLI_array_alloca(indices, coords_num);
#ifdef DEBUG_TIME
TIMEIT_START(polyfill2d);
@@ -899,21 +899,21 @@ void BLI_polyfill_calc(const float (*coords)[2],
polyfill_prepare(&pf,
coords,
- coords_tot,
+ coords_num,
coords_sign,
r_tris,
/* cache */
indices);
#ifdef USE_KDTREE
- if (pf.coords_tot_concave) {
- pf.kdtree.nodes = BLI_array_alloca(pf.kdtree.nodes, pf.coords_tot_concave);
- pf.kdtree.nodes_map = memset(BLI_array_alloca(pf.kdtree.nodes_map, coords_tot),
+ if (pf.coords_num_concave) {
+ pf.kdtree.nodes = BLI_array_alloca(pf.kdtree.nodes, pf.coords_num_concave);
+ pf.kdtree.nodes_map = memset(BLI_array_alloca(pf.kdtree.nodes_map, coords_num),
0xff,
- sizeof(*pf.kdtree.nodes_map) * coords_tot);
+ sizeof(*pf.kdtree.nodes_map) * coords_num);
}
else {
- pf.kdtree.totnode = 0;
+ pf.kdtree.node_num = 0;
}
#endif
diff --git a/source/blender/blenlib/intern/polyfill_2d_beautify.c b/source/blender/blenlib/intern/polyfill_2d_beautify.c
index c527e88b440..38cf97d6a8f 100644
--- a/source/blender/blenlib/intern/polyfill_2d_beautify.c
+++ b/source/blender/blenlib/intern/polyfill_2d_beautify.c
@@ -288,15 +288,15 @@ static void polyedge_rotate(struct HalfEdge *edges, struct HalfEdge *e)
}
void BLI_polyfill_beautify(const float (*coords)[2],
- const uint coords_tot,
+ const uint coords_num,
uint (*tris)[3],
/* structs for reuse */
MemArena *arena,
Heap *eheap)
{
- const uint coord_last = coords_tot - 1;
- const uint tris_len = coords_tot - 2;
+ const uint coord_last = coords_num - 1;
+ const uint tris_len = coords_num - 2;
/* internal edges only (between 2 tris) */
const uint edges_len = tris_len - 1;
diff --git a/source/blender/blenlib/intern/rand.cc b/source/blender/blenlib/intern/rand.cc
index 17bf5585f3f..f6d91cdcc4f 100644
--- a/source/blender/blenlib/intern/rand.cc
+++ b/source/blender/blenlib/intern/rand.cc
@@ -117,18 +117,18 @@ void BLI_rng_get_tri_sample_float_v3(
copy_v3_v3(r_pt, rng->rng.get_triangle_sample_3d(v1, v2, v3));
}
-void BLI_rng_shuffle_array(RNG *rng, void *data, unsigned int elem_size_i, unsigned int elem_tot)
+void BLI_rng_shuffle_array(RNG *rng, void *data, unsigned int elem_size_i, unsigned int elem_num)
{
- if (elem_tot <= 1) {
+ if (elem_num <= 1) {
return;
}
const uint elem_size = elem_size_i;
- unsigned int i = elem_tot;
+ unsigned int i = elem_num;
void *temp = malloc(elem_size);
while (i--) {
- const unsigned int j = BLI_rng_get_uint(rng) % elem_tot;
+ const unsigned int j = BLI_rng_get_uint(rng) % elem_num;
if (i != j) {
void *iElem = (unsigned char *)data + i * elem_size_i;
void *jElem = (unsigned char *)data + j * elem_size_i;
@@ -141,15 +141,15 @@ void BLI_rng_shuffle_array(RNG *rng, void *data, unsigned int elem_size_i, unsig
free(temp);
}
-void BLI_rng_shuffle_bitmap(struct RNG *rng, BLI_bitmap *bitmap, unsigned int bits_tot)
+void BLI_rng_shuffle_bitmap(struct RNG *rng, BLI_bitmap *bitmap, unsigned int bits_num)
{
- if (bits_tot <= 1) {
+ if (bits_num <= 1) {
return;
}
- unsigned int i = bits_tot;
+ unsigned int i = bits_num;
while (i--) {
- const unsigned int j = BLI_rng_get_uint(rng) % bits_tot;
+ const unsigned int j = BLI_rng_get_uint(rng) % bits_num;
if (i != j) {
const bool i_bit = BLI_BITMAP_TEST(bitmap, i);
const bool j_bit = BLI_BITMAP_TEST(bitmap, j);
@@ -187,21 +187,21 @@ float BLI_hash_frand(unsigned int seed)
void BLI_array_randomize(void *data,
unsigned int elem_size,
- unsigned int elem_tot,
+ unsigned int elem_num,
unsigned int seed)
{
RNG rng;
BLI_rng_seed(&rng, seed);
- BLI_rng_shuffle_array(&rng, data, elem_size, elem_tot);
+ BLI_rng_shuffle_array(&rng, data, elem_size, elem_num);
}
-void BLI_bitmap_randomize(BLI_bitmap *bitmap, unsigned int bits_tot, unsigned int seed)
+void BLI_bitmap_randomize(BLI_bitmap *bitmap, unsigned int bits_num, unsigned int seed)
{
RNG rng;
BLI_rng_seed(&rng, seed);
- BLI_rng_shuffle_bitmap(&rng, bitmap, bits_tot);
+ BLI_rng_shuffle_bitmap(&rng, bitmap, bits_num);
}
/* ********* for threaded random ************** */
diff --git a/source/blender/blenlib/intern/scanfill.c b/source/blender/blenlib/intern/scanfill.c
index 7e9893925a4..32932c3dee1 100644
--- a/source/blender/blenlib/intern/scanfill.c
+++ b/source/blender/blenlib/intern/scanfill.c
@@ -124,7 +124,7 @@ ScanFillVert *BLI_scanfill_vert_add(ScanFillContext *sf_ctx, const float vec[3])
zero_v2(sf_v->xy);
sf_v->keyindex = 0;
sf_v->poly_nr = sf_ctx->poly_nr;
- sf_v->edge_tot = 0;
+ sf_v->edge_count = 0;
sf_v->f = SF_VERT_NEW;
sf_v->user_flag = 0;
@@ -373,14 +373,14 @@ static bool boundinsideEV(ScanFillEdge *eed, ScanFillVert *eve)
static void testvertexnearedge(ScanFillContext *sf_ctx)
{
- /* only vertices with (->edge_tot == 1) are being tested for
+ /* only vertices with (->edge_count == 1) are being tested for
* being close to an edge, if true insert */
ScanFillVert *eve;
ScanFillEdge *eed, *ed1;
for (eve = sf_ctx->fillvertbase.first; eve; eve = eve->next) {
- if (eve->edge_tot == 1) {
+ if (eve->edge_count == 1) {
/* find the edge which has vertex eve,
* NOTE: we _know_ this will crash if 'ed1' becomes NULL
* but this will never happen. */
@@ -398,14 +398,14 @@ static void testvertexnearedge(ScanFillContext *sf_ctx)
if (eve != eed->v1 && eve != eed->v2 && eve->poly_nr == eed->poly_nr) {
if (compare_v2v2(eve->xy, eed->v1->xy, SF_EPSILON)) {
ed1->v2 = eed->v1;
- eed->v1->edge_tot++;
- eve->edge_tot = 0;
+ eed->v1->edge_count++;
+ eve->edge_count = 0;
break;
}
if (compare_v2v2(eve->xy, eed->v2->xy, SF_EPSILON)) {
ed1->v2 = eed->v2;
- eed->v2->edge_tot++;
- eve->edge_tot = 0;
+ eed->v2->edge_count++;
+ eve->edge_count = 0;
break;
}
@@ -418,7 +418,7 @@ static void testvertexnearedge(ScanFillContext *sf_ctx)
// printf("fill: vertex near edge %x\n", eve);
ed1->poly_nr = eed->poly_nr;
eed->v1 = eve;
- eve->edge_tot = 3;
+ eve->edge_count = 3;
break;
}
}
@@ -597,14 +597,14 @@ static unsigned int scanfill(ScanFillContext *sf_ctx, PolyFill *pf, const int fl
/* Set connect-flags. */
for (ed1 = sc->edge_first; ed1; ed1 = eed_next) {
eed_next = ed1->next;
- if (ed1->v1->edge_tot == 1 || ed1->v2->edge_tot == 1) {
+ if (ed1->v1->edge_count == 1 || ed1->v2->edge_count == 1) {
BLI_remlink((ListBase *)&(sc->edge_first), ed1);
BLI_addtail(&sf_ctx->filledgebase, ed1);
- if (ed1->v1->edge_tot > 1) {
- ed1->v1->edge_tot--;
+ if (ed1->v1->edge_count > 1) {
+ ed1->v1->edge_count--;
}
- if (ed1->v2->edge_tot > 1) {
- ed1->v2->edge_tot--;
+ if (ed1->v2->edge_count > 1) {
+ ed1->v2->edge_count--;
}
}
else {
@@ -628,8 +628,8 @@ static unsigned int scanfill(ScanFillContext *sf_ctx, PolyFill *pf, const int fl
// printf("just 1 edge to vert\n");
BLI_addtail(&sf_ctx->filledgebase, ed1);
ed1->v2->f = SF_VERT_NEW;
- ed1->v1->edge_tot--;
- ed1->v2->edge_tot--;
+ ed1->v1->edge_count--;
+ ed1->v2->edge_count--;
}
else {
/* test rest of vertices */
@@ -697,8 +697,8 @@ static unsigned int scanfill(ScanFillContext *sf_ctx, PolyFill *pf, const int fl
BLI_insertlinkbefore((ListBase *)&(sc->edge_first), ed2, ed3);
ed3->v2->f = SF_VERT_AVAILABLE;
ed3->f = SF_EDGE_INTERNAL;
- ed3->v1->edge_tot++;
- ed3->v2->edge_tot++;
+ ed3->v1->edge_count++;
+ ed3->v2->edge_count++;
}
else {
/* new triangle */
@@ -708,39 +708,39 @@ static unsigned int scanfill(ScanFillContext *sf_ctx, PolyFill *pf, const int fl
BLI_remlink((ListBase *)&(sc->edge_first), ed1);
BLI_addtail(&sf_ctx->filledgebase, ed1);
ed1->v2->f = SF_VERT_NEW;
- ed1->v1->edge_tot--;
- ed1->v2->edge_tot--;
+ ed1->v1->edge_count--;
+ ed1->v2->edge_count--;
/* ed2 can be removed when it's a boundary edge */
if (((ed2->f == SF_EDGE_NEW) && twoconnected) /* || (ed2->f == SF_EDGE_BOUNDARY) */) {
BLI_remlink((ListBase *)&(sc->edge_first), ed2);
BLI_addtail(&sf_ctx->filledgebase, ed2);
ed2->v2->f = SF_VERT_NEW;
- ed2->v1->edge_tot--;
- ed2->v2->edge_tot--;
+ ed2->v1->edge_count--;
+ ed2->v2->edge_count--;
}
/* new edge */
ed3 = BLI_scanfill_edge_add(sf_ctx, v1, v3);
BLI_remlink(&sf_ctx->filledgebase, ed3);
ed3->f = SF_EDGE_INTERNAL;
- ed3->v1->edge_tot++;
- ed3->v2->edge_tot++;
+ ed3->v1->edge_count++;
+ ed3->v2->edge_count++;
// printf("add new edge %x %x\n", v1, v3);
sc1 = addedgetoscanlist(scdata, ed3, verts);
if (sc1) { /* ed3 already exists: remove if a boundary */
// printf("Edge exists\n");
- ed3->v1->edge_tot--;
- ed3->v2->edge_tot--;
+ ed3->v1->edge_count--;
+ ed3->v2->edge_count--;
for (ed3 = sc1->edge_first; ed3; ed3 = ed3->next) {
if ((ed3->v1 == v1 && ed3->v2 == v3) || (ed3->v1 == v3 && ed3->v2 == v1)) {
if (twoconnected /* || (ed3->f == SF_EDGE_BOUNDARY) */) {
BLI_remlink((ListBase *)&(sc1->edge_first), ed3);
BLI_addtail(&sf_ctx->filledgebase, ed3);
- ed3->v1->edge_tot--;
- ed3->v2->edge_tot--;
+ ed3->v1->edge_count--;
+ ed3->v2->edge_count--;
}
break;
}
@@ -752,14 +752,14 @@ static unsigned int scanfill(ScanFillContext *sf_ctx, PolyFill *pf, const int fl
/* test for loose edges */
for (ed1 = sc->edge_first; ed1; ed1 = eed_next) {
eed_next = ed1->next;
- if (ed1->v1->edge_tot < 2 || ed1->v2->edge_tot < 2) {
+ if (ed1->v1->edge_count < 2 || ed1->v2->edge_count < 2) {
BLI_remlink((ListBase *)&(sc->edge_first), ed1);
BLI_addtail(&sf_ctx->filledgebase, ed1);
- if (ed1->v1->edge_tot > 1) {
- ed1->v1->edge_tot--;
+ if (ed1->v1->edge_count > 1) {
+ ed1->v1->edge_count--;
}
- if (ed1->v2->edge_tot > 1) {
- ed1->v2->edge_tot--;
+ if (ed1->v2->edge_count > 1) {
+ ed1->v2->edge_count--;
}
}
}
@@ -838,7 +838,7 @@ unsigned int BLI_scanfill_calc_ex(ScanFillContext *sf_ctx, const int flag, const
* however they should always be zero'd so check instead */
BLI_assert(eve->f == 0);
BLI_assert(sf_ctx->poly_nr || eve->poly_nr == 0);
- BLI_assert(eve->edge_tot == 0);
+ BLI_assert(eve->edge_count == 0);
}
#endif
@@ -964,10 +964,10 @@ unsigned int BLI_scanfill_calc_ex(ScanFillContext *sf_ctx, const int flag, const
if (flag & BLI_SCANFILL_CALC_LOOSE) {
unsigned int toggle = 0;
for (eed = sf_ctx->filledgebase.first; eed; eed = eed->next) {
- if (eed->v1->edge_tot++ > 250) {
+ if (eed->v1->edge_count++ > 250) {
break;
}
- if (eed->v2->edge_tot++ > 250) {
+ if (eed->v2->edge_count++ > 250) {
break;
}
}
@@ -979,7 +979,7 @@ unsigned int BLI_scanfill_calc_ex(ScanFillContext *sf_ctx, const int flag, const
return 0;
}
- /* does it only for vertices with (->edge_tot == 1) */
+ /* does it only for vertices with (->edge_count == 1) */
testvertexnearedge(sf_ctx);
ok = true;
@@ -990,14 +990,14 @@ unsigned int BLI_scanfill_calc_ex(ScanFillContext *sf_ctx, const int flag, const
for (eed = (toggle & 1) ? sf_ctx->filledgebase.first : sf_ctx->filledgebase.last; eed;
eed = eed_next) {
eed_next = (toggle & 1) ? eed->next : eed->prev;
- if (eed->v1->edge_tot == 1) {
- eed->v2->edge_tot--;
+ if (eed->v1->edge_count == 1) {
+ eed->v2->edge_count--;
BLI_remlink(&sf_ctx->fillvertbase, eed->v1);
BLI_remlink(&sf_ctx->filledgebase, eed);
ok = true;
}
- else if (eed->v2->edge_tot == 1) {
- eed->v1->edge_tot--;
+ else if (eed->v2->edge_count == 1) {
+ eed->v1->edge_count--;
BLI_remlink(&sf_ctx->fillvertbase, eed->v2);
BLI_remlink(&sf_ctx->filledgebase, eed);
ok = true;
@@ -1012,14 +1012,14 @@ unsigned int BLI_scanfill_calc_ex(ScanFillContext *sf_ctx, const int flag, const
else {
/* skip checks for loose edges */
for (eed = sf_ctx->filledgebase.first; eed; eed = eed->next) {
- eed->v1->edge_tot++;
- eed->v2->edge_tot++;
+ eed->v1->edge_count++;
+ eed->v2->edge_count++;
}
#ifdef DEBUG
/* ensure we're right! */
for (eed = sf_ctx->filledgebase.first; eed; eed = eed->next) {
- BLI_assert(eed->v1->edge_tot != 1);
- BLI_assert(eed->v2->edge_tot != 1);
+ BLI_assert(eed->v1->edge_count != 1);
+ BLI_assert(eed->v2->edge_count != 1);
}
#endif
}
@@ -1027,7 +1027,7 @@ unsigned int BLI_scanfill_calc_ex(ScanFillContext *sf_ctx, const int flag, const
/* CURRENT STATUS:
* - `eve->f`: 1 = available in edges.
* - `eve->poly_nr`: poly-number.
- * - `eve->edge_tot`: amount of edges connected to vertex.
+ * - `eve->edge_count`: amount of edges connected to vertex.
* - `eve->tmp.v`: store! original vertex number.
*
* - `eed->f`: 1 = boundary edge (optionally set by caller).
@@ -1058,7 +1058,7 @@ unsigned int BLI_scanfill_calc_ex(ScanFillContext *sf_ctx, const int flag, const
min_xy_p[1] = (min_xy_p[1]) < (eve->xy[1]) ? (min_xy_p[1]) : (eve->xy[1]);
max_xy_p[0] = (max_xy_p[0]) > (eve->xy[0]) ? (max_xy_p[0]) : (eve->xy[0]);
max_xy_p[1] = (max_xy_p[1]) > (eve->xy[1]) ? (max_xy_p[1]) : (eve->xy[1]);
- if (eve->edge_tot > 2) {
+ if (eve->edge_count > 2) {
pflist[eve->poly_nr].f = SF_POLY_VALID;
}
}
diff --git a/source/blender/blenlib/intern/scanfill_utils.c b/source/blender/blenlib/intern/scanfill_utils.c
index 149589fb933..1d2225a5b56 100644
--- a/source/blender/blenlib/intern/scanfill_utils.c
+++ b/source/blender/blenlib/intern/scanfill_utils.c
@@ -359,7 +359,7 @@ bool BLI_scanfill_calc_self_isect(ScanFillContext *sf_ctx,
ListBase *remvertbase,
ListBase *remedgebase)
{
- const unsigned int poly_tot = (unsigned int)sf_ctx->poly_nr + 1;
+ const unsigned int poly_num = (unsigned int)sf_ctx->poly_nr + 1;
unsigned int eed_index = 0;
int totvert_new = 0;
bool changed = false;
@@ -370,7 +370,7 @@ bool BLI_scanfill_calc_self_isect(ScanFillContext *sf_ctx,
return false;
}
- poly_info = MEM_callocN(sizeof(*poly_info) * poly_tot, __func__);
+ poly_info = MEM_callocN(sizeof(*poly_info) * poly_num, __func__);
/* get the polygon span */
if (sf_ctx->poly_nr == 0) {
@@ -408,7 +408,7 @@ bool BLI_scanfill_calc_self_isect(ScanFillContext *sf_ctx,
/* self-intersect each polygon */
{
unsigned short poly_nr;
- for (poly_nr = 0; poly_nr < poly_tot; poly_nr++) {
+ for (poly_nr = 0; poly_nr < poly_num; poly_nr++) {
changed |= scanfill_preprocess_self_isect(sf_ctx, poly_info, poly_nr, remedgebase);
}
}
diff --git a/source/blender/blenlib/intern/stack.c b/source/blender/blenlib/intern/stack.c
index 61319613859..ff34cfe41cb 100644
--- a/source/blender/blenlib/intern/stack.c
+++ b/source/blender/blenlib/intern/stack.c
@@ -34,7 +34,7 @@ struct BLI_Stack {
size_t chunk_elem_max; /* number of elements per chunk */
size_t elem_size;
#ifdef USE_TOTELEM
- size_t totelem;
+ size_t elem_num;
#endif
};
@@ -119,7 +119,7 @@ void *BLI_stack_push_r(BLI_Stack *stack)
BLI_assert(stack->chunk_index < stack->chunk_elem_max);
#ifdef USE_TOTELEM
- stack->totelem++;
+ stack->elem_num++;
#endif
/* Return end of stack */
@@ -175,7 +175,7 @@ void BLI_stack_discard(BLI_Stack *stack)
BLI_assert(BLI_stack_is_empty(stack) == false);
#ifdef USE_TOTELEM
- stack->totelem--;
+ stack->elem_num--;
#endif
if (UNLIKELY(--stack->chunk_index == CHUNK_EMPTY)) {
struct StackChunk *chunk_free;
@@ -193,10 +193,10 @@ void BLI_stack_discard(BLI_Stack *stack)
void BLI_stack_clear(BLI_Stack *stack)
{
#ifdef USE_TOTELEM
- if (UNLIKELY(stack->totelem == 0)) {
+ if (UNLIKELY(stack->elem_num == 0)) {
return;
}
- stack->totelem = 0;
+ stack->elem_num = 0;
#else
if (UNLIKELY(stack->chunk_curr == NULL)) {
return;
@@ -225,29 +225,29 @@ void BLI_stack_clear(BLI_Stack *stack)
size_t BLI_stack_count(const BLI_Stack *stack)
{
#ifdef USE_TOTELEM
- return stack->totelem;
+ return stack->elem_num;
#else
struct StackChunk *data = stack->chunk_curr;
- size_t totelem = stack->chunk_index + 1;
+ size_t elem_num = stack->chunk_index + 1;
size_t i;
- if (totelem != stack->chunk_elem_max) {
+ if (elem_num != stack->chunk_elem_max) {
data = data->next;
}
else {
- totelem = 0;
+ elem_num = 0;
}
for (i = 0; data; data = data->next) {
i++;
}
- totelem += stack->chunk_elem_max * i;
- return totelem;
+ elem_num += stack->chunk_elem_max * i;
+ return elem_num;
#endif
}
bool BLI_stack_is_empty(const BLI_Stack *stack)
{
#ifdef USE_TOTELEM
- BLI_assert((stack->chunk_curr == NULL) == (stack->totelem == 0));
+ BLI_assert((stack->chunk_curr == NULL) == (stack->elem_num == 0));
#endif
return (stack->chunk_curr == NULL);
}
diff --git a/source/blender/blenlib/intern/string.c b/source/blender/blenlib/intern/string.c
index 75fa628e701..74559751d91 100644
--- a/source/blender/blenlib/intern/string.c
+++ b/source/blender/blenlib/intern/string.c
@@ -1131,11 +1131,11 @@ void BLI_str_format_byte_unit(char dst[15], long long int bytes, const bool base
const int base = base_10 ? 1000 : 1024;
const char *units_base_10[] = {"B", "KB", "MB", "GB", "TB", "PB"};
const char *units_base_2[] = {"B", "KiB", "MiB", "GiB", "TiB", "PiB"};
- const int tot_units = ARRAY_SIZE(units_base_2);
+ const int units_num = ARRAY_SIZE(units_base_2);
BLI_STATIC_ASSERT(ARRAY_SIZE(units_base_2) == ARRAY_SIZE(units_base_10), "array size mismatch");
- while ((fabs(bytes_converted) >= base) && ((order + 1) < tot_units)) {
+ while ((fabs(bytes_converted) >= base) && ((order + 1) < units_num)) {
bytes_converted /= base;
order++;
}
@@ -1155,9 +1155,9 @@ void BLI_str_format_attribute_domain_size(char dst[7], int number_to_format)
int order = 0;
const float base = 1000;
const char *units[] = {"", "K", "M", "B"};
- const int tot_units = ARRAY_SIZE(units);
+ const int units_num = ARRAY_SIZE(units);
- while ((fabsf(number_to_format_converted) >= base) && ((order + 1) < tot_units)) {
+ while ((fabsf(number_to_format_converted) >= base) && ((order + 1) < units_num)) {
number_to_format_converted /= base;
order++;
}
diff --git a/source/blender/blenlib/intern/task_iterator.c b/source/blender/blenlib/intern/task_iterator.c
index 4ee4e6c6ff2..d5afbb2b117 100644
--- a/source/blender/blenlib/intern/task_iterator.c
+++ b/source/blender/blenlib/intern/task_iterator.c
@@ -40,8 +40,8 @@
* \{ */
BLI_INLINE void task_parallel_calc_chunk_size(const TaskParallelSettings *settings,
- const int tot_items,
- int num_tasks,
+ const int items_num,
+ int tasks_num,
int *r_chunk_size)
{
int chunk_size = 0;
@@ -50,7 +50,7 @@ BLI_INLINE void task_parallel_calc_chunk_size(const TaskParallelSettings *settin
/* Some users of this helper will still need a valid chunk size in case processing is not
* threaded. We can use a bigger one than in default threaded case then. */
chunk_size = 1024;
- num_tasks = 1;
+ tasks_num = 1;
}
else if (settings->min_iter_per_thread > 0) {
/* Already set by user, no need to do anything here. */
@@ -61,24 +61,24 @@ BLI_INLINE void task_parallel_calc_chunk_size(const TaskParallelSettings *settin
* The idea here is to increase the chunk size to compensate for a rather measurable threading
* overhead caused by fetching tasks. With too many CPU threads we are starting
* to spend too much time in those overheads.
- * First values are: 1 if num_tasks < 16;
- * else 2 if num_tasks < 32;
- * else 3 if num_tasks < 48;
- * else 4 if num_tasks < 64;
+ * First values are: 1 if tasks_num < 16;
+ * else 2 if tasks_num < 32;
+ * else 3 if tasks_num < 48;
+ * else 4 if tasks_num < 64;
* etc.
* NOTE: If we wanted to keep the 'power of two' multiplier, we'd need something like:
- * 1 << max_ii(0, (int)(sizeof(int) * 8) - 1 - bitscan_reverse_i(num_tasks) - 3)
+ * 1 << max_ii(0, (int)(sizeof(int) * 8) - 1 - bitscan_reverse_i(tasks_num) - 3)
*/
- const int num_tasks_factor = max_ii(1, num_tasks >> 3);
+ const int tasks_num_factor = max_ii(1, tasks_num >> 3);
/* We could make that 'base' 32 number configurable in TaskParallelSettings too, or maybe just
* always use that heuristic using TaskParallelSettings.min_iter_per_thread as basis? */
- chunk_size = 32 * num_tasks_factor;
+ chunk_size = 32 * tasks_num_factor;
/* Basic heuristic to avoid threading on low amount of items.
* We could make that limit configurable in settings too. */
- if (tot_items > 0 && tot_items < max_ii(256, chunk_size * 2)) {
- chunk_size = tot_items;
+ if (items_num > 0 && items_num < max_ii(256, chunk_size * 2)) {
+ chunk_size = items_num;
}
}
@@ -95,7 +95,7 @@ typedef struct TaskParallelIteratorState {
/* Common data also passed to the generator callback. */
TaskParallelIteratorStateShared iter_shared;
/* Total number of items. If unknown, set it to a negative number. */
- int tot_items;
+ int items_num;
} TaskParallelIteratorState;
static void parallel_iterator_func_do(TaskParallelIteratorState *__restrict state,
@@ -188,10 +188,10 @@ static void task_parallel_iterator_no_threads(const TaskParallelSettings *settin
static void task_parallel_iterator_do(const TaskParallelSettings *settings,
TaskParallelIteratorState *state)
{
- const int num_threads = BLI_task_scheduler_num_threads();
+ const int threads_num = BLI_task_scheduler_num_threads();
task_parallel_calc_chunk_size(
- settings, state->tot_items, num_threads, &state->iter_shared.chunk_size);
+ settings, state->items_num, threads_num, &state->iter_shared.chunk_size);
if (!settings->use_threading) {
task_parallel_iterator_no_threads(settings, state);
@@ -199,13 +199,13 @@ static void task_parallel_iterator_do(const TaskParallelSettings *settings,
}
const int chunk_size = state->iter_shared.chunk_size;
- const int tot_items = state->tot_items;
- const size_t num_tasks = tot_items >= 0 ?
- (size_t)min_ii(num_threads, state->tot_items / chunk_size) :
- (size_t)num_threads;
+ const int items_num = state->items_num;
+ const size_t tasks_num = items_num >= 0 ?
+ (size_t)min_ii(threads_num, state->items_num / chunk_size) :
+ (size_t)threads_num;
- BLI_assert(num_tasks > 0);
- if (num_tasks == 1) {
+ BLI_assert(tasks_num > 0);
+ if (tasks_num == 1) {
task_parallel_iterator_no_threads(settings, state);
return;
}
@@ -223,10 +223,10 @@ static void task_parallel_iterator_do(const TaskParallelSettings *settings,
TaskPool *task_pool = BLI_task_pool_create(state, TASK_PRIORITY_HIGH);
if (use_userdata_chunk) {
- userdata_chunk_array = MALLOCA(userdata_chunk_size * num_tasks);
+ userdata_chunk_array = MALLOCA(userdata_chunk_size * tasks_num);
}
- for (size_t i = 0; i < num_tasks; i++) {
+ for (size_t i = 0; i < tasks_num; i++) {
if (use_userdata_chunk) {
userdata_chunk_local = (char *)userdata_chunk_array + (userdata_chunk_size * i);
memcpy(userdata_chunk_local, userdata_chunk, userdata_chunk_size);
@@ -243,7 +243,7 @@ static void task_parallel_iterator_do(const TaskParallelSettings *settings,
if (use_userdata_chunk) {
if (settings->func_reduce != NULL || settings->func_free != NULL) {
- for (size_t i = 0; i < num_tasks; i++) {
+ for (size_t i = 0; i < tasks_num; i++) {
userdata_chunk_local = (char *)userdata_chunk_array + (userdata_chunk_size * i);
if (settings->func_reduce != NULL) {
settings->func_reduce(state->userdata, userdata_chunk, userdata_chunk_local);
@@ -253,7 +253,7 @@ static void task_parallel_iterator_do(const TaskParallelSettings *settings,
}
}
}
- MALLOCA_FREE(userdata_chunk_array, userdata_chunk_size * num_tasks);
+ MALLOCA_FREE(userdata_chunk_array, userdata_chunk_size * tasks_num);
}
BLI_spin_end(&spin_lock);
@@ -264,13 +264,13 @@ void BLI_task_parallel_iterator(void *userdata,
TaskParallelIteratorIterFunc iter_func,
void *init_item,
const int init_index,
- const int tot_items,
+ const int items_num,
TaskParallelIteratorFunc func,
const TaskParallelSettings *settings)
{
TaskParallelIteratorState state = {0};
- state.tot_items = tot_items;
+ state.items_num = items_num;
state.iter_shared.next_index = init_index;
state.iter_shared.next_item = init_item;
state.iter_shared.is_finished = false;
@@ -314,7 +314,7 @@ void BLI_task_parallel_listbase(ListBase *listbase,
TaskParallelIteratorState state = {0};
- state.tot_items = BLI_listbase_count(listbase);
+ state.items_num = BLI_listbase_count(listbase);
state.iter_shared.next_index = 0;
state.iter_shared.next_item = listbase->first;
state.iter_shared.is_finished = false;
@@ -391,25 +391,25 @@ void BLI_task_parallel_mempool(BLI_mempool *mempool,
ParallelMempoolState state;
TaskPool *task_pool = BLI_task_pool_create(&state, TASK_PRIORITY_HIGH);
- const int num_threads = BLI_task_scheduler_num_threads();
+ const int threads_num = BLI_task_scheduler_num_threads();
/* The idea here is to prevent creating task for each of the loop iterations
* and instead have tasks which are evenly distributed across CPU cores and
* pull next item to be crunched using the threaded-aware BLI_mempool_iter.
*/
- const int num_tasks = num_threads + 2;
+ const int tasks_num = threads_num + 2;
state.userdata = userdata;
state.func = func;
if (use_userdata_chunk) {
- userdata_chunk_array = MALLOCA(userdata_chunk_size * num_tasks);
+ userdata_chunk_array = MALLOCA(userdata_chunk_size * tasks_num);
}
ParallelMempoolTaskData *mempool_iterator_data = mempool_iter_threadsafe_create(
- mempool, (size_t)num_tasks);
+ mempool, (size_t)tasks_num);
- for (int i = 0; i < num_tasks; i++) {
+ for (int i = 0; i < tasks_num; i++) {
void *userdata_chunk_local = NULL;
if (use_userdata_chunk) {
userdata_chunk_local = (char *)userdata_chunk_array + (userdata_chunk_size * i);
@@ -429,7 +429,7 @@ void BLI_task_parallel_mempool(BLI_mempool *mempool,
if (use_userdata_chunk) {
if ((settings->func_free != NULL) || (settings->func_reduce != NULL)) {
- for (int i = 0; i < num_tasks; i++) {
+ for (int i = 0; i < tasks_num; i++) {
if (settings->func_reduce) {
settings->func_reduce(
userdata, userdata_chunk, mempool_iterator_data[i].tls.userdata_chunk);
@@ -439,7 +439,7 @@ void BLI_task_parallel_mempool(BLI_mempool *mempool,
}
}
}
- MALLOCA_FREE(userdata_chunk_array, userdata_chunk_size * num_tasks);
+ MALLOCA_FREE(userdata_chunk_array, userdata_chunk_size * tasks_num);
}
mempool_iter_threadsafe_destroy(mempool_iterator_data);
diff --git a/source/blender/blenlib/intern/task_scheduler.cc b/source/blender/blenlib/intern/task_scheduler.cc
index 32c833fae38..1f7747453c1 100644
--- a/source/blender/blenlib/intern/task_scheduler.cc
+++ b/source/blender/blenlib/intern/task_scheduler.cc
@@ -31,14 +31,14 @@ static tbb::global_control *task_scheduler_global_control = nullptr;
void BLI_task_scheduler_init()
{
#ifdef WITH_TBB_GLOBAL_CONTROL
- const int num_threads_override = BLI_system_num_threads_override_get();
+ const int threads_override_num = BLI_system_num_threads_override_get();
- if (num_threads_override > 0) {
+ if (threads_override_num > 0) {
/* Override number of threads. This settings is used within the lifetime
* of tbb::global_control, so we allocate it on the heap. */
task_scheduler_global_control = MEM_new<tbb::global_control>(
- __func__, tbb::global_control::max_allowed_parallelism, num_threads_override);
- task_scheduler_num_threads = num_threads_override;
+ __func__, tbb::global_control::max_allowed_parallelism, threads_override_num);
+ task_scheduler_num_threads = threads_override_num;
}
else {
/* Let TBB choose the number of threads. For (legacy) code that calls
diff --git a/source/blender/blenlib/intern/threads.cc b/source/blender/blenlib/intern/threads.cc
index ff67f821d1e..70c1e701348 100644
--- a/source/blender/blenlib/intern/threads.cc
+++ b/source/blender/blenlib/intern/threads.cc
@@ -109,7 +109,7 @@ static pthread_mutex_t _fftw_lock = PTHREAD_MUTEX_INITIALIZER;
static pthread_mutex_t _view3d_lock = PTHREAD_MUTEX_INITIALIZER;
static pthread_t mainid;
static unsigned int thread_levels = 0; /* threads can be invoked inside threads */
-static int num_threads_override = 0;
+static int threads_override_num = 0;
/* just a max for security reasons */
#define RE_MAX_THREAD BLENDER_MAX_THREADS
@@ -282,8 +282,8 @@ int BLI_system_thread_count()
{
static int t = -1;
- if (num_threads_override != 0) {
- return num_threads_override;
+ if (threads_override_num != 0) {
+ return threads_override_num;
}
if (LIKELY(t != -1)) {
return t;
@@ -316,12 +316,12 @@ int BLI_system_thread_count()
void BLI_system_num_threads_override_set(int num)
{
- num_threads_override = num;
+ threads_override_num = num;
}
int BLI_system_num_threads_override_get()
{
- return num_threads_override;
+ return threads_override_num;
}
/* Global Mutex Locks */
diff --git a/source/blender/blenlib/intern/uuid.cc b/source/blender/blenlib/intern/uuid.cc
index b175ed4a770..890a721a9d1 100644
--- a/source/blender/blenlib/intern/uuid.cc
+++ b/source/blender/blenlib/intern/uuid.cc
@@ -102,7 +102,7 @@ void BLI_uuid_format(char *buffer, const bUUID uuid)
bool BLI_uuid_parse_string(bUUID *uuid, const char *buffer)
{
- const int num_fields_parsed = std::sscanf(
+ const int fields_parsed_num = std::sscanf(
buffer,
"%8x-%4hx-%4hx-%2hhx%2hhx-%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx",
&uuid->time_low,
@@ -116,7 +116,7 @@ bool BLI_uuid_parse_string(bUUID *uuid, const char *buffer)
&uuid->node[3],
&uuid->node[4],
&uuid->node[5]);
- return num_fields_parsed == 11;
+ return fields_parsed_num == 11;
}
std::ostream &operator<<(std::ostream &stream, bUUID uuid)
diff --git a/source/blender/blenlib/tests/BLI_cpp_type_test.cc b/source/blender/blenlib/tests/BLI_cpp_type_test.cc
index 94456e1ee28..f00767eda8c 100644
--- a/source/blender/blenlib/tests/BLI_cpp_type_test.cc
+++ b/source/blender/blenlib/tests/BLI_cpp_type_test.cc
@@ -118,6 +118,40 @@ TEST(cpp_type, DefaultConstruction)
EXPECT_EQ(buffer[8], 0);
}
+TEST(cpp_type, DefaultConstructTrivial)
+{
+ int value = 5;
+ CPPType::get<int>().default_construct(&value);
+ EXPECT_EQ(value, 5);
+}
+
+TEST(cpp_type, ValueInitialize)
+{
+ int buffer[10] = {0};
+ CPPType_TestType.value_initialize((void *)buffer);
+ EXPECT_EQ(buffer[0], default_constructed_value);
+ EXPECT_EQ(buffer[1], 0);
+ CPPType_TestType.value_initialize_n((void *)buffer, 3);
+ EXPECT_EQ(buffer[0], default_constructed_value);
+ EXPECT_EQ(buffer[1], default_constructed_value);
+ EXPECT_EQ(buffer[2], default_constructed_value);
+ EXPECT_EQ(buffer[3], 0);
+ CPPType_TestType.value_initialize_indices((void *)buffer, {2, 5, 7});
+ EXPECT_EQ(buffer[2], default_constructed_value);
+ EXPECT_EQ(buffer[4], 0);
+ EXPECT_EQ(buffer[5], default_constructed_value);
+ EXPECT_EQ(buffer[6], 0);
+ EXPECT_EQ(buffer[7], default_constructed_value);
+ EXPECT_EQ(buffer[8], 0);
+}
+
+TEST(cpp_type, ValueInitializeTrivial)
+{
+ int value = 5;
+ CPPType::get<int>().value_initialize(&value);
+ EXPECT_EQ(value, 0);
+}
+
TEST(cpp_type, Destruct)
{
int buffer[10] = {0};
diff --git a/source/blender/blenlib/tests/BLI_delaunay_2d_test.cc b/source/blender/blenlib/tests/BLI_delaunay_2d_test.cc
index bdf263d982a..25ee523ebc0 100644
--- a/source/blender/blenlib/tests/BLI_delaunay_2d_test.cc
+++ b/source/blender/blenlib/tests/BLI_delaunay_2d_test.cc
@@ -1788,7 +1788,7 @@ TEST(delaunay_d, CintTwoFaceNoIds)
#if DO_TEXT_TESTS
template<typename T>
void text_test(
- int num_arc_points, int num_lets_per_line, int num_lines, CDT_output_type otype, bool need_ids)
+ int arc_points_num, int lets_per_line_num, int lines_num, CDT_output_type otype, bool need_ids)
{
constexpr bool print_timing = true;
/*
@@ -1810,7 +1810,7 @@ void text_test(
*
* Where the numbers are the first 13 vertices, and the rest of
* the vertices are in arcs a0, a1, a2, a3, each of which have
- * num_arc_points per arc in them.
+ * arc_points_num per arc in them.
*/
const char *b_before_arcs = R"(13 0 3
@@ -1834,13 +1834,13 @@ void text_test(
CDT_input<T> b_before_arcs_in = fill_input_from_string<T>(b_before_arcs);
constexpr int narcs = 4;
- int b_npts = b_before_arcs_in.vert.size() + narcs * num_arc_points;
+ int b_npts = b_before_arcs_in.vert.size() + narcs * arc_points_num;
constexpr int b_nfaces = 3;
Array<vec2<T>> b_vert(b_npts);
Array<Vector<int>> b_face(b_nfaces);
std::copy(b_before_arcs_in.vert.begin(), b_before_arcs_in.vert.end(), b_vert.begin());
std::copy(b_before_arcs_in.face.begin(), b_before_arcs_in.face.end(), b_face.begin());
- if (num_arc_points > 0) {
+ if (arc_points_num > 0) {
b_face[0].pop_last(); /* We'll add center point back between arcs for outer face. */
for (int arc = 0; arc < narcs; ++arc) {
int arc_origin_vert;
@@ -1875,10 +1875,10 @@ void text_test(
vec2<T> center_co = 0.5 * (start_co + end_co);
BLI_assert(start_co[0] == end_co[0]);
double radius = abs(math_to_double<T>(end_co[1] - center_co[1]));
- double angle_delta = M_PI / (num_arc_points + 1);
- int start_vert = b_before_arcs_in.vert.size() + arc * num_arc_points;
+ double angle_delta = M_PI / (arc_points_num + 1);
+ int start_vert = b_before_arcs_in.vert.size() + arc * arc_points_num;
Vector<int> &face = b_face[(arc <= 1) ? 0 : arc - 1];
- for (int i = 0; i < num_arc_points; ++i) {
+ for (int i = 0; i < arc_points_num; ++i) {
vec2<T> delta;
float ang = ccw ? (-M_PI_2 + (i + 1) * angle_delta) : (M_PI_2 - (i + 1) * angle_delta);
delta[0] = T(radius * cos(ang));
@@ -1893,7 +1893,7 @@ void text_test(
}
CDT_input<T> in;
- int tot_instances = num_lets_per_line * num_lines;
+ int tot_instances = lets_per_line_num * lines_num;
if (tot_instances == 1) {
in.vert = b_vert;
in.face = b_face;
@@ -1906,8 +1906,8 @@ void text_test(
T delta_x = T(2);
T delta_y = T(3.25);
int instance = 0;
- for (int line = 0; line < num_lines; ++line) {
- for (int let = 0; let < num_lets_per_line; ++let) {
+ for (int line = 0; line < lines_num; ++line) {
+ for (int let = 0; let < lets_per_line_num; ++let) {
vec2<T> co_offset(cur_x, cur_y);
int in_v_offset = instance * b_vert.size();
for (int v = 0; v < b_vert.size(); ++v) {
@@ -1940,12 +1940,12 @@ void text_test(
EXPECT_EQ(out.face_orig.size(), 0);
}
if (DO_DRAW) {
- std::string label = "Text arcpts=" + std::to_string(num_arc_points);
- if (num_lets_per_line > 1) {
- label += " linelen=" + std::to_string(num_lets_per_line);
+ std::string label = "Text arcpts=" + std::to_string(arc_points_num);
+ if (lets_per_line_num > 1) {
+ label += " linelen=" + std::to_string(lets_per_line_num);
}
- if (num_lines > 1) {
- label += " lines=" + std::to_string(num_lines);
+ if (lines_num > 1) {
+ label += " lines=" + std::to_string(lines_num);
}
if (!need_ids) {
label += " no_ids";
diff --git a/source/blender/blenlib/tests/BLI_length_parameterize_test.cc b/source/blender/blenlib/tests/BLI_length_parameterize_test.cc
new file mode 100644
index 00000000000..4a8b7095888
--- /dev/null
+++ b/source/blender/blenlib/tests/BLI_length_parameterize_test.cc
@@ -0,0 +1,202 @@
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#include "BLI_array.hh"
+#include "BLI_length_parameterize.hh"
+#include "BLI_vector.hh"
+
+#include "testing/testing.h"
+
+namespace blender::length_parameterize::tests {
+
+template<typename T> Array<float> calculate_lengths(const Span<T> values, const bool cyclic)
+{
+ Array<float> lengths(lengths_num(values.size(), cyclic));
+ accumulate_lengths<T>(values, cyclic, lengths);
+ return lengths;
+}
+
+template<typename T> void test_uniform_lengths(const Span<T> values)
+{
+ const float segment_length = math::distance(values.first(), values.last()) / (values.size() - 1);
+ for (const int i : values.index_range().drop_back(1)) {
+ EXPECT_NEAR(math::distance(values[i], values[i + 1]), segment_length, 1e-5);
+ }
+}
+
+TEST(length_parameterize, FloatSimple)
+{
+ Array<float> values{{0, 1, 4}};
+ Array<float> lengths = calculate_lengths(values.as_span(), false);
+
+ Array<int> indices(4);
+ Array<float> factors(4);
+ create_uniform_samples(lengths, false, indices, factors);
+ Array<float> results(4);
+ linear_interpolation<float>(values, indices, factors, results);
+ Array<float> expected({
+ 0.0f,
+ 1.33333f,
+ 2.66667f,
+ 4.0f,
+ });
+ for (const int i : results.index_range()) {
+ EXPECT_NEAR(results[i], expected[i], 1e-5);
+ }
+ test_uniform_lengths(results.as_span());
+}
+
+TEST(length_parameterize, Float)
+{
+ Array<float> values{{1, 2, 3, 5, 10}};
+ Array<float> lengths = calculate_lengths(values.as_span(), false);
+
+ Array<int> indices(20);
+ Array<float> factors(20);
+ create_uniform_samples(lengths, false, indices, factors);
+ Array<float> results(20);
+ linear_interpolation<float>(values, indices, factors, results);
+ Array<float> expected({
+ 1.0f, 1.47368f, 1.94737f, 2.42105f, 2.89474f, 3.36842f, 3.84211f,
+ 4.31579f, 4.78947f, 5.26316f, 5.73684f, 6.21053f, 6.68421f, 7.1579f,
+ 7.63158f, 8.10526f, 8.57895f, 9.05263f, 9.52632f, 10.0f,
+ });
+ for (const int i : results.index_range()) {
+ EXPECT_NEAR(results[i], expected[i], 1e-5);
+ }
+ test_uniform_lengths(results.as_span());
+}
+
+TEST(length_parameterize, Float2)
+{
+ Array<float2> values{{{0, 0}, {1, 0}, {1, 1}, {0, 1}}};
+ Array<float> lengths = calculate_lengths(values.as_span(), false);
+
+ Array<int> indices(12);
+ Array<float> factors(12);
+ create_uniform_samples(lengths, false, indices, factors);
+ Array<float2> results(12);
+ linear_interpolation<float2>(values, indices, factors, results);
+ Array<float2> expected({
+ {0.0f, 0.0f},
+ {0.272727f, 0.0f},
+ {0.545455f, 0.0f},
+ {0.818182f, 0.0f},
+ {1.0f, 0.0909091f},
+ {1.0f, 0.363636f},
+ {1.0f, 0.636364f},
+ {1.0f, 0.909091f},
+ {0.818182f, 1.0f},
+ {0.545455f, 1.0f},
+ {0.272727f, 1.0f},
+ {0.0f, 1.0f},
+ });
+ for (const int i : results.index_range()) {
+ EXPECT_NEAR(results[i].x, expected[i].x, 1e-5);
+ EXPECT_NEAR(results[i].y, expected[i].y, 1e-5);
+ }
+}
+
+TEST(length_parameterize, Float2Cyclic)
+{
+ Array<float2> values{{{0, 0}, {1, 0}, {1, 1}, {0, 1}}};
+ Array<float> lengths = calculate_lengths(values.as_span(), true);
+
+ Array<int> indices(12);
+ Array<float> factors(12);
+ create_uniform_samples(lengths, true, indices, factors);
+ Array<float2> results(12);
+ linear_interpolation<float2>(values, indices, factors, results);
+ Array<float2> expected({
+ {0.0f, 0.0f},
+ {0.333333f, 0.0f},
+ {0.666667f, 0.0f},
+ {1.0f, 0.0f},
+ {1.0f, 0.333333f},
+ {1.0f, 0.666667f},
+ {1.0f, 1.0f},
+ {0.666667f, 1.0f},
+ {0.333333f, 1.0f},
+ {0.0f, 1.0f},
+ {0.0f, 0.666667f},
+ {0.0f, 0.333333f},
+ });
+ for (const int i : results.index_range()) {
+ EXPECT_NEAR(results[i].x, expected[i].x, 1e-5);
+ EXPECT_NEAR(results[i].y, expected[i].y, 1e-5);
+ }
+}
+
+TEST(length_parameterize, LineMany)
+{
+ Array<float> values{{1, 2}};
+ Array<float> lengths = calculate_lengths(values.as_span(), false);
+
+ Array<int> indices(5007);
+ Array<float> factors(5007);
+ create_uniform_samples(lengths, false, indices, factors);
+ Array<float> results(5007);
+ linear_interpolation<float>(values, indices, factors, results);
+ Array<float> expected({
+ 1.9962f, 1.9964f, 1.9966f, 1.9968f, 1.997f, 1.9972f, 1.9974f, 1.9976f, 1.9978f, 1.998f,
+ 1.9982f, 1.9984f, 1.9986f, 1.9988f, 1.999f, 1.9992f, 1.9994f, 1.9996f, 1.9998f, 2.0f,
+ });
+ for (const int i : expected.index_range()) {
+ EXPECT_NEAR(results.as_span().take_back(20)[i], expected[i], 1e-5);
+ }
+}
+
+TEST(length_parameterize, CyclicMany)
+{
+ Array<float2> values{{{0, 0}, {1, 0}, {1, 1}, {0, 1}}};
+ Array<float> lengths = calculate_lengths(values.as_span(), true);
+
+ Array<int> indices(5007);
+ Array<float> factors(5007);
+ create_uniform_samples(lengths, true, indices, factors);
+ Array<float2> results(5007);
+ linear_interpolation<float2>(values, indices, factors, results);
+ Array<float2> expected({
+ {0, 0.0159776}, {0, 0.0151787}, {0, 0.0143797}, {0, 0.013581}, {0, 0.0127821},
+ {0, 0.0119832}, {0, 0.0111842}, {0, 0.0103855}, {0, 0.00958657}, {0, 0.00878763},
+ {0, 0.00798869}, {0, 0.00718999}, {0, 0.00639105}, {0, 0.00559211}, {0, 0.00479317},
+ {0, 0.00399446}, {0, 0.00319552}, {0, 0.00239658}, {0, 0.00159764}, {0, 0.000798941},
+ });
+ for (const int i : expected.index_range()) {
+ EXPECT_NEAR(results.as_span().take_back(20)[i].x, expected[i].x, 1e-5);
+ EXPECT_NEAR(results.as_span().take_back(20)[i].y, expected[i].y, 1e-5);
+ }
+}
+
+TEST(length_parameterize, InterpolateColor)
+{
+ Array<float2> values{{{0, 0}, {1, 0}, {1, 1}, {0, 1}}};
+ Array<float> lengths = calculate_lengths(values.as_span(), true);
+
+ Array<ColorGeometry4f> colors{{{0, 0, 0, 1}, {1, 0, 0, 1}, {1, 1, 0, 1}, {0, 1, 0, 1}}};
+
+ Array<int> indices(10);
+ Array<float> factors(10);
+ create_uniform_samples(lengths, true, indices, factors);
+ Array<ColorGeometry4f> results(10);
+ linear_interpolation<ColorGeometry4f>(colors, indices, factors, results);
+ Array<ColorGeometry4f> expected({
+ {0, 0, 0, 1},
+ {0.4, 0, 0, 1},
+ {0.8, 0, 0, 1},
+ {1, 0.2, 0, 1},
+ {1, 0.6, 0, 1},
+ {1, 1, 0, 1},
+ {0.6, 1, 0, 1},
+ {0.2, 1, 0, 1},
+ {0, 0.8, 0, 1},
+ {0, 0.4, 0, 1},
+ });
+ for (const int i : results.index_range()) {
+ EXPECT_NEAR(results[i].r, expected[i].r, 1e-6);
+ EXPECT_NEAR(results[i].g, expected[i].g, 1e-6);
+ EXPECT_NEAR(results[i].b, expected[i].b, 1e-6);
+ EXPECT_NEAR(results[i].a, expected[i].a, 1e-6);
+ }
+}
+
+} // namespace blender::length_parameterize::tests
diff --git a/source/blender/blenlib/tests/BLI_linklist_lockfree_test.cc b/source/blender/blenlib/tests/BLI_linklist_lockfree_test.cc
index 561ebefb8d2..0c2b4ee52cc 100644
--- a/source/blender/blenlib/tests/BLI_linklist_lockfree_test.cc
+++ b/source/blender/blenlib/tests/BLI_linklist_lockfree_test.cc
@@ -32,9 +32,9 @@ TEST(LockfreeLinkList, InsertSingle)
TEST(LockfreeLinkList, InsertMultiple)
{
- static const int num_nodes = 128;
+ static const int nodes_num = 128;
LockfreeLinkList list;
- LockfreeLinkNode nodes[num_nodes];
+ LockfreeLinkNode nodes[nodes_num];
BLI_linklist_lockfree_init(&list);
/* Insert all the nodes. */
for (LockfreeLinkNode &node : nodes) {
@@ -42,13 +42,13 @@ TEST(LockfreeLinkList, InsertMultiple)
}
/* Check head and tail. */
EXPECT_EQ(list.head, &list.dummy_node);
- EXPECT_EQ(list.tail, &nodes[num_nodes - 1]);
+ EXPECT_EQ(list.tail, &nodes[nodes_num - 1]);
/* Check rest of the nodes. */
int node_index = 0;
for (LockfreeLinkNode *node = BLI_linklist_lockfree_begin(&list); node != nullptr;
node = node->next, ++node_index) {
EXPECT_EQ(node, &nodes[node_index]);
- if (node_index != num_nodes - 1) {
+ if (node_index != nodes_num - 1) {
EXPECT_EQ(node->next, &nodes[node_index + 1]);
}
}
@@ -76,32 +76,32 @@ void concurrent_insert(TaskPool *__restrict pool, void *taskdata)
TEST(LockfreeLinkList, InsertMultipleConcurrent)
{
- static const int num_nodes = 655360;
+ static const int nodes_num = 655360;
/* Initialize list. */
LockfreeLinkList list;
BLI_linklist_lockfree_init(&list);
/* Initialize task scheduler and pool. */
TaskPool *pool = BLI_task_pool_create_suspended(&list, TASK_PRIORITY_HIGH);
/* Push tasks to the pool. */
- for (int i = 0; i < num_nodes; ++i) {
+ for (int i = 0; i < nodes_num; ++i) {
BLI_task_pool_push(pool, concurrent_insert, POINTER_FROM_INT(i), false, nullptr);
}
/* Run all the tasks. */
BLI_task_pool_work_and_wait(pool);
/* Verify we've got all the data properly inserted. */
EXPECT_EQ(list.head, &list.dummy_node);
- bool *visited_nodes = (bool *)MEM_callocN(sizeof(bool) * num_nodes, "visited nodes");
+ bool *visited_nodes = (bool *)MEM_callocN(sizeof(bool) * nodes_num, "visited nodes");
/* First, we make sure that none of the nodes are added twice. */
for (LockfreeLinkNode *node_v = BLI_linklist_lockfree_begin(&list); node_v != nullptr;
node_v = node_v->next) {
IndexedNode *node = (IndexedNode *)node_v;
EXPECT_GE(node->index, 0);
- EXPECT_LT(node->index, num_nodes);
+ EXPECT_LT(node->index, nodes_num);
EXPECT_FALSE(visited_nodes[node->index]);
visited_nodes[node->index] = true;
}
/* Then we make sure node was added. */
- for (int node_index = 0; node_index < num_nodes; ++node_index) {
+ for (int node_index = 0; node_index < nodes_num; ++node_index) {
EXPECT_TRUE(visited_nodes[node_index]);
}
MEM_freeN(visited_nodes);
diff --git a/source/blender/blenlib/tests/BLI_listbase_test.cc b/source/blender/blenlib/tests/BLI_listbase_test.cc
index f19b536a829..aa2f885e39d 100644
--- a/source/blender/blenlib/tests/BLI_listbase_test.cc
+++ b/source/blender/blenlib/tests/BLI_listbase_test.cc
@@ -215,13 +215,13 @@ static int testsort_listbase_str_cmp_reverse(const void *a, const void *b)
}
/* check array and listbase compare */
-static bool testsort_listbase_array_str_cmp(ListBase *lb, char **arr, int arr_tot)
+static bool testsort_listbase_array_str_cmp(ListBase *lb, char **arr, int arr_num)
{
LinkData *link_step;
int i;
link_step = (LinkData *)lb->first;
- for (i = 0; i < arr_tot; i++) {
+ for (i = 0; i < arr_num; i++) {
if (strcmp(arr[i], (char *)link_step->data) != 0) {
return false;
}
@@ -255,7 +255,7 @@ TEST(listbase, Sort)
{
const int words_len = sizeof(words10k) - 1;
char *words = BLI_strdupn(words10k, words_len);
- int words_tot;
+ int words_num;
char **words_arr; /* qsort for comparison */
int i;
char *w_step;
@@ -263,15 +263,15 @@ TEST(listbase, Sort)
LinkData *words_linkdata_arr;
/* delimit words */
- words_tot = 1 + char_switch(words, ' ', '\0');
+ words_num = 1 + char_switch(words, ' ', '\0');
- words_arr = (char **)MEM_mallocN(sizeof(*words_arr) * words_tot, __func__);
+ words_arr = (char **)MEM_mallocN(sizeof(*words_arr) * words_num, __func__);
- words_linkdata_arr = (LinkData *)MEM_mallocN(sizeof(*words_linkdata_arr) * words_tot, __func__);
+ words_linkdata_arr = (LinkData *)MEM_mallocN(sizeof(*words_linkdata_arr) * words_num, __func__);
/* create array */
w_step = words;
- for (i = 0; i < words_tot; i++) {
+ for (i = 0; i < words_num; i++) {
words_arr[i] = w_step;
w_step += strlen(w_step) + 1;
}
@@ -296,7 +296,7 @@ TEST(listbase, Sort)
/* create listbase */
BLI_listbase_clear(&words_lb);
w_step = words;
- for (i = 0; i < words_tot; i++) {
+ for (i = 0; i < words_num; i++) {
LinkData *link = &words_linkdata_arr[i];
link->data = w_step;
BLI_addtail(&words_lb, link);
@@ -306,37 +306,37 @@ TEST(listbase, Sort)
/* sort (forward) */
{
- qsort(words_arr, words_tot, sizeof(*words_arr), testsort_array_str_cmp);
+ qsort(words_arr, words_num, sizeof(*words_arr), testsort_array_str_cmp);
BLI_listbase_sort(&words_lb, testsort_listbase_str_cmp);
EXPECT_TRUE(listbase_is_valid(&words_lb));
- EXPECT_TRUE(testsort_listbase_array_str_cmp(&words_lb, words_arr, words_tot));
+ EXPECT_TRUE(testsort_listbase_array_str_cmp(&words_lb, words_arr, words_num));
EXPECT_TRUE(testsort_listbase_sort_is_stable(&words_lb, true));
}
/* sort (reverse) */
{
- qsort(words_arr, words_tot, sizeof(*words_arr), testsort_array_str_cmp_reverse);
+ qsort(words_arr, words_num, sizeof(*words_arr), testsort_array_str_cmp_reverse);
BLI_listbase_sort(&words_lb, testsort_listbase_str_cmp_reverse);
EXPECT_TRUE(listbase_is_valid(&words_lb));
- EXPECT_TRUE(testsort_listbase_array_str_cmp(&words_lb, words_arr, words_tot));
+ EXPECT_TRUE(testsort_listbase_array_str_cmp(&words_lb, words_arr, words_num));
EXPECT_TRUE(testsort_listbase_sort_is_stable(&words_lb, true));
}
/* sort (forward but after reversing, test stability in alternate direction) */
{
- BLI_array_reverse(words_arr, words_tot);
+ BLI_array_reverse(words_arr, words_num);
BLI_listbase_reverse(&words_lb);
EXPECT_TRUE(listbase_is_valid(&words_lb));
- EXPECT_TRUE(testsort_listbase_array_str_cmp(&words_lb, words_arr, words_tot));
+ EXPECT_TRUE(testsort_listbase_array_str_cmp(&words_lb, words_arr, words_num));
EXPECT_TRUE(testsort_listbase_sort_is_stable(&words_lb, false));
/* and again */
- BLI_array_reverse(words_arr, words_tot);
+ BLI_array_reverse(words_arr, words_num);
BLI_listbase_sort(&words_lb, testsort_listbase_str_cmp_reverse);
- EXPECT_TRUE(testsort_listbase_array_str_cmp(&words_lb, words_arr, words_tot));
+ EXPECT_TRUE(testsort_listbase_array_str_cmp(&words_lb, words_arr, words_num));
EXPECT_TRUE(testsort_listbase_sort_is_stable(&words_lb, false));
}
diff --git a/source/blender/blenlib/tests/BLI_memiter_test.cc b/source/blender/blenlib/tests/BLI_memiter_test.cc
index 17b26d115c4..eb88a8615f8 100644
--- a/source/blender/blenlib/tests/BLI_memiter_test.cc
+++ b/source/blender/blenlib/tests/BLI_memiter_test.cc
@@ -16,11 +16,11 @@ TEST(memiter, Nop)
BLI_memiter_destroy(mi);
}
-static void memiter_empty_test(int num_elems, const int chunk_size)
+static void memiter_empty_test(int elems_num, const int chunk_size)
{
BLI_memiter *mi = BLI_memiter_create(chunk_size);
void *data;
- for (int index = 0; index < num_elems; index++) {
+ for (int index = 0; index < elems_num; index++) {
data = BLI_memiter_alloc(mi, 0);
}
int index = 0, total_size = 0;
@@ -32,17 +32,17 @@ static void memiter_empty_test(int num_elems, const int chunk_size)
total_size += elem_size;
}
EXPECT_EQ(0, total_size);
- EXPECT_EQ(num_elems, index);
+ EXPECT_EQ(elems_num, index);
BLI_memiter_destroy(mi);
}
#define MEMITER_NUMBER_TEST_FN(fn, number_type) \
- static void fn(int num_elems, const int chunk_size) \
+ static void fn(int elems_num, const int chunk_size) \
{ \
BLI_memiter *mi = BLI_memiter_create(chunk_size); \
number_type *data; \
- for (int index = 0; index < num_elems; index++) { \
+ for (int index = 0; index < elems_num; index++) { \
data = (number_type *)BLI_memiter_alloc(mi, sizeof(number_type)); \
*data = index; \
} \
diff --git a/source/blender/blenlib/tests/BLI_mesh_intersect_test.cc b/source/blender/blenlib/tests/BLI_mesh_intersect_test.cc
index d6a7a338d13..c155068b94a 100644
--- a/source/blender/blenlib/tests/BLI_mesh_intersect_test.cc
+++ b/source/blender/blenlib/tests/BLI_mesh_intersect_test.cc
@@ -811,14 +811,14 @@ TEST(mesh_intersect, RectCross)
# if DO_PERF_TESTS
static void get_sphere_params(
- int nrings, int nsegs, bool triangulate, int *r_num_verts, int *r_num_faces)
+ int nrings, int nsegs, bool triangulate, int *r_verts_num, int *r_faces_num)
{
- *r_num_verts = nsegs * (nrings - 1) + 2;
+ *r_verts_num = nsegs * (nrings - 1) + 2;
if (triangulate) {
- *r_num_faces = 2 * nsegs + 2 * nsegs * (nrings - 2);
+ *r_faces_num = 2 * nsegs + 2 * nsegs * (nrings - 2);
}
else {
- *r_num_faces = nsegs * nrings;
+ *r_faces_num = nsegs * nrings;
}
}
@@ -832,11 +832,11 @@ static void fill_sphere_data(int nrings,
int fid_start,
IMeshArena *arena)
{
- int num_verts;
- int num_faces;
- get_sphere_params(nrings, nsegs, triangulate, &num_verts, &num_faces);
- BLI_assert(num_faces == face.size());
- Array<const Vert *> vert(num_verts);
+ int verts_num;
+ int faces_num;
+ get_sphere_params(nrings, nsegs, triangulate, &verts_num, &faces_num);
+ BLI_assert(faces_num == face.size());
+ Array<const Vert *> vert(verts_num);
const bool nrings_even = (nrings % 2 == 0);
int half_nrings = nrings / 2;
const bool nsegs_even = (nsegs % 2) == 0;
@@ -847,12 +847,12 @@ static void fill_sphere_data(int nrings,
double delta_theta = M_PI / nrings;
int fid = fid_start;
int vid = vid_start;
- auto vert_index_fn = [nrings, num_verts](int seg, int ring) {
+ auto vert_index_fn = [nrings, verts_num](int seg, int ring) {
if (ring == 0) { /* Top vert. */
- return num_verts - 2;
+ return verts_num - 2;
}
if (ring == nrings) { /* Bottom vert. */
- return num_verts - 1;
+ return verts_num - 1;
}
return seg * (nrings - 1) + (ring - 1);
};
@@ -980,18 +980,18 @@ static void spheresphere_test(int nrings, double y_offset, bool use_self)
double time_start = PIL_check_seconds_timer();
IMeshArena arena;
int nsegs = 2 * nrings;
- int num_sphere_verts;
- int num_sphere_tris;
- get_sphere_params(nrings, nsegs, true, &num_sphere_verts, &num_sphere_tris);
- Array<Face *> tris(2 * num_sphere_tris);
- arena.reserve(6 * num_sphere_verts / 2, 8 * num_sphere_tris);
+ int sphere_verts_num;
+ int sphere_tris_num;
+ get_sphere_params(nrings, nsegs, true, &sphere_verts_num, &sphere_tris_num);
+ Array<Face *> tris(2 * sphere_tris_num);
+ arena.reserve(6 * sphere_verts_num / 2, 8 * sphere_tris_num);
double3 center1(0.0, 0.0, 0.0);
fill_sphere_data(nrings,
nsegs,
center1,
1.0,
true,
- MutableSpan<Face *>(tris.begin(), num_sphere_tris),
+ MutableSpan<Face *>(tris.begin(), sphere_tris_num),
0,
0,
&arena);
@@ -1001,9 +1001,9 @@ static void spheresphere_test(int nrings, double y_offset, bool use_self)
center2,
1.0,
true,
- MutableSpan<Face *>(tris.begin() + num_sphere_tris, num_sphere_tris),
- num_sphere_verts,
- num_sphere_verts,
+ MutableSpan<Face *>(tris.begin() + sphere_tris_num, sphere_tris_num),
+ sphere_verts_num,
+ sphere_verts_num,
&arena);
IMesh mesh(tris);
double time_create = PIL_check_seconds_timer();
@@ -1013,7 +1013,7 @@ static void spheresphere_test(int nrings, double y_offset, bool use_self)
out = trimesh_self_intersect(mesh, &arena);
}
else {
- int nf = num_sphere_tris;
+ int nf = sphere_tris_num;
out = trimesh_nary_intersect(
mesh, 2, [nf](int t) { return t < nf ? 0 : 1; }, false, &arena);
}
@@ -1028,14 +1028,14 @@ static void spheresphere_test(int nrings, double y_offset, bool use_self)
}
static void get_grid_params(
- int x_subdiv, int y_subdiv, bool triangulate, int *r_num_verts, int *r_num_faces)
+ int x_subdiv, int y_subdiv, bool triangulate, int *r_verts_num, int *r_faces_num)
{
- *r_num_verts = x_subdiv * y_subdiv;
+ *r_verts_num = x_subdiv * y_subdiv;
if (triangulate) {
- *r_num_faces = 2 * (x_subdiv - 1) * (y_subdiv - 1);
+ *r_faces_num = 2 * (x_subdiv - 1) * (y_subdiv - 1);
}
else {
- *r_num_faces = (x_subdiv - 1) * (y_subdiv - 1);
+ *r_faces_num = (x_subdiv - 1) * (y_subdiv - 1);
}
}
@@ -1053,11 +1053,11 @@ static void fill_grid_data(int x_subdiv,
if (x_subdiv <= 1 || y_subdiv <= 1) {
return;
}
- int num_verts;
- int num_faces;
- get_grid_params(x_subdiv, y_subdiv, triangulate, &num_verts, &num_faces);
- BLI_assert(face.size() == num_faces);
- Array<const Vert *> vert(num_verts);
+ int verts_num;
+ int faces_num;
+ get_grid_params(x_subdiv, y_subdiv, triangulate, &verts_num, &faces_num);
+ BLI_assert(face.size() == faces_num);
+ Array<const Vert *> vert(verts_num);
auto vert_index_fn = [x_subdiv](int ix, int iy) { return iy * x_subdiv + ix; };
auto face_index_fn = [x_subdiv](int ix, int iy) { return iy * (x_subdiv - 1) + ix; };
auto tri_index_fn = [x_subdiv](int ix, int iy, int tri) {
@@ -1119,24 +1119,24 @@ static void spheregrid_test(int nrings, int grid_level, double z_offset, bool us
BLI_task_scheduler_init(); /* Without this, no parallelism. */
double time_start = PIL_check_seconds_timer();
IMeshArena arena;
- int num_sphere_verts;
- int num_sphere_tris;
+ int sphere_verts_num;
+ int sphere_tris_num;
int nsegs = 2 * nrings;
- int num_grid_verts;
- int num_grid_tris;
+ int grid_verts_num;
+ int grid_tris_num;
int subdivs = 1 << grid_level;
- get_sphere_params(nrings, nsegs, true, &num_sphere_verts, &num_sphere_tris);
- get_grid_params(subdivs, subdivs, true, &num_grid_verts, &num_grid_tris);
- Array<Face *> tris(num_sphere_tris + num_grid_tris);
- arena.reserve(3 * (num_sphere_verts + num_grid_verts) / 2,
- 4 * (num_sphere_tris + num_grid_tris));
+ get_sphere_params(nrings, nsegs, true, &sphere_verts_num, &sphere_tris_num);
+ get_grid_params(subdivs, subdivs, true, &grid_verts_num, &grid_tris_num);
+ Array<Face *> tris(sphere_tris_num + grid_tris_num);
+ arena.reserve(3 * (sphere_verts_num + grid_verts_num) / 2,
+ 4 * (sphere_tris_num + grid_tris_num));
double3 center(0.0, 0.0, z_offset);
fill_sphere_data(nrings,
nsegs,
center,
1.0,
true,
- MutableSpan<Face *>(tris.begin(), num_sphere_tris),
+ MutableSpan<Face *>(tris.begin(), sphere_tris_num),
0,
0,
&arena);
@@ -1146,9 +1146,9 @@ static void spheregrid_test(int nrings, int grid_level, double z_offset, bool us
4.0,
double3(0, 0, 0),
0.0,
- MutableSpan<Face *>(tris.begin() + num_sphere_tris, num_grid_tris),
- num_sphere_verts,
- num_sphere_tris,
+ MutableSpan<Face *>(tris.begin() + sphere_tris_num, grid_tris_num),
+ sphere_verts_num,
+ sphere_tris_num,
&arena);
IMesh mesh(tris);
double time_create = PIL_check_seconds_timer();
@@ -1158,7 +1158,7 @@ static void spheregrid_test(int nrings, int grid_level, double z_offset, bool us
out = trimesh_self_intersect(mesh, &arena);
}
else {
- int nf = num_sphere_tris;
+ int nf = sphere_tris_num;
out = trimesh_nary_intersect(
mesh, 2, [nf](int t) { return t < nf ? 0 : 1; }, false, &arena);
}
@@ -1190,22 +1190,22 @@ static void gridgrid_test(int x_level_1,
int y_subdivs_1 = 1 << y_level_1;
int x_subdivs_2 = 1 << x_level_2;
int y_subdivs_2 = 1 << y_level_2;
- int num_grid_verts_1;
- int num_grid_verts_2;
- int num_grid_tris_1;
- int num_grid_tris_2;
- get_grid_params(x_subdivs_1, y_subdivs_1, true, &num_grid_verts_1, &num_grid_tris_1);
- get_grid_params(x_subdivs_2, y_subdivs_2, true, &num_grid_verts_2, &num_grid_tris_2);
- Array<Face *> tris(num_grid_tris_1 + num_grid_tris_2);
- arena.reserve(3 * (num_grid_verts_1 + num_grid_verts_2) / 2,
- 4 * (num_grid_tris_1 + num_grid_tris_2));
+ int grid_verts_1_num;
+ int grid_verts_2_num;
+ int grid_tris_1_num;
+ int grid_tris_2_num;
+ get_grid_params(x_subdivs_1, y_subdivs_1, true, &grid_verts_1_num, &grid_tris_1_num);
+ get_grid_params(x_subdivs_2, y_subdivs_2, true, &grid_verts_2_num, &grid_tris_2_num);
+ Array<Face *> tris(grid_tris_1_num + grid_tris_2_num);
+ arena.reserve(3 * (grid_verts_1_num + grid_verts_2_num) / 2,
+ 4 * (grid_tris_1_num + grid_tris_2_num));
fill_grid_data(x_subdivs_1,
y_subdivs_1,
true,
4.0,
double3(0, 0, 0),
0.0,
- MutableSpan<Face *>(tris.begin(), num_grid_tris_1),
+ MutableSpan<Face *>(tris.begin(), grid_tris_1_num),
0,
0,
&arena);
@@ -1215,9 +1215,9 @@ static void gridgrid_test(int x_level_1,
4.0,
double3(x_off, y_off, 0),
rot_deg,
- MutableSpan<Face *>(tris.begin() + num_grid_tris_1, num_grid_tris_2),
- num_grid_verts_1,
- num_grid_tris_1,
+ MutableSpan<Face *>(tris.begin() + grid_tris_1_num, grid_tris_2_num),
+ grid_verts_1_num,
+ grid_tris_1_num,
&arena);
IMesh mesh(tris);
double time_create = PIL_check_seconds_timer();
@@ -1227,7 +1227,7 @@ static void gridgrid_test(int x_level_1,
out = trimesh_self_intersect(mesh, &arena);
}
else {
- int nf = num_grid_tris_1;
+ int nf = grid_tris_1_num;
out = trimesh_nary_intersect(
mesh, 2, [nf](int t) { return t < nf ? 0 : 1; }, false, &arena);
}
diff --git a/source/blender/blenlib/tests/BLI_polyfill_2d_test.cc b/source/blender/blenlib/tests/BLI_polyfill_2d_test.cc
index 3efa35a0048..db2fb1ba671 100644
--- a/source/blender/blenlib/tests/BLI_polyfill_2d_test.cc
+++ b/source/blender/blenlib/tests/BLI_polyfill_2d_test.cc
@@ -29,19 +29,19 @@
static void polyfill_to_obj(const char *id,
const float poly[][2],
- const unsigned int poly_tot,
+ const unsigned int poly_num,
const unsigned int tris[][3],
- const unsigned int tris_tot);
+ const unsigned int tris_num);
/* -------------------------------------------------------------------- */
/* test utility functions */
#define TRI_ERROR_VALUE (unsigned int)-1
-static void test_valid_polyfill_prepare(unsigned int tris[][3], unsigned int tris_tot)
+static void test_valid_polyfill_prepare(unsigned int tris[][3], unsigned int tris_num)
{
unsigned int i;
- for (i = 0; i < tris_tot; i++) {
+ for (i = 0; i < tris_num; i++) {
unsigned int j;
for (j = 0; j < 3; j++) {
tris[i][j] = TRI_ERROR_VALUE;
@@ -57,37 +57,37 @@ static void test_valid_polyfill_prepare(unsigned int tris[][3], unsigned int tri
* - all verts used at least once.
*/
static void test_polyfill_simple(const float /*poly*/[][2],
- const unsigned int poly_tot,
+ const unsigned int poly_num,
const unsigned int tris[][3],
- const unsigned int tris_tot)
+ const unsigned int tris_num)
{
unsigned int i;
- int *tot_used = (int *)MEM_callocN(poly_tot * sizeof(int), __func__);
- for (i = 0; i < tris_tot; i++) {
+ int *used_num = (int *)MEM_callocN(poly_num * sizeof(int), __func__);
+ for (i = 0; i < tris_num; i++) {
unsigned int j;
for (j = 0; j < 3; j++) {
EXPECT_NE(TRI_ERROR_VALUE, tris[i][j]);
- tot_used[tris[i][j]] += 1;
+ used_num[tris[i][j]] += 1;
}
EXPECT_NE(tris[i][0], tris[i][1]);
EXPECT_NE(tris[i][1], tris[i][2]);
EXPECT_NE(tris[i][2], tris[i][0]);
}
- for (i = 0; i < poly_tot; i++) {
- EXPECT_NE(0, tot_used[i]);
+ for (i = 0; i < poly_num; i++) {
+ EXPECT_NE(0, used_num[i]);
}
- MEM_freeN(tot_used);
+ MEM_freeN(used_num);
}
static void test_polyfill_topology(const float /*poly*/[][2],
- const unsigned int poly_tot,
+ const unsigned int poly_num,
const unsigned int tris[][3],
- const unsigned int tris_tot)
+ const unsigned int tris_num)
{
EdgeHash *edgehash = BLI_edgehash_new(__func__);
EdgeHashIterator *ehi;
unsigned int i;
- for (i = 0; i < tris_tot; i++) {
+ for (i = 0; i < tris_num; i++) {
unsigned int j;
for (j = 0; j < 3; j++) {
const unsigned int v1 = tris[i][j];
@@ -101,11 +101,11 @@ static void test_polyfill_topology(const float /*poly*/[][2],
}
}
}
- EXPECT_EQ(BLI_edgehash_len(edgehash), poly_tot + (poly_tot - 3));
+ EXPECT_EQ(BLI_edgehash_len(edgehash), poly_num + (poly_num - 3));
- for (i = 0; i < poly_tot; i++) {
+ for (i = 0; i < poly_num; i++) {
const unsigned int v1 = i;
- const unsigned int v2 = (i + 1) % poly_tot;
+ const unsigned int v2 = (i + 1) % poly_num;
void **p = BLI_edgehash_lookup_p(edgehash, v1, v2);
EXPECT_NE((void *)p, nullptr);
EXPECT_EQ((intptr_t)*p, 1);
@@ -125,13 +125,13 @@ static void test_polyfill_topology(const float /*poly*/[][2],
* Check all faces are flipped the same way
*/
static void test_polyfill_winding(const float poly[][2],
- const unsigned int /*poly_tot*/,
+ const unsigned int /*poly_num*/,
const unsigned int tris[][3],
- const unsigned int tris_tot)
+ const unsigned int tris_num)
{
unsigned int i;
unsigned int count[2] = {0, 0};
- for (i = 0; i < tris_tot; i++) {
+ for (i = 0; i < tris_num; i++) {
float winding_test = cross_tri_v2(poly[tris[i][0]], poly[tris[i][1]], poly[tris[i][2]]);
if (fabsf(winding_test) > FLT_EPSILON) {
count[winding_test < 0.0f] += 1;
@@ -144,19 +144,19 @@ static void test_polyfill_winding(const float poly[][2],
* Check the accumulated triangle area is close to the original area.
*/
static void test_polyfill_area(const float poly[][2],
- const unsigned int poly_tot,
+ const unsigned int poly_num,
const unsigned int tris[][3],
- const unsigned int tris_tot)
+ const unsigned int tris_num)
{
unsigned int i;
- const float area_tot = area_poly_v2(poly, poly_tot);
- float area_tot_tris = 0.0f;
+ const float area_total = area_poly_v2(poly, poly_num);
+ float area_total_tris = 0.0f;
const float eps_abs = 0.00001f;
- const float eps = area_tot > 1.0f ? (area_tot * eps_abs) : eps_abs;
- for (i = 0; i < tris_tot; i++) {
- area_tot_tris += area_tri_v2(poly[tris[i][0]], poly[tris[i][1]], poly[tris[i][2]]);
+ const float eps = area_total > 1.0f ? (area_total * eps_abs) : eps_abs;
+ for (i = 0; i < tris_num; i++) {
+ area_total_tris += area_tri_v2(poly[tris[i][0]], poly[tris[i][1]], poly[tris[i][2]]);
}
- EXPECT_NEAR(area_tot, area_tot_tris, eps);
+ EXPECT_NEAR(area_total, area_total_tris, eps);
}
/* -------------------------------------------------------------------- */
@@ -167,32 +167,32 @@ static void test_polyfill_area(const float poly[][2],
static void test_polyfill_template_check(const char *id,
bool is_degenerate,
const float poly[][2],
- const unsigned int poly_tot,
+ const unsigned int poly_num,
const unsigned int tris[][3],
- const unsigned int tris_tot)
+ const unsigned int tris_num)
{
- test_polyfill_simple(poly, poly_tot, tris, tris_tot);
- test_polyfill_topology(poly, poly_tot, tris, tris_tot);
+ test_polyfill_simple(poly, poly_num, tris, tris_num);
+ test_polyfill_topology(poly, poly_num, tris, tris_num);
if (!is_degenerate) {
- test_polyfill_winding(poly, poly_tot, tris, tris_tot);
+ test_polyfill_winding(poly, poly_num, tris, tris_num);
- test_polyfill_area(poly, poly_tot, tris, tris_tot);
+ test_polyfill_area(poly, poly_num, tris, tris_num);
}
- polyfill_to_obj(id, poly, poly_tot, tris, tris_tot);
+ polyfill_to_obj(id, poly, poly_num, tris, tris_num);
}
static void test_polyfill_template(const char *id,
bool is_degenerate,
const float poly[][2],
- const unsigned int poly_tot,
+ const unsigned int poly_num,
unsigned int tris[][3],
- const unsigned int tris_tot)
+ const unsigned int tris_num)
{
- test_valid_polyfill_prepare(tris, tris_tot);
- BLI_polyfill_calc(poly, poly_tot, 0, tris);
+ test_valid_polyfill_prepare(tris, tris_num);
+ BLI_polyfill_calc(poly, poly_num, 0, tris);
/* check all went well */
- test_polyfill_template_check(id, is_degenerate, poly, poly_tot, tris, tris_tot);
+ test_polyfill_template_check(id, is_degenerate, poly, poly_num, tris, tris_num);
#ifdef USE_BEAUTIFY
/* check beautify gives good results too */
@@ -200,9 +200,9 @@ static void test_polyfill_template(const char *id,
MemArena *pf_arena = BLI_memarena_new(BLI_POLYFILL_ARENA_SIZE, __func__);
Heap *pf_heap = BLI_heap_new_ex(BLI_POLYFILL_ALLOC_NGON_RESERVE);
- BLI_polyfill_beautify(poly, poly_tot, tris, pf_arena, pf_heap);
+ BLI_polyfill_beautify(poly, poly_num, tris, pf_arena, pf_heap);
- test_polyfill_template_check(id, is_degenerate, poly, poly_tot, tris, tris_tot);
+ test_polyfill_template_check(id, is_degenerate, poly, poly_num, tris, tris_num);
BLI_memarena_free(pf_arena);
BLI_heap_free(pf_heap, nullptr);
@@ -213,20 +213,20 @@ static void test_polyfill_template(const char *id,
static void test_polyfill_template_flip_sign(const char *id,
bool is_degenerate,
const float poly[][2],
- const unsigned int poly_tot,
+ const unsigned int poly_num,
unsigned int tris[][3],
- const unsigned int tris_tot)
+ const unsigned int tris_num)
{
- float(*poly_copy)[2] = (float(*)[2])MEM_mallocN(sizeof(float[2]) * poly_tot, id);
+ float(*poly_copy)[2] = (float(*)[2])MEM_mallocN(sizeof(float[2]) * poly_num, id);
for (int flip_x = 0; flip_x < 2; flip_x++) {
for (int flip_y = 0; flip_y < 2; flip_y++) {
float sign_x = flip_x ? -1.0f : 1.0f;
float sign_y = flip_y ? -1.0f : 1.0f;
- for (int i = 0; i < poly_tot; i++) {
+ for (int i = 0; i < poly_num; i++) {
poly_copy[i][0] = poly[i][0] * sign_x;
poly_copy[i][1] = poly[i][1] * sign_y;
}
- test_polyfill_template(id, is_degenerate, poly_copy, poly_tot, tris, tris_tot);
+ test_polyfill_template(id, is_degenerate, poly_copy, poly_num, tris, tris_num);
}
}
MEM_freeN(poly_copy);
@@ -236,32 +236,32 @@ static void test_polyfill_template_flip_sign(const char *id,
static void test_polyfill_template_main(const char *id,
bool is_degenerate,
const float poly[][2],
- const unsigned int poly_tot,
+ const unsigned int poly_num,
unsigned int tris[][3],
- const unsigned int tris_tot)
+ const unsigned int tris_num)
{
/* overkill? - try at _every_ offset & reverse */
unsigned int poly_reverse;
- float(*poly_copy)[2] = (float(*)[2])MEM_mallocN(sizeof(float[2]) * poly_tot, id);
+ float(*poly_copy)[2] = (float(*)[2])MEM_mallocN(sizeof(float[2]) * poly_num, id);
float tmp[2];
- memcpy(poly_copy, poly, sizeof(float[2]) * poly_tot);
+ memcpy(poly_copy, poly, sizeof(float[2]) * poly_num);
for (poly_reverse = 0; poly_reverse < 2; poly_reverse++) {
unsigned int poly_cycle;
if (poly_reverse) {
- BLI_array_reverse(poly_copy, poly_tot);
+ BLI_array_reverse(poly_copy, poly_num);
}
- for (poly_cycle = 0; poly_cycle < poly_tot; poly_cycle++) {
+ for (poly_cycle = 0; poly_cycle < poly_num; poly_cycle++) {
// printf("polytest %s ofs=%d, reverse=%d\n", id, poly_cycle, poly_reverse);
- test_polyfill_template_flip_sign(id, is_degenerate, poly, poly_tot, tris, tris_tot);
+ test_polyfill_template_flip_sign(id, is_degenerate, poly, poly_num, tris, tris_num);
/* cycle */
copy_v2_v2(tmp, poly_copy[0]);
- memmove(&poly_copy[0], &poly_copy[1], (poly_tot - 1) * sizeof(float[2]));
- copy_v2_v2(poly_copy[poly_tot - 1], tmp);
+ memmove(&poly_copy[0], &poly_copy[1], (poly_num - 1) * sizeof(float[2]));
+ copy_v2_v2(poly_copy[poly_num - 1], tmp);
}
}
@@ -271,22 +271,22 @@ static void test_polyfill_template_main(const char *id,
static void test_polyfill_template_main(const char *id,
bool is_degenerate,
const float poly[][2],
- const unsigned int poly_tot,
+ const unsigned int poly_num,
unsigned int tris[][3],
- const unsigned int tris_tot)
+ const unsigned int tris_num)
{
- test_polyfill_template_flip_sign(id, is_degenerate, poly, poly_tot, tris, tris_tot);
+ test_polyfill_template_flip_sign(id, is_degenerate, poly, poly_num, tris, tris_num);
}
#endif /* USE_COMBINATIONS_ALL */
#define TEST_POLYFILL_TEMPLATE_STATIC(poly, is_degenerate) \
{ \
unsigned int tris[POLY_TRI_COUNT(ARRAY_SIZE(poly))][3]; \
- const unsigned int poly_tot = ARRAY_SIZE(poly); \
- const unsigned int tris_tot = ARRAY_SIZE(tris); \
+ const unsigned int poly_num = ARRAY_SIZE(poly); \
+ const unsigned int tris_num = ARRAY_SIZE(tris); \
const char *id = typeid(*this).name(); \
\
- test_polyfill_template_main(id, is_degenerate, poly, poly_tot, tris, tris_tot); \
+ test_polyfill_template_main(id, is_degenerate, poly, poly_num, tris, tris_num); \
} \
(void)0
@@ -296,9 +296,9 @@ static void test_polyfill_template_main(const char *id,
#ifdef USE_OBJ_PREVIEW
static void polyfill_to_obj(const char *id,
const float poly[][2],
- const unsigned int poly_tot,
+ const unsigned int poly_num,
const unsigned int tris[][3],
- const unsigned int tris_tot)
+ const unsigned int tris_num)
{
char path[1024];
FILE *f;
@@ -311,11 +311,11 @@ static void polyfill_to_obj(const char *id,
return;
}
- for (i = 0; i < poly_tot; i++) {
+ for (i = 0; i < poly_num; i++) {
fprintf(f, "v %f %f 0.0\n", UNPACK2(poly[i]));
}
- for (i = 0; i < tris_tot; i++) {
+ for (i = 0; i < tris_num; i++) {
fprintf(f, "f %u %u %u\n", UNPACK3_EX(1 +, tris[i], ));
}
@@ -324,13 +324,13 @@ static void polyfill_to_obj(const char *id,
#else
static void polyfill_to_obj(const char *id,
const float poly[][2],
- const unsigned int poly_tot,
+ const unsigned int poly_num,
const unsigned int tris[][3],
- const unsigned int tris_tot)
+ const unsigned int tris_num)
{
(void)id;
- (void)poly, (void)poly_tot;
- (void)tris, (void)tris_tot;
+ (void)poly, (void)poly_num;
+ (void)tris, (void)tris_num;
}
#endif /* USE_OBJ_PREVIEW */
diff --git a/source/blender/blenlib/tests/BLI_string_test.cc b/source/blender/blenlib/tests/BLI_string_test.cc
index 553bd8453e0..6c16af5767c 100644
--- a/source/blender/blenlib/tests/BLI_string_test.cc
+++ b/source/blender/blenlib/tests/BLI_string_test.cc
@@ -324,35 +324,35 @@ TEST(string, StrPartitionExUtf8)
/* BLI_str_format_int_grouped */
TEST(string, StrFormatIntGrouped)
{
- char num_str[16];
- int num;
+ char number_str[16];
+ int number;
- BLI_str_format_int_grouped(num_str, num = 0);
- EXPECT_STREQ("0", num_str);
+ BLI_str_format_int_grouped(number_str, number = 0);
+ EXPECT_STREQ("0", number_str);
- BLI_str_format_int_grouped(num_str, num = 1);
- EXPECT_STREQ("1", num_str);
+ BLI_str_format_int_grouped(number_str, number = 1);
+ EXPECT_STREQ("1", number_str);
- BLI_str_format_int_grouped(num_str, num = -1);
- EXPECT_STREQ("-1", num_str);
+ BLI_str_format_int_grouped(number_str, number = -1);
+ EXPECT_STREQ("-1", number_str);
- BLI_str_format_int_grouped(num_str, num = -2147483648);
- EXPECT_STREQ("-2,147,483,648", num_str);
+ BLI_str_format_int_grouped(number_str, number = -2147483648);
+ EXPECT_STREQ("-2,147,483,648", number_str);
- BLI_str_format_int_grouped(num_str, num = 2147483647);
- EXPECT_STREQ("2,147,483,647", num_str);
+ BLI_str_format_int_grouped(number_str, number = 2147483647);
+ EXPECT_STREQ("2,147,483,647", number_str);
- BLI_str_format_int_grouped(num_str, num = 1000);
- EXPECT_STREQ("1,000", num_str);
+ BLI_str_format_int_grouped(number_str, number = 1000);
+ EXPECT_STREQ("1,000", number_str);
- BLI_str_format_int_grouped(num_str, num = -1000);
- EXPECT_STREQ("-1,000", num_str);
+ BLI_str_format_int_grouped(number_str, number = -1000);
+ EXPECT_STREQ("-1,000", number_str);
- BLI_str_format_int_grouped(num_str, num = 999);
- EXPECT_STREQ("999", num_str);
+ BLI_str_format_int_grouped(number_str, number = 999);
+ EXPECT_STREQ("999", number_str);
- BLI_str_format_int_grouped(num_str, num = -999);
- EXPECT_STREQ("-999", num_str);
+ BLI_str_format_int_grouped(number_str, number = -999);
+ EXPECT_STREQ("-999", number_str);
}
/* BLI_str_format_byte_unit */
diff --git a/source/blender/blenlib/tests/BLI_string_utf8_test.cc b/source/blender/blenlib/tests/BLI_string_utf8_test.cc
index a2b8e139510..2da439dad18 100644
--- a/source/blender/blenlib/tests/BLI_string_utf8_test.cc
+++ b/source/blender/blenlib/tests/BLI_string_utf8_test.cc
@@ -274,15 +274,15 @@ TEST(string, Utf8InvalidBytes)
for (int i = 0; utf8_invalid_tests[i][0] != nullptr; i++) {
const char *tst = utf8_invalid_tests[i][0];
const char *tst_stripped = utf8_invalid_tests[i][1];
- const int num_errors = (int)utf8_invalid_tests[i][2][0];
+ const int errors_num = (int)utf8_invalid_tests[i][2][0];
char buff[80];
memcpy(buff, tst, sizeof(buff));
- const int num_errors_found = BLI_str_utf8_invalid_strip(buff, sizeof(buff) - 1);
+ const int errors_found_num = BLI_str_utf8_invalid_strip(buff, sizeof(buff) - 1);
- printf("[%02d] -> [%02d] \"%s\" -> \"%s\"\n", num_errors, num_errors_found, tst, buff);
- EXPECT_EQ(num_errors_found, num_errors);
+ printf("[%02d] -> [%02d] \"%s\" -> \"%s\"\n", errors_num, errors_found_num, tst, buff);
+ EXPECT_EQ(errors_found_num, errors_num);
EXPECT_STREQ(buff, tst_stripped);
}
}
diff --git a/source/blender/blenlib/tests/BLI_task_test.cc b/source/blender/blenlib/tests/BLI_task_test.cc
index 52852873a06..a933d45e7cd 100644
--- a/source/blender/blenlib/tests/BLI_task_test.cc
+++ b/source/blender/blenlib/tests/BLI_task_test.cc
@@ -15,7 +15,7 @@
#include "BLI_task.h"
#include "BLI_task.hh"
-#define NUM_ITEMS 10000
+#define ITEMS_NUM 10000
/* *** Parallel iterations over range of integer values. *** */
@@ -34,12 +34,12 @@ static void task_range_iter_reduce_func(const void *__restrict UNUSED(userdata),
int *join = (int *)join_v;
int *chunk = (int *)userdata_chunk;
*join += *chunk;
- // printf("%d, %d\n", data[NUM_ITEMS], *((int *)userdata_chunk));
+ // printf("%d, %d\n", data[ITEMS_NUM], *((int *)userdata_chunk));
}
TEST(task, RangeIter)
{
- int data[NUM_ITEMS] = {0};
+ int data[ITEMS_NUM] = {0};
int sum = 0;
BLI_threadapi_init();
@@ -52,13 +52,13 @@ TEST(task, RangeIter)
settings.userdata_chunk_size = sizeof(sum);
settings.func_reduce = task_range_iter_reduce_func;
- BLI_task_parallel_range(0, NUM_ITEMS, data, task_range_iter_func, &settings);
+ BLI_task_parallel_range(0, ITEMS_NUM, data, task_range_iter_func, &settings);
/* Those checks should ensure us all items of the listbase were processed once, and only once
* as expected. */
int expected_sum = 0;
- for (int i = 0; i < NUM_ITEMS; i++) {
+ for (int i = 0; i < ITEMS_NUM; i++) {
EXPECT_EQ(data[i], i);
expected_sum += i;
}
@@ -84,41 +84,41 @@ static void task_mempool_iter_func(void *userdata,
TEST(task, MempoolIter)
{
- int *data[NUM_ITEMS];
+ int *data[ITEMS_NUM];
BLI_threadapi_init();
BLI_mempool *mempool = BLI_mempool_create(
- sizeof(*data[0]), NUM_ITEMS, 32, BLI_MEMPOOL_ALLOW_ITER);
+ sizeof(*data[0]), ITEMS_NUM, 32, BLI_MEMPOOL_ALLOW_ITER);
int i;
/* '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++) {
+ int items_num = 0;
+ for (i = 0; i < ITEMS_NUM; i++) {
data[i] = (int *)BLI_mempool_alloc(mempool);
*data[i] = i - 1;
- num_items++;
+ items_num++;
}
- for (i = 0; i < NUM_ITEMS; i += 3) {
+ for (i = 0; i < ITEMS_NUM; i += 3) {
BLI_mempool_free(mempool, data[i]);
data[i] = nullptr;
- num_items--;
+ items_num--;
}
- for (i = 0; i < NUM_ITEMS; i += 7) {
+ for (i = 0; i < ITEMS_NUM; i += 7) {
if (data[i] == nullptr) {
data[i] = (int *)BLI_mempool_alloc(mempool);
*data[i] = i - 1;
- num_items++;
+ items_num++;
}
}
- for (i = 0; i < NUM_ITEMS - 5; i += 23) {
+ for (i = 0; i < ITEMS_NUM - 5; i += 23) {
for (int j = 0; j < 5; j++) {
if (data[i + j] != nullptr) {
BLI_mempool_free(mempool, data[i + j]);
data[i + j] = nullptr;
- num_items--;
+ items_num--;
}
}
}
@@ -126,12 +126,12 @@ TEST(task, MempoolIter)
TaskParallelSettings settings;
BLI_parallel_mempool_settings_defaults(&settings);
- BLI_task_parallel_mempool(mempool, &num_items, task_mempool_iter_func, &settings);
+ BLI_task_parallel_mempool(mempool, &items_num, task_mempool_iter_func, &settings);
/* Those checks should ensure us all items of the mempool were processed once, and only once - as
* expected. */
- EXPECT_EQ(num_items, 0);
- for (i = 0; i < NUM_ITEMS; i++) {
+ EXPECT_EQ(items_num, 0);
+ for (i = 0; i < ITEMS_NUM; i++) {
if (data[i] != nullptr) {
EXPECT_EQ(*data[i], i);
}
@@ -189,19 +189,19 @@ static void task_mempool_iter_tls_free(const void *UNUSED(userdata),
TEST(task, MempoolIterTLS)
{
- int *data[NUM_ITEMS];
+ int *data[ITEMS_NUM];
BLI_threadapi_init();
BLI_mempool *mempool = BLI_mempool_create(
- sizeof(*data[0]), NUM_ITEMS, 32, BLI_MEMPOOL_ALLOW_ITER);
+ sizeof(*data[0]), ITEMS_NUM, 32, BLI_MEMPOOL_ALLOW_ITER);
int i;
- /* Add numbers negative `1..NUM_ITEMS` inclusive. */
- int num_items = 0;
- for (i = 0; i < NUM_ITEMS; i++) {
+ /* Add numbers negative `1..ITEMS_NUM` inclusive. */
+ int items_num = 0;
+ for (i = 0; i < ITEMS_NUM; i++) {
data[i] = (int *)BLI_mempool_alloc(mempool);
*data[i] = -(i + 1);
- num_items++;
+ items_num++;
}
TaskParallelSettings settings;
@@ -218,15 +218,15 @@ TEST(task, MempoolIterTLS)
BLI_task_parallel_mempool(mempool, nullptr, task_mempool_iter_tls_func, &settings);
- EXPECT_EQ(BLI_listbase_count(tls_data.accumulate_items), NUM_ITEMS);
+ EXPECT_EQ(BLI_listbase_count(tls_data.accumulate_items), ITEMS_NUM);
/* Check that all elements are added into the list once. */
- int num_accum = 0;
+ int number_accum = 0;
for (LinkData *link = (LinkData *)tls_data.accumulate_items->first; link; link = link->next) {
int *data = (int *)link->data;
- num_accum += *data;
+ number_accum += *data;
}
- EXPECT_EQ(num_accum, (NUM_ITEMS * (NUM_ITEMS + 1)) / 2);
+ EXPECT_EQ(number_accum, (ITEMS_NUM * (ITEMS_NUM + 1)) / 2);
BLI_freelistN(tls_data.accumulate_items);
MEM_freeN(tls_data.accumulate_items);
@@ -253,31 +253,31 @@ TEST(task, ListBaseIter)
{
ListBase list = {nullptr, nullptr};
LinkData *items_buffer = (LinkData *)MEM_calloc_arrayN(
- NUM_ITEMS, sizeof(*items_buffer), __func__);
+ ITEMS_NUM, sizeof(*items_buffer), __func__);
BLI_threadapi_init();
int i;
- int num_items = 0;
- for (i = 0; i < NUM_ITEMS; i++) {
+ int items_num = 0;
+ for (i = 0; i < ITEMS_NUM; i++) {
BLI_addtail(&list, &items_buffer[i]);
- num_items++;
+ items_num++;
}
TaskParallelSettings settings;
BLI_parallel_range_settings_defaults(&settings);
- BLI_task_parallel_listbase(&list, &num_items, task_listbase_iter_func, &settings);
+ BLI_task_parallel_listbase(&list, &items_num, task_listbase_iter_func, &settings);
/* Those checks should ensure us all items of the listbase were processed once, and only once -
* as expected. */
- EXPECT_EQ(num_items, 0);
+ EXPECT_EQ(items_num, 0);
LinkData *item;
- for (i = 0, item = (LinkData *)list.first; i < NUM_ITEMS && item != nullptr;
+ for (i = 0, item = (LinkData *)list.first; i < ITEMS_NUM && item != nullptr;
i++, item = item->next) {
EXPECT_EQ(POINTER_AS_INT(item->data), i);
}
- EXPECT_EQ(NUM_ITEMS, i);
+ EXPECT_EQ(ITEMS_NUM, i);
MEM_freeN(items_buffer);
BLI_threadapi_exit();
diff --git a/source/blender/blenlib/tests/performance/BLI_task_performance_test.cc b/source/blender/blenlib/tests/performance/BLI_task_performance_test.cc
index 98fafe55d69..a86e9b0b86d 100644
--- a/source/blender/blenlib/tests/performance/BLI_task_performance_test.cc
+++ b/source/blender/blenlib/tests/performance/BLI_task_performance_test.cc
@@ -95,12 +95,12 @@ static void task_listbase_heavy_membarrier_iter_func(void *userdata,
}
static void task_listbase_test_do(ListBase *list,
- const int num_items,
- int *num_items_tmp,
+ const int items_num,
+ int *items_tmp_num,
const char *id,
TaskParallelIteratorFunc func,
const bool use_threads,
- const bool check_num_items_tmp)
+ const bool check_items_tmp_num)
{
TaskParallelSettings settings;
BLI_parallel_range_settings_defaults(&settings);
@@ -109,24 +109,24 @@ static void task_listbase_test_do(ListBase *list,
double averaged_timing = 0.0;
for (int i = 0; i < NUM_RUN_AVERAGED; i++) {
const double init_time = PIL_check_seconds_timer();
- BLI_task_parallel_listbase(list, num_items_tmp, func, &settings);
+ BLI_task_parallel_listbase(list, items_tmp_num, func, &settings);
averaged_timing += PIL_check_seconds_timer() - init_time;
/* Those checks should ensure us all items of the listbase were processed once, and only once -
* as expected. */
- if (check_num_items_tmp) {
- EXPECT_EQ(*num_items_tmp, 0);
+ if (check_items_tmp_num) {
+ EXPECT_EQ(*items_tmp_num, 0);
}
LinkData *item;
int j;
- for (j = 0, item = (LinkData *)list->first; j < num_items && item != nullptr;
+ for (j = 0, item = (LinkData *)list->first; j < items_num && item != nullptr;
j++, item = item->next) {
EXPECT_EQ(POINTER_AS_INT(item->data), j);
item->data = POINTER_FROM_INT(0);
}
- EXPECT_EQ(num_items, j);
+ EXPECT_EQ(items_num, j);
- *num_items_tmp = num_items;
+ *items_tmp_num = items_num;
}
printf("\t%s: done in %fs on average over %d runs\n",
@@ -144,40 +144,40 @@ static void task_listbase_test(const char *id, const int count, const bool use_t
BLI_threadapi_init();
- int num_items = 0;
+ int items_num = 0;
for (int i = 0; i < count; i++) {
BLI_addtail(&list, &items_buffer[i]);
- num_items++;
+ items_num++;
}
- int num_items_tmp = num_items;
+ int items_tmp_num = items_num;
task_listbase_test_do(&list,
- num_items,
- &num_items_tmp,
+ items_num,
+ &items_tmp_num,
"Light iter",
task_listbase_light_iter_func,
use_threads,
false);
task_listbase_test_do(&list,
- num_items,
- &num_items_tmp,
+ items_num,
+ &items_tmp_num,
"Light iter with mem barrier",
task_listbase_light_membarrier_iter_func,
use_threads,
true);
task_listbase_test_do(&list,
- num_items,
- &num_items_tmp,
+ items_num,
+ &items_tmp_num,
"Heavy iter",
task_listbase_heavy_iter_func,
use_threads,
false);
task_listbase_test_do(&list,
- num_items,
- &num_items_tmp,
+ items_num,
+ &items_tmp_num,
"Heavy iter with mem barrier",
task_listbase_heavy_membarrier_iter_func,
use_threads,
diff --git a/source/blender/blenloader/intern/versioning_300.c b/source/blender/blenloader/intern/versioning_300.c
index adc6b990869..eee0e7fbea8 100644
--- a/source/blender/blenloader/intern/versioning_300.c
+++ b/source/blender/blenloader/intern/versioning_300.c
@@ -1569,10 +1569,10 @@ void blo_do_versions_300(FileData *fd, Library *UNUSED(lib), Main *bmain)
LISTBASE_FOREACH (ModifierData *, md, &ob->modifiers) {
if (md->type == eModifierType_SurfaceDeform) {
SurfaceDeformModifierData *smd = (SurfaceDeformModifierData *)md;
- if (smd->num_bind_verts && smd->verts) {
- smd->num_mesh_verts = smd->num_bind_verts;
+ if (smd->bind_verts_num && smd->verts) {
+ smd->mesh_verts_num = smd->bind_verts_num;
- for (unsigned int i = 0; i < smd->num_bind_verts; i++) {
+ for (unsigned int i = 0; i < smd->bind_verts_num; i++) {
smd->verts[i].vertex_idx = i;
}
}
@@ -2435,17 +2435,27 @@ void blo_do_versions_300(FileData *fd, Library *UNUSED(lib), Main *bmain)
}
}
- /**
- * Versioning code until next subversion bump goes here.
- *
- * \note Be sure to check when bumping the version:
- * - "versioning_userdef.c", #blo_do_versions_userdef
- * - "versioning_userdef.c", #do_versions_theme
- *
- * \note Keep this message at the bottom of the function.
- */
- {
- /* Keep this block, even when empty. */
+ if (!MAIN_VERSION_ATLEAST(bmain, 302, 7)) {
+ /* Generate 'system' liboverrides IDs.
+ * NOTE: This is a fairly rough process, based on very basic heuristics. Should be enough for a
+ * do_version code though, this is a new optional feature, not a critical conversion. */
+ ID *id;
+ FOREACH_MAIN_ID_BEGIN (bmain, id) {
+ if (!ID_IS_OVERRIDE_LIBRARY_REAL(id) || ID_IS_LINKED(id)) {
+ /* Ignore non-real liboverrides, and linked ones. */
+ continue;
+ }
+ if (GS(id->name) == ID_OB) {
+ /* Never 'lock' an object into a system override for now. */
+ continue;
+ }
+ if (BKE_lib_override_library_is_user_edited(id)) {
+ /* Do not 'lock' an ID already edited by the user. */
+ continue;
+ }
+ id->override_library->flag |= IDOVERRIDE_LIBRARY_FLAG_SYSTEM_DEFINED;
+ }
+ FOREACH_MAIN_ID_END;
/* Initialize brush curves sculpt settings. */
LISTBASE_FOREACH (Brush *, brush, &bmain->brushes) {
@@ -2476,4 +2486,17 @@ void blo_do_versions_300(FileData *fd, Library *UNUSED(lib), Main *bmain)
}
}
}
+
+ /**
+ * Versioning code until next subversion bump goes here.
+ *
+ * \note Be sure to check when bumping the version:
+ * - "versioning_userdef.c", #blo_do_versions_userdef
+ * - "versioning_userdef.c", #do_versions_theme
+ *
+ * \note Keep this message at the bottom of the function.
+ */
+ {
+ /* Keep this block, even when empty. */
+ }
}
diff --git a/source/blender/blenloader/intern/versioning_legacy.c b/source/blender/blenloader/intern/versioning_legacy.c
index 16297149cc3..4c27b8b9016 100644
--- a/source/blender/blenloader/intern/versioning_legacy.c
+++ b/source/blender/blenloader/intern/versioning_legacy.c
@@ -1254,7 +1254,7 @@ void blo_do_versions_pre250(FileData *fd, Library *lib, Main *bmain)
}
cam = cam->id.next;
}
- /* Force oops draw if depgraph was set. */
+ /* Force oops draw if depsgraph was set. */
/* Set time line var. */
/* softbody init new vars */
diff --git a/source/blender/blenloader/intern/versioning_userdef.c b/source/blender/blenloader/intern/versioning_userdef.c
index 3b966fe5358..ec76f516780 100644
--- a/source/blender/blenloader/intern/versioning_userdef.c
+++ b/source/blender/blenloader/intern/versioning_userdef.c
@@ -324,6 +324,10 @@ static void do_versions_theme(const UserDef *userdef, bTheme *btheme)
if (!USER_VERSION_ATLEAST(301, 2)) {
FROM_DEFAULT_V4_UCHAR(space_sequencer.mask);
}
+
+ if (!USER_VERSION_ATLEAST(302, 8)) {
+ btheme->space_node.grid_levels = U_theme_default.space_node.grid_levels;
+ }
/**
* Versioning code until next subversion bump goes here.
*
diff --git a/source/blender/bmesh/intern/bmesh_mesh_convert.cc b/source/blender/bmesh/intern/bmesh_mesh_convert.cc
index 118e7751cbc..40f1d7c496d 100644
--- a/source/blender/bmesh/intern/bmesh_mesh_convert.cc
+++ b/source/blender/bmesh/intern/bmesh_mesh_convert.cc
@@ -1096,7 +1096,7 @@ void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMesh
vertMap = bm_to_mesh_vertex_map(bm, ototvert);
}
- for (i = j = 0; i < hmd->totindex; i++) {
+ for (i = j = 0; i < hmd->indexar_num; i++) {
if (hmd->indexar[i] < ototvert) {
eve = vertMap[hmd->indexar[i]];
@@ -1109,7 +1109,7 @@ void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMesh
}
}
- hmd->totindex = j;
+ hmd->indexar_num = j;
}
}
}
diff --git a/source/blender/compositor/operations/COM_OutputFileOperation.cc b/source/blender/compositor/operations/COM_OutputFileOperation.cc
index cde1496546e..372e0736cd2 100644
--- a/source/blender/compositor/operations/COM_OutputFileOperation.cc
+++ b/source/blender/compositor/operations/COM_OutputFileOperation.cc
@@ -225,6 +225,11 @@ OutputSingleLayerOperation::OutputSingleLayerOperation(const Scene *scene,
save_as_render_ = save_as_render;
}
+OutputSingleLayerOperation::~OutputSingleLayerOperation()
+{
+ BKE_image_format_free(&format_);
+}
+
void OutputSingleLayerOperation::init_execution()
{
image_input_ = get_input_socket_reader(0);
diff --git a/source/blender/compositor/operations/COM_OutputFileOperation.h b/source/blender/compositor/operations/COM_OutputFileOperation.h
index 98b7e77cc21..875defe00e9 100644
--- a/source/blender/compositor/operations/COM_OutputFileOperation.h
+++ b/source/blender/compositor/operations/COM_OutputFileOperation.h
@@ -39,6 +39,7 @@ class OutputSingleLayerOperation : public MultiThreadedOperation {
const char *path,
const char *view_name,
bool save_as_render);
+ ~OutputSingleLayerOperation();
void execute_region(rcti *rect, unsigned int tile_number) override;
bool is_output_operation(bool /*rendering*/) const override
diff --git a/source/blender/compositor/operations/COM_ViewerOperation.cc b/source/blender/compositor/operations/COM_ViewerOperation.cc
index bc7e08ee98a..58392b8a638 100644
--- a/source/blender/compositor/operations/COM_ViewerOperation.cc
+++ b/source/blender/compositor/operations/COM_ViewerOperation.cc
@@ -202,7 +202,7 @@ void ViewerOperation::update_image(const rcti *rect)
rect->ymax);
/* This could be improved to use partial updates. For now disabled as the full frame compositor
- * would not use partial frames anymore and the image engine requires more testing.*/
+ * would not use partial frames anymore and the image engine requires more testing. */
BKE_image_partial_update_mark_full_update(image_);
this->update_draw();
}
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc
index 76bfd216c03..4782f1c4a5d 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc
@@ -1085,7 +1085,7 @@ void DepsgraphNodeBuilder::build_animation_images(ID *id)
* tree. */
const bool can_have_gpu_material = ELEM(GS(id->name), ID_MA, ID_WO);
- if (BKE_image_user_id_has_animation(id) || can_have_gpu_material) {
+ if (can_have_gpu_material || BKE_image_user_id_has_animation(id)) {
ID *id_cow = get_cow_id(id);
add_operation_node(
id,
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc
index 163ed1607e9..b5945c06ad3 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc
@@ -1423,7 +1423,7 @@ void DepsgraphRelationBuilder::build_animation_images(ID *id)
const bool can_have_gpu_material = ELEM(GS(id->name), ID_MA, ID_WO);
/* TODO: can we check for existence of node for performance? */
- if (BKE_image_user_id_has_animation(id) || can_have_gpu_material) {
+ if (can_have_gpu_material || BKE_image_user_id_has_animation(id)) {
OperationKey image_animation_key(
id, NodeType::IMAGE_ANIMATION, OperationCode::IMAGE_ANIMATION);
TimeSourceKey time_src_key;
@@ -1839,9 +1839,8 @@ void DepsgraphRelationBuilder::build_rigidbody(Scene *scene)
/* We do not have to update the objects final transform after the simulation if it is
* passive or controlled by the animation system in blender.
* (Bullet doesn't move the object at all in these cases).
- * But we can't update the depgraph when the animated property in changed during playback.
- * So always assume that active bodies needs updating.
- */
+ * But we can't update the depsgraph when the animated property in changed during playback.
+ * So always assume that active bodies needs updating. */
OperationKey rb_transform_copy_key(
&object->id, NodeType::TRANSFORM, OperationCode::RIGIDBODY_TRANSFORM_COPY);
/* Rigid body synchronization depends on the actual simulation. */
@@ -2089,7 +2088,7 @@ void DepsgraphRelationBuilder::build_object_data_geometry(Object *object)
ctx.node = reinterpret_cast<::DepsNodeHandle *>(&handle);
mti->updateDepsgraph(md, &ctx);
}
- if (BKE_object_modifier_use_time(scene_, object, md, graph_->mode)) {
+ if (BKE_object_modifier_use_time(scene_, object, md)) {
TimeSourceKey time_src_key;
add_relation(time_src_key, obdata_ubereval_key, "Time Source");
}
diff --git a/source/blender/depsgraph/intern/depsgraph_query_iter.cc b/source/blender/depsgraph/intern/depsgraph_query_iter.cc
index d5566e4be98..bcde1839a0f 100644
--- a/source/blender/depsgraph/intern/depsgraph_query_iter.cc
+++ b/source/blender/depsgraph/intern/depsgraph_query_iter.cc
@@ -54,7 +54,7 @@ void deg_invalidate_iterator_work_data(DEGObjectIterData *data)
{
#ifdef INVALIDATE_WORK_DATA
BLI_assert(data != nullptr);
- memset(&data->temp_dupli_object, 0xff, sizeof(data->temp_dupli_object));
+ memset((void *)&data->temp_dupli_object, 0xff, sizeof(data->temp_dupli_object));
#else
(void)data;
#endif
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 19022d534b2..91170abed0b 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
@@ -886,7 +886,7 @@ ID *deg_update_copy_on_write_datablock(const Depsgraph *depsgraph, const IDNode
return id_cow;
}
/* In case we don't need to do a copy-on-write, we can use the update cache of the grease
- * pencil data to do an update-on-write.*/
+ * pencil data to do an update-on-write. */
if (id_type == ID_GD && BKE_gpencil_can_avoid_full_copy_on_write(
(const ::Depsgraph *)depsgraph, (bGPdata *)id_orig)) {
BKE_gpencil_update_on_write((bGPdata *)id_orig, (bGPdata *)id_cow);
diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt
index 38ae9e86585..be7d24fb007 100644
--- a/source/blender/draw/CMakeLists.txt
+++ b/source/blender/draw/CMakeLists.txt
@@ -190,6 +190,7 @@ set(SRC
intern/draw_cache_inline.h
intern/draw_color_management.h
intern/draw_common.h
+ intern/draw_common_shader_shared.h
intern/draw_debug.h
intern/draw_hair_private.h
intern/draw_instance_data.h
@@ -392,6 +393,7 @@ set(GLSL_SRC
intern/shaders/common_subdiv_vbo_sculpt_data_comp.glsl
intern/draw_shader_shared.h
+ intern/draw_common_shader_shared.h
engines/gpencil/shaders/gpencil_frag.glsl
engines/gpencil/shaders/gpencil_vert.glsl
diff --git a/source/blender/draw/engines/eevee/eevee_effects.c b/source/blender/draw/engines/eevee/eevee_effects.c
index 78b9b68bb01..5fa719facf4 100644
--- a/source/blender/draw/engines/eevee/eevee_effects.c
+++ b/source/blender/draw/engines/eevee/eevee_effects.c
@@ -108,7 +108,7 @@ void EEVEE_effects_init(EEVEE_ViewLayerData *sldata,
* MinMax Pyramid
*/
- if (GPU_type_matches(GPU_DEVICE_INTEL, GPU_OS_ANY, GPU_DRIVER_ANY)) {
+ if (GPU_type_matches_ex(GPU_DEVICE_INTEL, GPU_OS_ANY, GPU_DRIVER_ANY, GPU_BACKEND_OPENGL)) {
/* Intel gpu seems to have problem rendering to only depth hiz_format */
DRW_texture_ensure_2d(&txl->maxzbuffer, UNPACK2(effects->hiz_size), GPU_R32F, DRW_TEX_MIPMAP);
GPU_framebuffer_ensure_config(&fbl->maxzbuffer_fb,
@@ -230,7 +230,7 @@ void EEVEE_effects_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
/* Intel gpu seems to have problem rendering to only depth format.
* Use color texture instead. */
- if (GPU_type_matches(GPU_DEVICE_INTEL, GPU_OS_ANY, GPU_DRIVER_ANY)) {
+ if (GPU_type_matches_ex(GPU_DEVICE_INTEL, GPU_OS_ANY, GPU_DRIVER_ANY, GPU_BACKEND_OPENGL)) {
downsample_write = DRW_STATE_WRITE_COLOR;
}
diff --git a/source/blender/draw/engines/eevee/eevee_lightprobes.c b/source/blender/draw/engines/eevee/eevee_lightprobes.c
index 7029d015b22..219c44de9dc 100644
--- a/source/blender/draw/engines/eevee/eevee_lightprobes.c
+++ b/source/blender/draw/engines/eevee/eevee_lightprobes.c
@@ -204,7 +204,7 @@ void EEVEE_lightbake_cache_init(EEVEE_ViewLayerData *sldata,
DRW_shgroup_uniform_float(grp, "intensityFac", &pinfo->intensity_fac, 1);
DRW_shgroup_uniform_float(grp, "sampleCount", &pinfo->samples_len, 1);
- DRW_shgroup_uniform_float(grp, "roughness", &pinfo->roughness, 1);
+ DRW_shgroup_uniform_float(grp, "probe_roughness", &pinfo->roughness, 1);
DRW_shgroup_uniform_float(grp, "lodFactor", &pinfo->lodfactor, 1);
DRW_shgroup_uniform_float(grp, "lodMax", &pinfo->lod_rt_max, 1);
DRW_shgroup_uniform_float(grp, "texelSize", &pinfo->texel_size, 1);
diff --git a/source/blender/draw/engines/eevee/eevee_occlusion.c b/source/blender/draw/engines/eevee/eevee_occlusion.c
index e148ac53cd4..d896c4e9331 100644
--- a/source/blender/draw/engines/eevee/eevee_occlusion.c
+++ b/source/blender/draw/engines/eevee/eevee_occlusion.c
@@ -200,7 +200,8 @@ void EEVEE_occlusion_compute(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
}
if (GPU_mip_render_workaround() ||
- GPU_type_matches(GPU_DEVICE_INTEL_UHD, GPU_OS_WIN, GPU_DRIVER_ANY)) {
+ GPU_type_matches_ex(
+ GPU_DEVICE_INTEL_UHD, GPU_OS_WIN, GPU_DRIVER_ANY, GPU_BACKEND_OPENGL)) {
/* Fix dot corruption on intel HD5XX/HD6XX series. */
GPU_flush();
}
diff --git a/source/blender/draw/engines/eevee/eevee_shadows.c b/source/blender/draw/engines/eevee/eevee_shadows.c
index 29d98f6795d..9e571b1d15b 100644
--- a/source/blender/draw/engines/eevee/eevee_shadows.c
+++ b/source/blender/draw/engines/eevee/eevee_shadows.c
@@ -147,7 +147,7 @@ void EEVEE_shadows_caster_register(EEVEE_ViewLayerData *sldata, Object *ob)
}
/* Update World AABB in frontbuffer. */
- BoundBox *bb = BKE_object_boundbox_get(ob);
+ const BoundBox *bb = BKE_object_boundbox_get(ob);
float min[3], max[3];
INIT_MINMAX(min, max);
for (int i = 0; i < 8; i++) {
diff --git a/source/blender/draw/engines/eevee/eevee_shadows_cascade.c b/source/blender/draw/engines/eevee/eevee_shadows_cascade.c
index 25939926cfa..536242f67d8 100644
--- a/source/blender/draw/engines/eevee/eevee_shadows_cascade.c
+++ b/source/blender/draw/engines/eevee/eevee_shadows_cascade.c
@@ -311,7 +311,7 @@ static void eevee_shadow_cascade_setup(EEVEE_LightsInfo *linfo,
if (c < 3) {
dbg_col[c] = 1.0f;
}
- DRW_debug_bbox((BoundBox *)&corners, dbg_col);
+ DRW_debug_bbox((const BoundBox *)&corners, dbg_col);
DRW_debug_sphere(center, csm_render->radius[c], dbg_col);
#endif
diff --git a/source/blender/draw/engines/eevee/eevee_volumes.c b/source/blender/draw/engines/eevee/eevee_volumes.c
index 6ef58c90e7a..7d210f15d8b 100644
--- a/source/blender/draw/engines/eevee/eevee_volumes.c
+++ b/source/blender/draw/engines/eevee/eevee_volumes.c
@@ -346,7 +346,7 @@ static bool eevee_volume_object_grids_init(Object *ob, ListBase *gpu_grids, DRWS
if (multiple_transforms) {
/* For multiple grids with different transform, we first transform from object space
* to bounds, then for each individual grid from bounds to texture. */
- BoundBox *bb = BKE_volume_boundbox_get(ob);
+ const BoundBox *bb = BKE_volume_boundbox_get(ob);
float bb_size[3];
sub_v3_v3v3(bb_size, bb->vec[6], bb->vec[0]);
size_to_mat4(bounds_to_object, bb_size);
diff --git a/source/blender/draw/engines/eevee/shaders/effect_mist_frag.glsl b/source/blender/draw/engines/eevee/shaders/effect_mist_frag.glsl
index 7331f92ba6d..94b881b44f1 100644
--- a/source/blender/draw/engines/eevee/shaders/effect_mist_frag.glsl
+++ b/source/blender/draw/engines/eevee/shaders/effect_mist_frag.glsl
@@ -4,7 +4,7 @@
/* Convert depth to Mist factor */
uniform vec3 mistSettings;
-uniform sampler2D depthBuffer;
+uniform depth2D depthBuffer;
#define mistStart mistSettings.x
#define mistInvDistance mistSettings.y
diff --git a/source/blender/draw/engines/eevee/shaders/effect_motion_blur_frag.glsl b/source/blender/draw/engines/eevee/shaders/effect_motion_blur_frag.glsl
index 0aa54715460..4f87cdf05d2 100644
--- a/source/blender/draw/engines/eevee/shaders/effect_motion_blur_frag.glsl
+++ b/source/blender/draw/engines/eevee/shaders/effect_motion_blur_frag.glsl
@@ -11,7 +11,7 @@
* by Jorge Jimenez
*/
uniform sampler2D colorBuffer;
-uniform sampler2D depthBuffer;
+uniform depth2D depthBuffer;
uniform sampler2D velocityBuffer;
uniform sampler2D tileMaxBuffer;
diff --git a/source/blender/draw/engines/eevee/shaders/effect_subsurface_frag.glsl b/source/blender/draw/engines/eevee/shaders/effect_subsurface_frag.glsl
index 58bbb825043..1aff93e01f8 100644
--- a/source/blender/draw/engines/eevee/shaders/effect_subsurface_frag.glsl
+++ b/source/blender/draw/engines/eevee/shaders/effect_subsurface_frag.glsl
@@ -9,7 +9,7 @@
#define MAX_SSS_SAMPLES 65
layout(std140) uniform sssProfile
{
- vec4 kernel[MAX_SSS_SAMPLES];
+ vec4 sss_kernel[MAX_SSS_SAMPLES];
vec4 radii_max_radius;
int sss_samples;
};
@@ -48,11 +48,11 @@ void main(void)
float sss_radius_inv = 1.0 / max(1e-8, sss_radius);
/* Center sample */
- vec3 accum = sss_irradiance * kernel[0].rgb;
+ vec3 accum = sss_irradiance * sss_kernel[0].rgb;
for (int i = 1; i < sss_samples && i < MAX_SSS_SAMPLES; i++) {
- vec2 sample_uv = uvs + kernel[i].a * finalStep *
- ((abs(kernel[i].a) > sssJitterThreshold) ? dir : dir_rand);
+ vec2 sample_uv = uvs + sss_kernel[i].a * finalStep *
+ ((abs(sss_kernel[i].a) > sssJitterThreshold) ? dir : dir_rand);
vec3 color = texture(sssIrradiance, sample_uv).rgb;
float sample_depth = texture(depthBuffer, sample_uv).r;
sample_depth = get_view_z_from_depth(sample_depth);
@@ -66,8 +66,8 @@ void main(void)
if (any(lessThan(sample_uv, vec2(0.0))) || any(greaterThan(sample_uv, vec2(1.0)))) {
s = 0.0;
}
- /* Mix with first sample in failure case and apply kernel color. */
- accum += kernel[i].rgb * mix(sss_irradiance, color, s);
+ /* Mix with first sample in failure case and apply sss_kernel color. */
+ accum += sss_kernel[i].rgb * mix(sss_irradiance, color, s);
}
#if defined(FIRST_PASS)
diff --git a/source/blender/draw/engines/eevee/shaders/effect_temporal_aa.glsl b/source/blender/draw/engines/eevee/shaders/effect_temporal_aa.glsl
index c54621f123d..b4ae8bd4405 100644
--- a/source/blender/draw/engines/eevee/shaders/effect_temporal_aa.glsl
+++ b/source/blender/draw/engines/eevee/shaders/effect_temporal_aa.glsl
@@ -3,7 +3,7 @@
#pragma BLENDER_REQUIRE(common_view_lib.glsl)
uniform sampler2D colorBuffer;
-uniform sampler2D depthBuffer;
+uniform depth2D depthBuffer;
uniform sampler2D colorHistoryBuffer;
uniform mat4 prevViewProjectionMatrix;
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 831ed0a119a..3cf21dc32d1 100644
--- a/source/blender/draw/engines/eevee/shaders/effect_translucency_frag.glsl
+++ b/source/blender/draw/engines/eevee/shaders/effect_translucency_frag.glsl
@@ -8,7 +8,7 @@ in vec4 uvcoordsvar;
out vec4 FragColor;
-uniform sampler2D depthBuffer;
+uniform depth2D depthBuffer;
uniform sampler1D sssTexProfile;
uniform sampler2D sssRadius;
uniform sampler2DArray sssShadowCubes;
@@ -21,7 +21,7 @@ uniform sampler2DArray sssShadowCascades;
layout(std140) uniform sssProfile
{
- vec4 kernel[MAX_SSS_SAMPLES];
+ vec4 sss_kernel[MAX_SSS_SAMPLES];
vec4 radii_max_radius;
int sss_samples;
};
diff --git a/source/blender/draw/engines/eevee/shaders/effect_velocity_resolve_frag.glsl b/source/blender/draw/engines/eevee/shaders/effect_velocity_resolve_frag.glsl
index 9182171bab4..87854dd3be2 100644
--- a/source/blender/draw/engines/eevee/shaders/effect_velocity_resolve_frag.glsl
+++ b/source/blender/draw/engines/eevee/shaders/effect_velocity_resolve_frag.glsl
@@ -1,7 +1,7 @@
#pragma BLENDER_REQUIRE(common_math_lib.glsl)
-uniform sampler2D depthBuffer;
+uniform depth2D depthBuffer;
uniform mat4 prevViewProjMatrix;
uniform mat4 currViewProjMatrixInv;
diff --git a/source/blender/draw/engines/eevee/shaders/lightprobe_filter_glossy_frag.glsl b/source/blender/draw/engines/eevee/shaders/lightprobe_filter_glossy_frag.glsl
index a5d11f52a1d..af2982b30c0 100644
--- a/source/blender/draw/engines/eevee/shaders/lightprobe_filter_glossy_frag.glsl
+++ b/source/blender/draw/engines/eevee/shaders/lightprobe_filter_glossy_frag.glsl
@@ -4,7 +4,7 @@
#pragma BLENDER_REQUIRE(common_math_geom_lib.glsl)
uniform samplerCube probeHdr;
-uniform float roughness;
+uniform float probe_roughness;
uniform float texelSize;
uniform float lodFactor;
uniform float lodMax;
@@ -51,7 +51,7 @@ void main()
float pdf;
/* Microfacet normal */
- vec3 H = sample_ggx(Xi, roughness, V, N, T, B, pdf);
+ vec3 H = sample_ggx(Xi, probe_roughness, V, N, T, B, pdf);
vec3 L = -reflect(V, H);
float NL = dot(N, L);
diff --git a/source/blender/draw/engines/eevee/shaders/lights_lib.glsl b/source/blender/draw/engines/eevee/shaders/lights_lib.glsl
index dc98a00a1cd..3d43ef9addd 100644
--- a/source/blender/draw/engines/eevee/shaders/lights_lib.glsl
+++ b/source/blender/draw/engines/eevee/shaders/lights_lib.glsl
@@ -89,8 +89,8 @@ layout(std140) uniform light_block
LightData lights_data[MAX_LIGHT];
};
-uniform sampler2DArrayShadow shadowCubeTexture;
-uniform sampler2DArrayShadow shadowCascadeTexture;
+uniform depth2DArrayShadow shadowCubeTexture;
+uniform depth2DArrayShadow shadowCascadeTexture;
/** \} */
diff --git a/source/blender/draw/engines/eevee/shaders/renderpass_postprocess_frag.glsl b/source/blender/draw/engines/eevee/shaders/renderpass_postprocess_frag.glsl
index 363b5cb978a..64ba8d44d39 100644
--- a/source/blender/draw/engines/eevee/shaders/renderpass_postprocess_frag.glsl
+++ b/source/blender/draw/engines/eevee/shaders/renderpass_postprocess_frag.glsl
@@ -16,7 +16,7 @@
uniform int postProcessType;
uniform int currentSample;
-uniform sampler2D depthBuffer;
+uniform depth2D depthBuffer;
uniform sampler2D inputBuffer;
uniform sampler2D inputSecondLightBuffer;
uniform sampler2D inputColorBuffer;
diff --git a/source/blender/draw/engines/eevee/shaders/shadow_accum_frag.glsl b/source/blender/draw/engines/eevee/shaders/shadow_accum_frag.glsl
index ad0d682dcf4..2a7d7e38504 100644
--- a/source/blender/draw/engines/eevee/shaders/shadow_accum_frag.glsl
+++ b/source/blender/draw/engines/eevee/shaders/shadow_accum_frag.glsl
@@ -3,7 +3,7 @@
#pragma BLENDER_REQUIRE(common_utiltex_lib.glsl)
#pragma BLENDER_REQUIRE(lights_lib.glsl)
-uniform sampler2D depthBuffer;
+uniform depth2D depthBuffer;
out vec4 fragColor;
diff --git a/source/blender/draw/engines/gpencil/gpencil_cache_utils.c b/source/blender/draw/engines/gpencil/gpencil_cache_utils.c
index be35660a4d7..40ebd262df5 100644
--- a/source/blender/draw/engines/gpencil/gpencil_cache_utils.c
+++ b/source/blender/draw/engines/gpencil/gpencil_cache_utils.c
@@ -60,7 +60,7 @@ GPENCIL_tObject *gpencil_object_cache_add(GPENCIL_PrivateData *pd, Object *ob)
* strokes not aligned with the object axes. Maybe we could try to
* compute the minimum axis of all strokes. But this would be more
* computationally heavy and should go into the GPData evaluation. */
- BoundBox *bbox = BKE_object_boundbox_get(ob);
+ const BoundBox *bbox = BKE_object_boundbox_get(ob);
/* Convert bbox to matrix */
float mat[4][4], size[3], center[3];
BKE_boundbox_calc_size_aabb(bbox, size);
diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_vert.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_vert.glsl
index c0ff8d945f2..af8aec85598 100644
--- a/source/blender/draw/engines/gpencil/shaders/gpencil_vert.glsl
+++ b/source/blender/draw/engines/gpencil/shaders/gpencil_vert.glsl
@@ -61,7 +61,9 @@ void main()
gp_interp.hardness);
if (GPENCIL_IS_STROKE_VERTEX) {
- gp_interp.uv.x *= gp_mat._stroke_u_scale;
+ if (!flag_test(gp_flag, GP_STROKE_ALIGNMENT)) {
+ gp_interp.uv.x *= gp_mat._stroke_u_scale;
+ }
/* Special case: We don't use vertex color if material Holdout. */
if (flag_test(gp_flag, GP_STROKE_HOLDOUT)) {
diff --git a/source/blender/draw/engines/image/image_drawing_mode.hh b/source/blender/draw/engines/image/image_drawing_mode.hh
index f43bbadfa91..14529797405 100644
--- a/source/blender/draw/engines/image/image_drawing_mode.hh
+++ b/source/blender/draw/engines/image/image_drawing_mode.hh
@@ -58,7 +58,7 @@ struct OneTextureMethod {
{
/* Although this works, computing an inverted matrix adds some precision issues and leads to
* tearing artifacts. This should be modified to use the scaling and transformation from the
- * not inverted matrix.*/
+ * not inverted matrix. */
float4x4 mat(instance_data->ss_to_texture);
float4x4 mat_inv = mat.inverted();
float3 min_uv = mat_inv * float3(0.0f, 0.0f, 0.0f);
@@ -420,7 +420,7 @@ template<typename TextureMethod> class ScreenSpaceDrawingMode : public AbstractD
/* IMB_transform works in a non-consistent space. This should be documented or fixed!.
* Construct a variant of the info_uv_to_texture that adds the texel space
- * transformation.*/
+ * transformation. */
float uv_to_texel[4][4];
copy_m4_m4(uv_to_texel, instance_data.ss_to_texture);
float scale[3] = {static_cast<float>(texture_width) / static_cast<float>(tile_buffer.x),
diff --git a/source/blender/draw/engines/image/image_usage.hh b/source/blender/draw/engines/image/image_usage.hh
index bea5c3853b0..f4ba3f495ce 100644
--- a/source/blender/draw/engines/image/image_usage.hh
+++ b/source/blender/draw/engines/image/image_usage.hh
@@ -14,7 +14,7 @@
struct ImageUsage {
/** Render pass of the image that is used. */
short pass = 0;
- /** Layer of the image that is used.*/
+ /** Layer of the image that is used. */
short layer = 0;
/** View of the image that is used. */
short view = 0;
diff --git a/source/blender/draw/engines/overlay/overlay_edit_mesh.c b/source/blender/draw/engines/overlay/overlay_edit_mesh.c
index e605a3be375..e0671eac156 100644
--- a/source/blender/draw/engines/overlay/overlay_edit_mesh.c
+++ b/source/blender/draw/engines/overlay/overlay_edit_mesh.c
@@ -138,6 +138,7 @@ void OVERLAY_edit_mesh_cache_init(OVERLAY_Data *vedata)
GPUShader *edge_sh = OVERLAY_shader_edit_mesh_edge(!select_vert);
GPUShader *face_sh = OVERLAY_shader_edit_mesh_face();
const bool do_zbufclip = (i == 0 && pd->edit_mesh.do_zbufclip);
+ const bool do_smooth_wire = (U.gpu_flag & USER_GPU_FLAG_NO_EDIT_MODE_SMOOTH_WIRE) == 0;
DRWState state_common = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_LESS_EQUAL |
DRW_STATE_BLEND_ALPHA;
/* Faces */
@@ -173,17 +174,21 @@ void OVERLAY_edit_mesh_cache_init(OVERLAY_Data *vedata)
DRW_shgroup_uniform_float_copy(grp, "alpha", backwire_opacity);
DRW_shgroup_uniform_texture_ref(grp, "depthTex", depth_tex);
DRW_shgroup_uniform_bool_copy(grp, "selectEdges", pd->edit_mesh.do_edges || select_edge);
+ DRW_shgroup_uniform_bool_copy(grp, "do_smooth_wire", do_smooth_wire);
/* Verts */
state |= DRW_STATE_WRITE_DEPTH;
DRW_PASS_CREATE(psl->edit_mesh_verts_ps[i], state | pd->clipping_state);
if (select_vert) {
+ int vert_mask[4] = {0xFF, 0xFF, 0xFF, 0xFF};
+
sh = OVERLAY_shader_edit_mesh_vert();
grp = pd->edit_mesh_verts_grp[i] = DRW_shgroup_create(sh, psl->edit_mesh_verts_ps[i]);
DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
DRW_shgroup_uniform_float_copy(grp, "alpha", backwire_opacity);
DRW_shgroup_uniform_texture_ref(grp, "depthTex", depth_tex);
+ DRW_shgroup_uniform_ivec4_copy(grp, "dataMask", vert_mask);
sh = OVERLAY_shader_edit_mesh_skin_root();
grp = pd->edit_mesh_skin_roots_grp[i] = DRW_shgroup_create(sh, psl->edit_mesh_verts_ps[i]);
diff --git a/source/blender/draw/engines/overlay/overlay_extra.c b/source/blender/draw/engines/overlay/overlay_extra.c
index aae12e5513e..4f0bf0b8048 100644
--- a/source/blender/draw/engines/overlay/overlay_extra.c
+++ b/source/blender/draw/engines/overlay/overlay_extra.c
@@ -345,18 +345,17 @@ static void OVERLAY_bounds(OVERLAY_ExtraCallBuffers *cb,
bool around_origin)
{
float center[3], size[3], tmp[4][4], final_mat[4][4];
- BoundBox bb_local;
if (ob->type == OB_MBALL && !BKE_mball_is_basis(ob)) {
return;
}
- BoundBox *bb = BKE_object_boundbox_get(ob);
-
+ const BoundBox *bb = BKE_object_boundbox_get(ob);
+ BoundBox bb_local;
if (bb == NULL) {
const float min[3] = {-1.0f, -1.0f, -1.0f}, max[3] = {1.0f, 1.0f, 1.0f};
+ BKE_boundbox_init_from_minmax(&bb_local, min, max);
bb = &bb_local;
- BKE_boundbox_init_from_minmax(bb, min, max);
}
BKE_boundbox_calc_size_aabb(bb, size);
@@ -756,7 +755,7 @@ void OVERLAY_lightprobe_cache_populate(OVERLAY_Data *vedata, Object *ob)
uint cell_count = prb->grid_resolution_x * prb->grid_resolution_y * prb->grid_resolution_z;
DRWShadingGroup *grp = DRW_shgroup_create_sub(vedata->stl->pd->extra_grid_grp);
- DRW_shgroup_uniform_vec4_array_copy(grp, "gridModelMatrix", instdata.mat, 4);
+ DRW_shgroup_uniform_mat4_copy(grp, "gridModelMatrix", instdata.mat);
DRW_shgroup_call_procedural_points(grp, NULL, cell_count);
}
break;
diff --git a/source/blender/draw/engines/overlay/overlay_outline.c b/source/blender/draw/engines/overlay/overlay_outline.c
index cb94008f53f..8010319e3fa 100644
--- a/source/blender/draw/engines/overlay/overlay_outline.c
+++ b/source/blender/draw/engines/overlay/overlay_outline.c
@@ -32,7 +32,7 @@ static void gpencil_depth_plane(Object *ob, float r_plane[4])
* strokes not aligned with the object axes. Maybe we could try to
* compute the minimum axis of all strokes. But this would be more
* computationally heavy and should go into the GPData evaluation. */
- BoundBox *bbox = BKE_object_boundbox_get(ob);
+ const BoundBox *bbox = BKE_object_boundbox_get(ob);
/* Convert bbox to matrix */
float mat[4][4], size[3], center[3];
BKE_boundbox_calc_size_aabb(bbox, size);
diff --git a/source/blender/draw/engines/overlay/overlay_shader.c b/source/blender/draw/engines/overlay/overlay_shader.c
index 639b20feae4..278aefb8fec 100644
--- a/source/blender/draw/engines/overlay/overlay_shader.c
+++ b/source/blender/draw/engines/overlay/overlay_shader.c
@@ -299,21 +299,10 @@ GPUShader *OVERLAY_shader_depth_only(void)
GPUShader *OVERLAY_shader_edit_mesh_vert(void)
{
const DRWContextState *draw_ctx = DRW_context_state_get();
- const GPUShaderConfigData *sh_cfg = &GPU_shader_cfg_data[draw_ctx->sh_cfg];
OVERLAY_Shaders *sh_data = &e_data.sh_data[draw_ctx->sh_cfg];
if (!sh_data->edit_mesh_vert) {
- sh_data->edit_mesh_vert = GPU_shader_create_from_arrays({
- .vert = (const char *[]){sh_cfg->lib,
- datatoc_common_globals_lib_glsl,
- datatoc_common_view_lib_glsl,
- datatoc_edit_mesh_common_lib_glsl,
- datatoc_edit_mesh_vert_glsl,
- NULL},
- .frag = (const char *[]){datatoc_common_globals_lib_glsl,
- datatoc_gpu_shader_point_varying_color_frag_glsl,
- NULL},
- .defs = (const char *[]){sh_cfg->def, "#define VERT\n", NULL},
- });
+ sh_data->edit_mesh_vert = GPU_shader_create_from_info_name(
+ draw_ctx->sh_cfg ? "overlay_edit_mesh_vert_clipped" : "overlay_edit_mesh_vert");
}
return sh_data->edit_mesh_vert;
}
@@ -321,47 +310,14 @@ GPUShader *OVERLAY_shader_edit_mesh_vert(void)
GPUShader *OVERLAY_shader_edit_mesh_edge(bool use_flat_interp)
{
const DRWContextState *draw_ctx = DRW_context_state_get();
- const GPUShaderConfigData *sh_cfg = &GPU_shader_cfg_data[draw_ctx->sh_cfg];
OVERLAY_Shaders *sh_data = &e_data.sh_data[draw_ctx->sh_cfg];
GPUShader **sh = use_flat_interp ? &sh_data->edit_mesh_edge_flat : &sh_data->edit_mesh_edge;
if (*sh == NULL) {
- /* Use geometry shader to draw edge wire-frame. This ensure us
- * the same result across platforms and more flexibility.
- * But we pay the cost of running a geometry shader.
- * In the future we might consider using only the vertex shader
- * and loading data manually with buffer textures. */
- const bool use_geom_shader = true;
- const bool use_smooth_wires = (U.gpu_flag & USER_GPU_FLAG_NO_EDIT_MODE_SMOOTH_WIRE) == 0;
- const char *geom_sh_code[] = {use_geom_shader ? sh_cfg->lib : NULL,
- datatoc_common_globals_lib_glsl,
- datatoc_common_view_lib_glsl,
- datatoc_edit_mesh_geom_glsl,
- NULL};
- const char *vert_sh_code[] = {sh_cfg->lib,
- datatoc_common_globals_lib_glsl,
- datatoc_common_view_lib_glsl,
- datatoc_edit_mesh_common_lib_glsl,
- datatoc_edit_mesh_vert_glsl,
- NULL};
- const char *frag_sh_code[] = {sh_cfg->lib,
- datatoc_common_globals_lib_glsl,
- datatoc_common_view_lib_glsl,
- datatoc_edit_mesh_common_lib_glsl,
- datatoc_edit_mesh_frag_glsl,
- NULL};
- const char *defs[] = {sh_cfg->def,
- use_geom_shader ? "#define USE_GEOM_SHADER\n" : "",
- use_smooth_wires ? "#define USE_SMOOTH_WIRE\n" : "",
- use_flat_interp ? "#define FLAT\n" : "",
- "#define EDGE\n",
- NULL};
-
- *sh = GPU_shader_create_from_arrays({
- .vert = vert_sh_code,
- .frag = frag_sh_code,
- .geom = geom_sh_code,
- .defs = defs,
- });
+ *sh = GPU_shader_create_from_info_name(
+ draw_ctx->sh_cfg ?
+ (use_flat_interp ? "overlay_edit_mesh_edge_flat_clipped" :
+ "overlay_edit_mesh_edge_clipped") :
+ (use_flat_interp ? "overlay_edit_mesh_edge_flat" : "overlay_edit_mesh_edge"));
}
return *sh;
}
@@ -369,35 +325,16 @@ GPUShader *OVERLAY_shader_edit_mesh_edge(bool use_flat_interp)
GPUShader *OVERLAY_shader_armature_sphere(bool use_outline)
{
const DRWContextState *draw_ctx = DRW_context_state_get();
- const GPUShaderConfigData *sh_cfg = &GPU_shader_cfg_data[draw_ctx->sh_cfg];
OVERLAY_Shaders *sh_data = &e_data.sh_data[draw_ctx->sh_cfg];
- const char extensions[] = "";
if (use_outline && !sh_data->armature_sphere_outline) {
- sh_data->armature_sphere_outline = GPU_shader_create_from_arrays({
- .vert = (const char *[]){sh_cfg->lib,
- datatoc_common_globals_lib_glsl,
- datatoc_common_view_lib_glsl,
- datatoc_armature_sphere_outline_vert_glsl,
- NULL},
- .frag = (const char *[]){extensions,
- datatoc_common_view_lib_glsl,
- datatoc_armature_wire_frag_glsl,
- NULL},
- .defs = (const char *[]){sh_cfg->def, NULL},
- });
+ sh_data->armature_sphere_outline = GPU_shader_create_from_info_name(
+ draw_ctx->sh_cfg ? "overlay_armature_sphere_outline_clipped" :
+ "overlay_armature_sphere_outline");
}
else if (!sh_data->armature_sphere_solid) {
- sh_data->armature_sphere_solid = GPU_shader_create_from_arrays({
- .vert = (const char *[]){sh_cfg->lib,
- datatoc_common_view_lib_glsl,
- datatoc_armature_sphere_solid_vert_glsl,
- NULL},
- .frag = (const char *[]){extensions,
- datatoc_common_view_lib_glsl,
- datatoc_armature_sphere_solid_frag_glsl,
- NULL},
- .defs = (const char *[]){sh_cfg->def, NULL},
- });
+ sh_data->armature_sphere_solid = GPU_shader_create_from_info_name(
+ draw_ctx->sh_cfg ? "overlay_armature_sphere_solid_clipped" :
+ "overlay_armature_sphere_solid");
}
return use_outline ? sh_data->armature_sphere_outline : sh_data->armature_sphere_solid;
}
@@ -405,34 +342,16 @@ GPUShader *OVERLAY_shader_armature_sphere(bool use_outline)
GPUShader *OVERLAY_shader_armature_shape(bool use_outline)
{
const DRWContextState *draw_ctx = DRW_context_state_get();
- const GPUShaderConfigData *sh_cfg = &GPU_shader_cfg_data[draw_ctx->sh_cfg];
OVERLAY_Shaders *sh_data = &e_data.sh_data[draw_ctx->sh_cfg];
if (use_outline && !sh_data->armature_shape_outline) {
- sh_data->armature_shape_outline = GPU_shader_create_from_arrays({
- .vert = (const char *[]){sh_cfg->lib,
- datatoc_common_globals_lib_glsl,
- datatoc_common_view_lib_glsl,
- datatoc_armature_shape_outline_vert_glsl,
- NULL},
- .geom = (const char *[]){sh_cfg->lib,
- datatoc_common_globals_lib_glsl,
- datatoc_common_view_lib_glsl,
- datatoc_armature_shape_outline_geom_glsl,
- NULL},
- .frag =
- (const char *[]){datatoc_common_view_lib_glsl, datatoc_armature_wire_frag_glsl, NULL},
- .defs = (const char *[]){sh_cfg->def, NULL},
- });
+ sh_data->armature_shape_outline = GPU_shader_create_from_info_name(
+ draw_ctx->sh_cfg ? "overlay_armature_shape_outline_clipped" :
+ "overlay_armature_shape_outline");
}
else if (!sh_data->armature_shape_solid) {
- sh_data->armature_shape_solid = GPU_shader_create_from_arrays({
- .vert = (const char *[]){sh_cfg->lib,
- datatoc_common_view_lib_glsl,
- datatoc_armature_shape_solid_vert_glsl,
- NULL},
- .frag = (const char *[]){datatoc_armature_shape_solid_frag_glsl, NULL},
- .defs = (const char *[]){sh_cfg->def, NULL},
- });
+ sh_data->armature_shape_solid = GPU_shader_create_from_info_name(
+ draw_ctx->sh_cfg ? "overlay_armature_shape_solid_clipped" :
+ "overlay_armature_shape_solid");
}
return use_outline ? sh_data->armature_shape_outline : sh_data->armature_shape_solid;
}
@@ -440,19 +359,10 @@ GPUShader *OVERLAY_shader_armature_shape(bool use_outline)
GPUShader *OVERLAY_shader_armature_shape_wire(void)
{
const DRWContextState *draw_ctx = DRW_context_state_get();
- const GPUShaderConfigData *sh_cfg = &GPU_shader_cfg_data[draw_ctx->sh_cfg];
OVERLAY_Shaders *sh_data = &e_data.sh_data[draw_ctx->sh_cfg];
if (!sh_data->armature_shape_wire) {
- sh_data->armature_shape_wire = GPU_shader_create_from_arrays({
- .vert = (const char *[]){sh_cfg->lib,
- datatoc_common_globals_lib_glsl,
- datatoc_common_view_lib_glsl,
- datatoc_armature_shape_wire_vert_glsl,
- NULL},
- .frag =
- (const char *[]){datatoc_common_view_lib_glsl, datatoc_armature_wire_frag_glsl, NULL},
- .defs = (const char *[]){sh_cfg->def, NULL},
- });
+ sh_data->armature_shape_wire = GPU_shader_create_from_info_name(
+ draw_ctx->sh_cfg ? "overlay_armature_shape_wire_clipped" : "overlay_armature_shape_wire");
}
return sh_data->armature_shape_wire;
}
@@ -460,29 +370,16 @@ GPUShader *OVERLAY_shader_armature_shape_wire(void)
GPUShader *OVERLAY_shader_armature_envelope(bool use_outline)
{
const DRWContextState *draw_ctx = DRW_context_state_get();
- const GPUShaderConfigData *sh_cfg = &GPU_shader_cfg_data[draw_ctx->sh_cfg];
OVERLAY_Shaders *sh_data = &e_data.sh_data[draw_ctx->sh_cfg];
if (use_outline && !sh_data->armature_envelope_outline) {
- sh_data->armature_envelope_outline = GPU_shader_create_from_arrays({
- .vert = (const char *[]){sh_cfg->lib,
- datatoc_common_globals_lib_glsl,
- datatoc_common_view_lib_glsl,
- datatoc_armature_envelope_outline_vert_glsl,
- NULL},
- .frag =
- (const char *[]){datatoc_common_view_lib_glsl, datatoc_armature_wire_frag_glsl, NULL},
- .defs = (const char *[]){sh_cfg->def, NULL},
- });
+ sh_data->armature_envelope_outline = GPU_shader_create_from_info_name(
+ draw_ctx->sh_cfg ? "overlay_armature_envelope_outline_clipped" :
+ "overlay_armature_envelope_outline");
}
else if (!sh_data->armature_envelope_solid) {
- sh_data->armature_envelope_solid = GPU_shader_create_from_arrays({
- .vert = (const char *[]){sh_cfg->lib,
- datatoc_common_view_lib_glsl,
- datatoc_armature_envelope_solid_vert_glsl,
- NULL},
- .frag = (const char *[]){datatoc_armature_envelope_solid_frag_glsl, NULL},
- .defs = (const char *[]){sh_cfg->def, NULL},
- });
+ sh_data->armature_envelope_solid = GPU_shader_create_from_info_name(
+ draw_ctx->sh_cfg ? "overlay_armature_envelope_solid_clipped" :
+ "overlay_armature_envelope_solid");
}
return use_outline ? sh_data->armature_envelope_outline : sh_data->armature_envelope_solid;
}
@@ -490,18 +387,10 @@ GPUShader *OVERLAY_shader_armature_envelope(bool use_outline)
GPUShader *OVERLAY_shader_armature_stick(void)
{
const DRWContextState *draw_ctx = DRW_context_state_get();
- const GPUShaderConfigData *sh_cfg = &GPU_shader_cfg_data[draw_ctx->sh_cfg];
OVERLAY_Shaders *sh_data = &e_data.sh_data[draw_ctx->sh_cfg];
if (!sh_data->armature_stick) {
- sh_data->armature_stick = GPU_shader_create_from_arrays({
- .vert = (const char *[]){sh_cfg->lib,
- datatoc_common_globals_lib_glsl,
- datatoc_common_view_lib_glsl,
- datatoc_armature_stick_vert_glsl,
- NULL},
- .frag = (const char *[]){datatoc_armature_stick_frag_glsl, NULL},
- .defs = (const char *[]){sh_cfg->def, NULL},
- });
+ sh_data->armature_stick = GPU_shader_create_from_info_name(
+ draw_ctx->sh_cfg ? "overlay_armature_stick_clipped" : "overlay_armature_stick");
}
return sh_data->armature_stick;
}
@@ -509,19 +398,10 @@ GPUShader *OVERLAY_shader_armature_stick(void)
GPUShader *OVERLAY_shader_armature_degrees_of_freedom_wire(void)
{
const DRWContextState *draw_ctx = DRW_context_state_get();
- const GPUShaderConfigData *sh_cfg = &GPU_shader_cfg_data[draw_ctx->sh_cfg];
OVERLAY_Shaders *sh_data = &e_data.sh_data[draw_ctx->sh_cfg];
if (!sh_data->armature_dof_wire) {
- sh_data->armature_dof_wire = GPU_shader_create_from_arrays({
- .vert = (const char *[]){sh_cfg->lib,
- datatoc_common_globals_lib_glsl,
- datatoc_common_view_lib_glsl,
- datatoc_armature_dof_vert_glsl,
- NULL},
- .frag =
- (const char *[]){datatoc_common_view_lib_glsl, datatoc_armature_wire_frag_glsl, NULL},
- .defs = (const char *[]){sh_cfg->def, "#define EDGE\n", NULL},
- });
+ sh_data->armature_dof_wire = GPU_shader_create_from_info_name(
+ draw_ctx->sh_cfg ? "overlay_armature_dof_wire_clipped" : "overlay_armature_dof_wire");
}
return sh_data->armature_dof_wire;
}
@@ -529,20 +409,10 @@ GPUShader *OVERLAY_shader_armature_degrees_of_freedom_wire(void)
GPUShader *OVERLAY_shader_armature_degrees_of_freedom_solid(void)
{
const DRWContextState *draw_ctx = DRW_context_state_get();
- const GPUShaderConfigData *sh_cfg = &GPU_shader_cfg_data[draw_ctx->sh_cfg];
OVERLAY_Shaders *sh_data = &e_data.sh_data[draw_ctx->sh_cfg];
if (!sh_data->armature_dof_solid) {
- sh_data->armature_dof_solid = GPU_shader_create_from_arrays({
- .vert = (const char *[]){sh_cfg->lib,
- datatoc_common_globals_lib_glsl,
- datatoc_common_view_lib_glsl,
- datatoc_armature_dof_vert_glsl,
- NULL},
- .frag = (const char *[]){datatoc_common_view_lib_glsl,
- datatoc_armature_dof_solid_frag_glsl,
- NULL},
- .defs = (const char *[]){sh_cfg->def, NULL},
- });
+ sh_data->armature_dof_solid = GPU_shader_create_from_info_name(
+ draw_ctx->sh_cfg ? "overlay_armature_dof_solid_clipped" : "overlay_armature_dof_solid");
}
return sh_data->armature_dof_solid;
}
@@ -550,19 +420,10 @@ GPUShader *OVERLAY_shader_armature_degrees_of_freedom_solid(void)
GPUShader *OVERLAY_shader_armature_wire(void)
{
const DRWContextState *draw_ctx = DRW_context_state_get();
- const GPUShaderConfigData *sh_cfg = &GPU_shader_cfg_data[draw_ctx->sh_cfg];
OVERLAY_Shaders *sh_data = &e_data.sh_data[draw_ctx->sh_cfg];
if (!sh_data->armature_wire) {
- sh_data->armature_wire = GPU_shader_create_from_arrays({
- .vert = (const char *[]){sh_cfg->lib,
- datatoc_common_globals_lib_glsl,
- datatoc_common_view_lib_glsl,
- datatoc_armature_wire_vert_glsl,
- NULL},
- .frag =
- (const char *[]){datatoc_common_view_lib_glsl, datatoc_armature_wire_frag_glsl, NULL},
- .defs = (const char *[]){sh_cfg->def, NULL},
- });
+ sh_data->armature_wire = GPU_shader_create_from_info_name(
+ draw_ctx->sh_cfg ? "overlay_armature_wire_clipped" : "overlay_armature_wire");
}
return sh_data->armature_wire;
}
@@ -722,19 +583,10 @@ GPUShader *OVERLAY_shader_edit_lattice_wire(void)
GPUShader *OVERLAY_shader_edit_mesh_face(void)
{
const DRWContextState *draw_ctx = DRW_context_state_get();
- const GPUShaderConfigData *sh_cfg = &GPU_shader_cfg_data[draw_ctx->sh_cfg];
OVERLAY_Shaders *sh_data = &e_data.sh_data[draw_ctx->sh_cfg];
if (!sh_data->edit_mesh_face) {
- sh_data->edit_mesh_face = GPU_shader_create_from_arrays({
- .vert = (const char *[]){sh_cfg->lib,
- datatoc_common_globals_lib_glsl,
- datatoc_common_view_lib_glsl,
- datatoc_edit_mesh_common_lib_glsl,
- datatoc_edit_mesh_vert_glsl,
- NULL},
- .frag = (const char *[]){datatoc_gpu_shader_3D_smooth_color_frag_glsl, NULL},
- .defs = (const char *[]){sh_cfg->def, "#define FACE\n", NULL},
- });
+ sh_data->edit_mesh_face = GPU_shader_create_from_info_name(
+ draw_ctx->sh_cfg ? "overlay_edit_mesh_face_clipped" : "overlay_edit_mesh_face");
}
return sh_data->edit_mesh_face;
}
@@ -742,19 +594,10 @@ GPUShader *OVERLAY_shader_edit_mesh_face(void)
GPUShader *OVERLAY_shader_edit_mesh_facedot(void)
{
const DRWContextState *draw_ctx = DRW_context_state_get();
- const GPUShaderConfigData *sh_cfg = &GPU_shader_cfg_data[draw_ctx->sh_cfg];
OVERLAY_Shaders *sh_data = &e_data.sh_data[draw_ctx->sh_cfg];
if (!sh_data->edit_mesh_facedot) {
- sh_data->edit_mesh_facedot = GPU_shader_create_from_arrays({
- .vert = (const char *[]){sh_cfg->lib,
- datatoc_common_globals_lib_glsl,
- datatoc_common_view_lib_glsl,
- datatoc_edit_mesh_common_lib_glsl,
- datatoc_edit_mesh_vert_glsl,
- NULL},
- .frag = (const char *[]){datatoc_gpu_shader_point_varying_color_frag_glsl, NULL},
- .defs = (const char *[]){sh_cfg->def, "#define FACEDOT\n", NULL},
- });
+ sh_data->edit_mesh_facedot = GPU_shader_create_from_info_name(
+ draw_ctx->sh_cfg ? "overlay_edit_mesh_facedot_clipped" : "overlay_edit_mesh_facedot");
}
return sh_data->edit_mesh_facedot;
}
@@ -762,18 +605,10 @@ GPUShader *OVERLAY_shader_edit_mesh_facedot(void)
GPUShader *OVERLAY_shader_edit_mesh_normal(void)
{
const DRWContextState *draw_ctx = DRW_context_state_get();
- const GPUShaderConfigData *sh_cfg = &GPU_shader_cfg_data[draw_ctx->sh_cfg];
OVERLAY_Shaders *sh_data = &e_data.sh_data[draw_ctx->sh_cfg];
if (!sh_data->edit_mesh_normals) {
- sh_data->edit_mesh_normals = GPU_shader_create_from_arrays({
- .vert = (const char *[]){sh_cfg->lib,
- datatoc_common_globals_lib_glsl,
- datatoc_common_view_lib_glsl,
- datatoc_edit_mesh_normal_vert_glsl,
- NULL},
- .frag = (const char *[]){datatoc_gpu_shader_flat_color_frag_glsl, NULL},
- .defs = (const char *[]){sh_cfg->def, "#define INSTANCED_ATTR\n", NULL},
- });
+ sh_data->edit_mesh_normals = GPU_shader_create_from_info_name(
+ draw_ctx->sh_cfg ? "overlay_edit_mesh_normal_clipped" : "overlay_edit_mesh_normal");
}
return sh_data->edit_mesh_normals;
}
@@ -781,17 +616,10 @@ GPUShader *OVERLAY_shader_edit_mesh_normal(void)
GPUShader *OVERLAY_shader_edit_mesh_analysis(void)
{
const DRWContextState *draw_ctx = DRW_context_state_get();
- const GPUShaderConfigData *sh_cfg = &GPU_shader_cfg_data[draw_ctx->sh_cfg];
OVERLAY_Shaders *sh_data = &e_data.sh_data[draw_ctx->sh_cfg];
if (!sh_data->edit_mesh_analysis) {
- sh_data->edit_mesh_analysis = GPU_shader_create_from_arrays({
- .vert = (const char *[]){sh_cfg->lib,
- datatoc_common_view_lib_glsl,
- datatoc_edit_mesh_analysis_vert_glsl,
- NULL},
- .frag = (const char *[]){datatoc_edit_mesh_analysis_frag_glsl, NULL},
- .defs = (const char *[]){sh_cfg->def, NULL},
- });
+ sh_data->edit_mesh_analysis = GPU_shader_create_from_info_name(
+ draw_ctx->sh_cfg ? "overlay_edit_mesh_analysis_clipped" : "overlay_edit_mesh_analysis");
}
return sh_data->edit_mesh_analysis;
}
@@ -799,18 +627,10 @@ GPUShader *OVERLAY_shader_edit_mesh_analysis(void)
GPUShader *OVERLAY_shader_edit_mesh_skin_root(void)
{
const DRWContextState *draw_ctx = DRW_context_state_get();
- const GPUShaderConfigData *sh_cfg = &GPU_shader_cfg_data[draw_ctx->sh_cfg];
OVERLAY_Shaders *sh_data = &e_data.sh_data[draw_ctx->sh_cfg];
if (!sh_data->edit_mesh_skin_root) {
- sh_data->edit_mesh_skin_root = GPU_shader_create_from_arrays({
- .vert = (const char *[]){sh_cfg->lib,
- datatoc_common_globals_lib_glsl,
- datatoc_common_view_lib_glsl,
- datatoc_edit_mesh_skin_root_vert_glsl,
- NULL},
- .frag = (const char *[]){datatoc_gpu_shader_flat_color_frag_glsl, NULL},
- .defs = (const char *[]){sh_cfg->def, "#define INSTANCED_ATTR\n", NULL},
- });
+ sh_data->edit_mesh_skin_root = GPU_shader_create_from_info_name(
+ draw_ctx->sh_cfg ? "overlay_edit_mesh_skin_root_clipped" : "overlay_edit_mesh_skin_root");
}
return sh_data->edit_mesh_skin_root;
}
diff --git a/source/blender/draw/engines/overlay/overlay_wireframe.c b/source/blender/draw/engines/overlay/overlay_wireframe.c
index b3c0c5da9b5..a5628559cfd 100644
--- a/source/blender/draw/engines/overlay/overlay_wireframe.c
+++ b/source/blender/draw/engines/overlay/overlay_wireframe.c
@@ -148,7 +148,7 @@ static void wireframe_hair_cache_populate(OVERLAY_Data *vedata, Object *ob, Part
const bool use_coloring = true;
DRWShadingGroup *shgrp = DRW_shgroup_create_sub(pd->wires_hair_grp[is_xray][use_coloring]);
- DRW_shgroup_uniform_vec4_array_copy(shgrp, "hairDupliMatrix", dupli_mat, 4);
+ DRW_shgroup_uniform_mat4_copy(shgrp, "hairDupliMatrix", dupli_mat);
DRW_shgroup_call_no_cull(shgrp, hairs, ob);
}
diff --git a/source/blender/draw/engines/overlay/shaders/antialiasing_frag.glsl b/source/blender/draw/engines/overlay/shaders/antialiasing_frag.glsl
index 67d172fbd01..2f4542343f7 100644
--- a/source/blender/draw/engines/overlay/shaders/antialiasing_frag.glsl
+++ b/source/blender/draw/engines/overlay/shaders/antialiasing_frag.glsl
@@ -2,7 +2,7 @@
#pragma BLENDER_REQUIRE(common_math_lib.glsl)
uniform sampler2D colorTex;
-uniform sampler2D depthTex;
+uniform depth2D depthTex;
uniform sampler2D lineTex;
uniform bool doSmoothLines;
diff --git a/source/blender/draw/engines/overlay/shaders/armature_dof_solid_frag.glsl b/source/blender/draw/engines/overlay/shaders/armature_dof_solid_frag.glsl
index aedc9bcda61..d46abbf79ee 100644
--- a/source/blender/draw/engines/overlay/shaders/armature_dof_solid_frag.glsl
+++ b/source/blender/draw/engines/overlay/shaders/armature_dof_solid_frag.glsl
@@ -1,11 +1,4 @@
-uniform float alpha = 1.0;
-
-flat in vec4 finalColor;
-
-layout(location = 0) out vec4 fragColor;
-layout(location = 1) out vec4 lineOutput;
-
void main()
{
fragColor = vec4(finalColor.rgb, finalColor.a * alpha);
diff --git a/source/blender/draw/engines/overlay/shaders/armature_dof_vert.glsl b/source/blender/draw/engines/overlay/shaders/armature_dof_vert.glsl
index 18a80fc1fb4..b3c9ce5dfd2 100644
--- a/source/blender/draw/engines/overlay/shaders/armature_dof_vert.glsl
+++ b/source/blender/draw/engines/overlay/shaders/armature_dof_vert.glsl
@@ -1,17 +1,6 @@
-/* ---- Instantiated Attrs ---- */
-in vec2 pos;
-
-/* ---- Per instance Attrs ---- */
-/* Assumed to be in world coordinate already. */
-in vec4 color;
-in mat4 inst_obmat;
-
-flat out vec4 finalColor;
-#ifdef EDGE
-flat out vec2 edgeStart;
-noperspective out vec2 edgePos;
-#endif
+#pragma BLENDER_REQUIRE(common_view_clipping_lib.glsl)
+#pragma BLENDER_REQUIRE(common_view_lib.glsl)
vec3 sphere_project(float ax, float az)
{
@@ -37,11 +26,7 @@ void main()
gl_Position = point_world_to_ndc(world_pos);
finalColor = color;
-#ifdef EDGE
- edgeStart = edgePos = ((gl_Position.xy / gl_Position.w) * 0.5 + 0.5) * sizeViewport.xy;
-#endif
+ edgeStart = edgePos = ((gl_Position.xy / gl_Position.w) * 0.5 + 0.5) * sizeViewport;
-#ifdef USE_WORLD_CLIP_PLANES
- world_clip_planes_calc_clip_distance(world_pos);
-#endif
+ view_clipping_distances(world_pos);
}
diff --git a/source/blender/draw/engines/overlay/shaders/armature_envelope_outline_vert.glsl b/source/blender/draw/engines/overlay/shaders/armature_envelope_outline_vert.glsl
index 2260b2d3fa6..0a8e279e9b0 100644
--- a/source/blender/draw/engines/overlay/shaders/armature_envelope_outline_vert.glsl
+++ b/source/blender/draw/engines/overlay/shaders/armature_envelope_outline_vert.glsl
@@ -1,19 +1,6 @@
-/* ---- Instantiated Attrs ---- */
-in vec2 pos0;
-in vec2 pos1;
-in vec2 pos2;
-
-/* ---- Per instance Attrs ---- */
-/* Assumed to be in world coordinate already. */
-in vec4 headSphere;
-in vec4 tailSphere;
-in vec4 outlineColorSize;
-in vec3 xAxis;
-
-flat out vec4 finalColor;
-flat out vec2 edgeStart;
-noperspective out vec2 edgePos;
+#pragma BLENDER_REQUIRE(common_view_clipping_lib.glsl)
+#pragma BLENDER_REQUIRE(common_view_lib.glsl)
/* project to screen space */
vec2 proj(vec4 pos)
@@ -134,9 +121,7 @@ void main()
vec3 wpos2 = get_outline_point(
pos2, sph_near, sph_far, mat_near, mat_far, z_ofs_near, z_ofs_far, b);
-#ifdef USE_WORLD_CLIP_PLANES
- world_clip_planes_calc_clip_distance(wpos1);
-#endif
+ view_clipping_distances(wpos1);
vec4 p0 = point_world_to_ndc(wpos0);
vec4 p1 = point_world_to_ndc(wpos1);
@@ -152,7 +137,7 @@ void main()
vec2 ofs_dir = compute_dir(ss0, ss1, ss2);
/* Offset away from the center to avoid overlap with solid shape. */
- gl_Position.xy += ofs_dir * sizeViewportInv.xy * gl_Position.w;
+ gl_Position.xy += ofs_dir * drw_view.viewport_size_inverse * gl_Position.w;
edgeStart = edgePos = proj(gl_Position);
diff --git a/source/blender/draw/engines/overlay/shaders/armature_envelope_solid_frag.glsl b/source/blender/draw/engines/overlay/shaders/armature_envelope_solid_frag.glsl
index 51cfe6250be..a90d2e3e406 100644
--- a/source/blender/draw/engines/overlay/shaders/armature_envelope_solid_frag.glsl
+++ b/source/blender/draw/engines/overlay/shaders/armature_envelope_solid_frag.glsl
@@ -1,14 +1,4 @@
-uniform float alpha = 0.6;
-uniform bool isDistance;
-
-flat in vec3 finalStateColor;
-flat in vec3 finalBoneColor;
-in vec3 normalView;
-
-layout(location = 0) out vec4 fragColor;
-layout(location = 1) out vec4 lineOutput;
-
void main()
{
float n = normalize(normalView).z;
diff --git a/source/blender/draw/engines/overlay/shaders/armature_envelope_solid_vert.glsl b/source/blender/draw/engines/overlay/shaders/armature_envelope_solid_vert.glsl
index 620b3f2527c..2dd86a57dfd 100644
--- a/source/blender/draw/engines/overlay/shaders/armature_envelope_solid_vert.glsl
+++ b/source/blender/draw/engines/overlay/shaders/armature_envelope_solid_vert.glsl
@@ -1,18 +1,6 @@
-/* ---- Instantiated Attrs ---- */
-in vec3 pos;
-
-/* ---- Per instance Attrs ---- */
-/* Assumed to be in world coordinate already. */
-in vec4 headSphere;
-in vec4 tailSphere;
-in vec3 xAxis;
-in vec3 stateColor;
-in vec3 boneColor;
-
-flat out vec3 finalStateColor;
-flat out vec3 finalBoneColor;
-out vec3 normalView;
+#pragma BLENDER_REQUIRE(common_view_clipping_lib.glsl)
+#pragma BLENDER_REQUIRE(common_view_lib.glsl)
void main()
{
@@ -47,9 +35,8 @@ void main()
finalStateColor = stateColor;
finalBoneColor = boneColor;
+ view_clipping_distances(sp);
+
vec4 pos_4d = vec4(sp, 1.0);
gl_Position = ViewProjectionMatrix * pos_4d;
-#ifdef USE_WORLD_CLIP_PLANES
- world_clip_planes_calc_clip_distance(pos_4d.xyz);
-#endif
}
diff --git a/source/blender/draw/engines/overlay/shaders/armature_shape_outline_geom.glsl b/source/blender/draw/engines/overlay/shaders/armature_shape_outline_geom.glsl
index a2a478f400b..47c5dada708 100644
--- a/source/blender/draw/engines/overlay/shaders/armature_shape_outline_geom.glsl
+++ b/source/blender/draw/engines/overlay/shaders/armature_shape_outline_geom.glsl
@@ -1,28 +1,16 @@
-layout(lines_adjacency) in;
-layout(line_strip, max_vertices = 2) out;
-
-in vec4 pPos[];
-in vec3 vPos[];
-in vec2 ssPos[];
-in vec2 ssNor[];
-in vec4 vColSize[];
-in int inverted[];
-
-flat out vec4 finalColor;
-flat out vec2 edgeStart;
-noperspective out vec2 edgePos;
+#pragma BLENDER_REQUIRE(common_view_clipping_lib.glsl)
void main(void)
{
- finalColor = vec4(vColSize[0].rgb, 1.0);
+ finalColor = vec4(geom_in[0].vColSize.rgb, 1.0);
bool is_persp = (ProjectionMatrix[3][3] == 0.0);
- vec3 view_vec = (is_persp) ? normalize(vPos[1]) : vec3(0.0, 0.0, -1.0);
- vec3 v10 = vPos[0] - vPos[1];
- vec3 v12 = vPos[2] - vPos[1];
- vec3 v13 = vPos[3] - vPos[1];
+ vec3 view_vec = (is_persp) ? normalize(geom_in[1].vPos) : vec3(0.0, 0.0, -1.0);
+ vec3 v10 = geom_in[0].vPos - geom_in[1].vPos;
+ vec3 v12 = geom_in[2].vPos - geom_in[1].vPos;
+ vec3 v13 = geom_in[3].vPos - geom_in[1].vPos;
vec3 n0 = cross(v12, v10);
vec3 n3 = cross(v13, v12);
@@ -40,13 +28,13 @@ void main(void)
}
}
- n0 = (inverted[0] == 1) ? -n0 : n0;
+ n0 = (geom_in[0].inverted == 1) ? -n0 : n0;
/* Don't outline if concave edge. */
if (dot(n0, v13) > 0.0001) {
return;
}
- vec2 perp = normalize(ssPos[2] - ssPos[1]);
+ vec2 perp = normalize(geom_in[2].ssPos - geom_in[1].ssPos);
vec2 edge_dir = vec2(-perp.y, perp.x);
vec2 hidden_point;
@@ -55,37 +43,33 @@ void main(void)
* If the chosen point is parallel to the edge in screen space,
* choose the other point anyway.
* This fixes some issue with cubes in orthographic views. */
- if (vPos[0].z < vPos[3].z) {
- hidden_point = (abs(fac0) > 1e-5) ? ssPos[0] : ssPos[3];
+ if (geom_in[0].vPos.z < geom_in[3].vPos.z) {
+ hidden_point = (abs(fac0) > 1e-5) ? geom_in[0].ssPos : geom_in[3].ssPos;
}
else {
- hidden_point = (abs(fac3) > 1e-5) ? ssPos[3] : ssPos[0];
+ hidden_point = (abs(fac3) > 1e-5) ? geom_in[3].ssPos : geom_in[0].ssPos;
}
- vec2 hidden_dir = normalize(hidden_point - ssPos[1]);
+ vec2 hidden_dir = normalize(hidden_point - geom_in[1].ssPos);
float fac = dot(-hidden_dir, edge_dir);
edge_dir *= (fac < 0.0) ? -1.0 : 1.0;
- gl_Position = pPos[1];
+ gl_Position = geom_in[1].pPos;
/* Offset away from the center to avoid overlap with solid shape. */
- gl_Position.xy += (edge_dir - perp) * sizeViewportInv.xy * gl_Position.w;
+ gl_Position.xy += (edge_dir - perp) * drw_view.viewport_size_inverse * gl_Position.w;
/* Improve AA bleeding inside bone silhouette. */
gl_Position.z -= (is_persp) ? 1e-4 : 1e-6;
- edgeStart = edgePos = ((gl_Position.xy / gl_Position.w) * 0.5 + 0.5) * sizeViewport.xy;
-#ifdef USE_WORLD_CLIP_PLANES
- world_clip_planes_set_clip_distance(gl_in[1].gl_ClipDistance);
-#endif
+ edgeStart = edgePos = ((gl_Position.xy / gl_Position.w) * 0.5 + 0.5) * sizeViewport;
+ view_clipping_distances_set(gl_in[1]);
EmitVertex();
- gl_Position = pPos[2];
+ gl_Position = geom_in[2].pPos;
/* Offset away from the center to avoid overlap with solid shape. */
- gl_Position.xy += (edge_dir + perp) * sizeViewportInv.xy * gl_Position.w;
+ gl_Position.xy += (edge_dir + perp) * drw_view.viewport_size_inverse * gl_Position.w;
/* Improve AA bleeding inside bone silhouette. */
gl_Position.z -= (is_persp) ? 1e-4 : 1e-6;
edgeStart = edgePos = ((gl_Position.xy / gl_Position.w) * 0.5 + 0.5) * sizeViewport.xy;
-#ifdef USE_WORLD_CLIP_PLANES
- world_clip_planes_set_clip_distance(gl_in[2].gl_ClipDistance);
-#endif
+ view_clipping_distances_set(gl_in[2]);
EmitVertex();
EndPrimitive();
diff --git a/source/blender/draw/engines/overlay/shaders/armature_shape_outline_vert.glsl b/source/blender/draw/engines/overlay/shaders/armature_shape_outline_vert.glsl
index ddc6328e6a2..29319b3f7ac 100644
--- a/source/blender/draw/engines/overlay/shaders/armature_shape_outline_vert.glsl
+++ b/source/blender/draw/engines/overlay/shaders/armature_shape_outline_vert.glsl
@@ -1,18 +1,6 @@
-/* ---- Instantiated Attrs ---- */
-in vec3 pos;
-in vec3 snor;
-
-/* ---- Per instance Attrs ---- */
-in vec4 color;
-in mat4 inst_obmat;
-
-out vec4 pPos;
-out vec3 vPos;
-out vec2 ssPos;
-out vec2 ssNor;
-out vec4 vColSize;
-out int inverted;
+#pragma BLENDER_REQUIRE(common_view_clipping_lib.glsl)
+#pragma BLENDER_REQUIRE(common_view_lib.glsl)
/* project to screen space */
vec2 proj(vec4 pos)
@@ -25,13 +13,13 @@ void main()
vec4 bone_color, state_color;
mat4 model_mat = extract_matrix_packed_data(inst_obmat, state_color, bone_color);
- vec4 worldPosition = model_mat * vec4(pos, 1.0);
- vec4 viewpos = ViewMatrix * worldPosition;
+ vec4 world_pos = model_mat * vec4(pos, 1.0);
+ vec4 view_pos = ViewMatrix * world_pos;
- vPos = viewpos.xyz;
- pPos = ProjectionMatrix * viewpos;
+ geom_in.vPos = view_pos.xyz;
+ geom_in.pPos = ProjectionMatrix * view_pos;
- inverted = int(dot(cross(model_mat[0].xyz, model_mat[1].xyz), model_mat[2].xyz) < 0.0);
+ geom_in.inverted = int(dot(cross(model_mat[0].xyz, model_mat[1].xyz), model_mat[2].xyz) < 0.0);
/* This is slow and run per vertex, but it's still faster than
* doing it per instance on CPU and sending it on via instance attribute. */
@@ -39,13 +27,11 @@ void main()
/* TODO: FIX: there is still a problem with this vector
* when the bone is scaled or in persp mode. But it's
* barely visible at the outline corners. */
- ssNor = normalize(normal_world_to_view(normal_mat * snor).xy);
+ geom_in.ssNor = normalize(normal_world_to_view(normal_mat * snor).xy);
- ssPos = proj(pPos);
+ geom_in.ssPos = proj(geom_in.pPos);
- vColSize = bone_color;
+ geom_in.vColSize = bone_color;
-#ifdef USE_WORLD_CLIP_PLANES
- world_clip_planes_calc_clip_distance(worldPosition.xyz);
-#endif
+ view_clipping_distances(world_pos.xyz);
}
diff --git a/source/blender/draw/engines/overlay/shaders/armature_shape_solid_frag.glsl b/source/blender/draw/engines/overlay/shaders/armature_shape_solid_frag.glsl
index 26796c82f66..8e1768846dc 100644
--- a/source/blender/draw/engines/overlay/shaders/armature_shape_solid_frag.glsl
+++ b/source/blender/draw/engines/overlay/shaders/armature_shape_solid_frag.glsl
@@ -1,12 +1,4 @@
-uniform float alpha = 0.6;
-
-in vec4 finalColor;
-flat in int inverted;
-
-layout(location = 0) out vec4 fragColor;
-layout(location = 1) out vec4 lineOutput;
-
void main()
{
/* Manual back-face culling. Not ideal for performance
diff --git a/source/blender/draw/engines/overlay/shaders/armature_shape_solid_vert.glsl b/source/blender/draw/engines/overlay/shaders/armature_shape_solid_vert.glsl
index 5979a877681..cdbe8c3d7df 100644
--- a/source/blender/draw/engines/overlay/shaders/armature_shape_solid_vert.glsl
+++ b/source/blender/draw/engines/overlay/shaders/armature_shape_solid_vert.glsl
@@ -1,13 +1,6 @@
-/* ---- Instantiated Attrs ---- */
-in vec3 pos;
-in vec3 nor;
-
-/* ---- Per instance Attrs ---- */
-in mat4 inst_obmat;
-
-out vec4 finalColor;
-flat out int inverted;
+#pragma BLENDER_REQUIRE(common_view_clipping_lib.glsl)
+#pragma BLENDER_REQUIRE(common_view_lib.glsl)
void main()
{
@@ -31,10 +24,8 @@ void main()
finalColor.rgb = mix(state_color.rgb, bone_color.rgb, fac * fac);
finalColor.a = 1.0;
- vec4 worldPosition = model_mat * vec4(pos, 1.0);
- gl_Position = ViewProjectionMatrix * worldPosition;
+ vec4 world_pos = model_mat * vec4(pos, 1.0);
+ gl_Position = ViewProjectionMatrix * world_pos;
-#ifdef USE_WORLD_CLIP_PLANES
- world_clip_planes_calc_clip_distance(worldPosition.xyz);
-#endif
+ view_clipping_distances(world_pos.xyz);
}
diff --git a/source/blender/draw/engines/overlay/shaders/armature_shape_wire_vert.glsl b/source/blender/draw/engines/overlay/shaders/armature_shape_wire_vert.glsl
index 0bf21cbaaac..cee86956c43 100644
--- a/source/blender/draw/engines/overlay/shaders/armature_shape_wire_vert.glsl
+++ b/source/blender/draw/engines/overlay/shaders/armature_shape_wire_vert.glsl
@@ -1,14 +1,6 @@
-/* ---- Instantiated Attrs ---- */
-in vec3 pos;
-in vec3 nor;
-
-/* ---- Per instance Attrs ---- */
-in mat4 inst_obmat;
-
-flat out vec4 finalColor;
-flat out vec2 edgeStart;
-noperspective out vec2 edgePos;
+#pragma BLENDER_REQUIRE(common_view_clipping_lib.glsl)
+#pragma BLENDER_REQUIRE(common_view_lib.glsl)
void main()
{
@@ -23,7 +15,5 @@ void main()
edgeStart = edgePos = ((gl_Position.xy / gl_Position.w) * 0.5 + 0.5) * sizeViewport.xy;
-#ifdef USE_WORLD_CLIP_PLANES
- world_clip_planes_calc_clip_distance(world_pos);
-#endif
+ view_clipping_distances(world_pos);
}
diff --git a/source/blender/draw/engines/overlay/shaders/armature_sphere_outline_vert.glsl b/source/blender/draw/engines/overlay/shaders/armature_sphere_outline_vert.glsl
index 934485359b3..31369e0c3df 100644
--- a/source/blender/draw/engines/overlay/shaders/armature_sphere_outline_vert.glsl
+++ b/source/blender/draw/engines/overlay/shaders/armature_sphere_outline_vert.glsl
@@ -1,13 +1,6 @@
-/* ---- Instantiated Attrs ---- */
-in vec2 pos;
-
-/* ---- Per instance Attrs ---- */
-in mat4 inst_obmat;
-
-flat out vec4 finalColor;
-flat out vec2 edgeStart;
-noperspective out vec2 edgePos;
+#pragma BLENDER_REQUIRE(common_view_clipping_lib.glsl)
+#pragma BLENDER_REQUIRE(common_view_lib.glsl)
/* project to screen space */
vec2 proj(vec4 pos)
@@ -70,14 +63,12 @@ void main()
/* Offset away from the center to avoid overlap with solid shape. */
vec2 ofs_dir = normalize(proj(gl_Position) - proj(center));
- gl_Position.xy += ofs_dir * sizeViewportInv.xy * gl_Position.w;
+ gl_Position.xy += ofs_dir * drw_view.viewport_size_inverse * gl_Position.w;
edgeStart = edgePos = proj(gl_Position);
finalColor = vec4(bone_color.rgb, 1.0);
-#ifdef USE_WORLD_CLIP_PLANES
- vec4 worldPosition = model_mat * vec4(cam_pos0, 1.0);
- world_clip_planes_calc_clip_distance(worldPosition.xyz);
-#endif
+ vec4 world_pos = model_mat * vec4(cam_pos0, 1.0);
+ view_clipping_distances(world_pos.xyz);
}
diff --git a/source/blender/draw/engines/overlay/shaders/armature_sphere_solid_frag.glsl b/source/blender/draw/engines/overlay/shaders/armature_sphere_solid_frag.glsl
index 0925901a9c9..e60b6e94492 100644
--- a/source/blender/draw/engines/overlay/shaders/armature_sphere_solid_frag.glsl
+++ b/source/blender/draw/engines/overlay/shaders/armature_sphere_solid_frag.glsl
@@ -1,18 +1,5 @@
-uniform float alpha = 0.4;
-
-flat in vec3 finalStateColor;
-flat in vec3 finalBoneColor;
-flat in mat4 sphereMatrix;
-in vec3 viewPosition;
-
-#ifdef GL_ARB_conservative_depth
-/* Saves a lot of overdraw! */
-layout(depth_greater) out float gl_FragDepth;
-#endif
-
-layout(location = 0) out vec4 fragColor;
-layout(location = 1) out vec4 lineOutput;
+#pragma BLENDER_REQUIRE(common_view_lib.glsl)
void main()
{
diff --git a/source/blender/draw/engines/overlay/shaders/armature_sphere_solid_vert.glsl b/source/blender/draw/engines/overlay/shaders/armature_sphere_solid_vert.glsl
index e6fa29ce851..abbaad8cd10 100644
--- a/source/blender/draw/engines/overlay/shaders/armature_sphere_solid_vert.glsl
+++ b/source/blender/draw/engines/overlay/shaders/armature_sphere_solid_vert.glsl
@@ -1,15 +1,6 @@
-/* ---- Instantiated Attrs ---- */
-in vec2 pos;
-
-/* ---- Per instance Attrs ---- */
-in vec4 color;
-in mat4 inst_obmat;
-
-flat out vec3 finalStateColor;
-flat out vec3 finalBoneColor;
-flat out mat4 sphereMatrix;
-out vec3 viewPosition;
+#pragma BLENDER_REQUIRE(common_view_clipping_lib.glsl)
+#pragma BLENDER_REQUIRE(common_view_lib.glsl)
/* Sphere radius */
const float rad = 0.05;
@@ -80,8 +71,6 @@ void main()
finalStateColor = state_color.xyz;
finalBoneColor = bone_color.xyz;
-#ifdef USE_WORLD_CLIP_PLANES
- vec4 worldPosition = model_mat * pos_4d;
- world_clip_planes_calc_clip_distance(worldPosition.xyz);
-#endif
+ vec4 world_pos = model_mat * pos_4d;
+ view_clipping_distances(world_pos.xyz);
}
diff --git a/source/blender/draw/engines/overlay/shaders/armature_stick_frag.glsl b/source/blender/draw/engines/overlay/shaders/armature_stick_frag.glsl
index 85136672180..2e42cdf0517 100644
--- a/source/blender/draw/engines/overlay/shaders/armature_stick_frag.glsl
+++ b/source/blender/draw/engines/overlay/shaders/armature_stick_frag.glsl
@@ -1,13 +1,4 @@
-uniform float alpha = 1.0;
-
-noperspective in float colorFac;
-flat in vec4 finalWireColor;
-flat in vec4 finalInnerColor;
-
-layout(location = 0) out vec4 fragColor;
-layout(location = 1) out vec4 lineOutput;
-
void main()
{
float fac = smoothstep(1.0, 0.2, colorFac);
diff --git a/source/blender/draw/engines/overlay/shaders/armature_stick_vert.glsl b/source/blender/draw/engines/overlay/shaders/armature_stick_vert.glsl
index 0a2598fb6b7..b5edcd2858b 100644
--- a/source/blender/draw/engines/overlay/shaders/armature_stick_vert.glsl
+++ b/source/blender/draw/engines/overlay/shaders/armature_stick_vert.glsl
@@ -1,8 +1,8 @@
-/* ---- Instantiated Attrs ---- */
-in vec2 pos; /* bone aligned screen space */
-in uint flag;
+#pragma BLENDER_REQUIRE(common_view_clipping_lib.glsl)
+#pragma BLENDER_REQUIRE(common_view_lib.glsl)
+/* TODO(@fclem): Share definition with C code. */
#define COL_WIRE 1u /* (1 << 0) */
#define COL_HEAD 2u /* (1 << 1) */
#define COL_TAIL 4u /* (1 << 2) */
@@ -12,22 +12,9 @@ in uint flag;
#define POS_TAIL 32u /* (1 << 5) */ /* UNUSED */
#define POS_BONE 64u /* (1 << 6) */
-/* ---- Per instance Attrs ---- */
-in vec3 boneStart;
-in vec3 boneEnd;
-in vec4 wireColor; /* alpha encode if we do wire. If 0.0 we don't. */
-in vec4 boneColor; /* alpha encode if we do bone. If 0.0 we don't. */
-in vec4 headColor; /* alpha encode if we do head. If 0.0 we don't. */
-in vec4 tailColor; /* alpha encode if we do tail. If 0.0 we don't. */
-
-#define do_wire (wireColor.a > 0.0)
#define is_head bool(flag & POS_HEAD)
#define is_bone bool(flag & POS_BONE)
-noperspective out float colorFac;
-flat out vec4 finalWireColor;
-flat out vec4 finalInnerColor;
-
/* project to screen space */
vec2 proj(vec4 pos)
{
@@ -77,12 +64,9 @@ void main()
if (finalInnerColor.a > 0.0) {
float stick_size = sizePixel * 5.0;
gl_Position = (is_head) ? p0 : p1;
- gl_Position.xy += stick_size * (vpos * sizeViewportInv.xy);
+ gl_Position.xy += stick_size * (vpos * drw_view.viewport_size_inverse);
gl_Position.z += (is_bone) ? 0.0 : 1e-6; /* Avoid Z fighting of head/tails. */
-
-#ifdef USE_WORLD_CLIP_PLANES
- world_clip_planes_calc_clip_distance((is_head ? boneStart_4d : boneEnd_4d).xyz);
-#endif
+ view_clipping_distances((is_head ? boneStart_4d : boneEnd_4d).xyz);
}
else {
gl_Position = vec4(0.0);
diff --git a/source/blender/draw/engines/overlay/shaders/armature_wire_frag.glsl b/source/blender/draw/engines/overlay/shaders/armature_wire_frag.glsl
index 55278515f74..2c454a8becd 100644
--- a/source/blender/draw/engines/overlay/shaders/armature_wire_frag.glsl
+++ b/source/blender/draw/engines/overlay/shaders/armature_wire_frag.glsl
@@ -1,12 +1,5 @@
-uniform float alpha = 1.0;
-
-flat in vec4 finalColor;
-flat in vec2 edgeStart;
-noperspective in vec2 edgePos;
-
-layout(location = 0) out vec4 fragColor;
-layout(location = 1) out vec4 lineOutput;
+#pragma BLENDER_REQUIRE(common_view_lib.glsl)
void main()
{
diff --git a/source/blender/draw/engines/overlay/shaders/armature_wire_vert.glsl b/source/blender/draw/engines/overlay/shaders/armature_wire_vert.glsl
index d6d6cb6e024..c89d0249e4f 100644
--- a/source/blender/draw/engines/overlay/shaders/armature_wire_vert.glsl
+++ b/source/blender/draw/engines/overlay/shaders/armature_wire_vert.glsl
@@ -1,22 +1,16 @@
-in vec3 color;
-in vec3 pos;
-
-flat out vec4 finalColor;
-flat out vec2 edgeStart;
-noperspective out vec2 edgePos;
+#pragma BLENDER_REQUIRE(common_view_clipping_lib.glsl)
+#pragma BLENDER_REQUIRE(common_view_lib.glsl)
void main()
{
- finalColor.rgb = color;
+ finalColor.rgb = color.rgb;
finalColor.a = 1.0;
- vec3 worldPosition = point_object_to_world(pos);
- gl_Position = point_world_to_ndc(worldPosition);
+ vec3 world_pos = point_object_to_world(pos);
+ gl_Position = point_world_to_ndc(world_pos);
edgeStart = edgePos = ((gl_Position.xy / gl_Position.w) * 0.5 + 0.5) * sizeViewport.xy;
-#ifdef USE_WORLD_CLIP_PLANES
- world_clip_planes_calc_clip_distance(worldPosition);
-#endif
+ view_clipping_distances(world_pos);
}
diff --git a/source/blender/draw/engines/overlay/shaders/edit_mesh_analysis_frag.glsl b/source/blender/draw/engines/overlay/shaders/edit_mesh_analysis_frag.glsl
index 8d96c0e418f..430ace8726a 100644
--- a/source/blender/draw/engines/overlay/shaders/edit_mesh_analysis_frag.glsl
+++ b/source/blender/draw/engines/overlay/shaders/edit_mesh_analysis_frag.glsl
@@ -1,6 +1,3 @@
-out vec4 fragColor;
-
-in vec4 weightColor;
void main()
{
diff --git a/source/blender/draw/engines/overlay/shaders/edit_mesh_analysis_vert.glsl b/source/blender/draw/engines/overlay/shaders/edit_mesh_analysis_vert.glsl
index b89a3f407f9..1e163dc9a9a 100644
--- a/source/blender/draw/engines/overlay/shaders/edit_mesh_analysis_vert.glsl
+++ b/source/blender/draw/engines/overlay/shaders/edit_mesh_analysis_vert.glsl
@@ -1,10 +1,6 @@
-in vec3 pos;
-in float weight;
-
-uniform sampler1D weightTex;
-
-out vec4 weightColor;
+#pragma BLENDER_REQUIRE(common_view_clipping_lib.glsl)
+#pragma BLENDER_REQUIRE(common_view_lib.glsl)
vec3 weight_to_rgb(float t)
{
@@ -29,7 +25,5 @@ void main()
gl_Position = point_world_to_ndc(world_pos);
weightColor = vec4(weight_to_rgb(weight), 1.0);
-#ifdef USE_WORLD_CLIP_PLANES
- world_clip_planes_calc_clip_distance(world_pos);
-#endif
+ view_clipping_distances(world_pos);
}
diff --git a/source/blender/draw/engines/overlay/shaders/edit_mesh_common_lib.glsl b/source/blender/draw/engines/overlay/shaders/edit_mesh_common_lib.glsl
index 418c7bceb63..72b0a43cdb4 100644
--- a/source/blender/draw/engines/overlay/shaders/edit_mesh_common_lib.glsl
+++ b/source/blender/draw/engines/overlay/shaders/edit_mesh_common_lib.glsl
@@ -1,7 +1,4 @@
-uniform bool selectFaces = true;
-uniform bool selectEdges = true;
-
vec4 EDIT_MESH_edge_color_outer(int edge_flag, int face_flag, float crease, float bweight)
{
vec4 color = vec4(0.0);
diff --git a/source/blender/draw/engines/overlay/shaders/edit_mesh_frag.glsl b/source/blender/draw/engines/overlay/shaders/edit_mesh_frag.glsl
index 1fe20d1cb1f..2fd155f715c 100644
--- a/source/blender/draw/engines/overlay/shaders/edit_mesh_frag.glsl
+++ b/source/blender/draw/engines/overlay/shaders/edit_mesh_frag.glsl
@@ -12,35 +12,33 @@
#define GRID_LINE_SMOOTH_START (0.5 - DISC_RADIUS)
#define GRID_LINE_SMOOTH_END (0.5 + DISC_RADIUS)
-uniform sampler2D depthTex;
-uniform float alpha = 1.0;
-
-flat in vec4 finalColorOuter_f;
-in vec4 finalColor_f;
-noperspective in float edgeCoord_f;
-
-out vec4 FragColor;
-
bool test_occlusion()
{
return gl_FragCoord.z > texelFetch(depthTex, ivec2(gl_FragCoord.xy), 0).r;
}
+float edge_step(float dist)
+{
+ if (do_smooth_wire) {
+ return smoothstep(GRID_LINE_SMOOTH_START, GRID_LINE_SMOOTH_END, dist);
+ }
+ else {
+ return step(0.5, dist);
+ }
+}
+
void main()
{
- float dist = abs(edgeCoord_f) - max(sizeEdge - 0.5, 0.0);
+ float dist = abs(geometry_out.edgeCoord) - max(sizeEdge - 0.5, 0.0);
float dist_outer = dist - max(sizeEdge, 1.0);
-#ifdef USE_SMOOTH_WIRE
- float mix_w = smoothstep(GRID_LINE_SMOOTH_START, GRID_LINE_SMOOTH_END, dist);
- float mix_w_outer = smoothstep(GRID_LINE_SMOOTH_START, GRID_LINE_SMOOTH_END, dist_outer);
-#else
- float mix_w = step(0.5, dist);
- float mix_w_outer = step(0.5, dist_outer);
-#endif
+ float mix_w = edge_step(dist);
+ float mix_w_outer = edge_step(dist_outer);
/* Line color & alpha. */
- FragColor = mix(finalColorOuter_f, finalColor_f, 1.0 - mix_w * finalColorOuter_f.a);
+ fragColor = mix(geometry_out.finalColorOuter,
+ geometry_out.finalColor,
+ 1.0 - mix_w * geometry_out.finalColorOuter.a);
/* Line edges shape. */
- FragColor.a *= 1.0 - (finalColorOuter_f.a > 0.0 ? mix_w_outer : mix_w);
+ fragColor.a *= 1.0 - (geometry_out.finalColorOuter.a > 0.0 ? mix_w_outer : mix_w);
- FragColor.a *= test_occlusion() ? alpha : 1.0;
+ fragColor.a *= test_occlusion() ? alpha : 1.0;
}
diff --git a/source/blender/draw/engines/overlay/shaders/edit_mesh_geom.glsl b/source/blender/draw/engines/overlay/shaders/edit_mesh_geom.glsl
index 66fa85685e2..65615524927 100644
--- a/source/blender/draw/engines/overlay/shaders/edit_mesh_geom.glsl
+++ b/source/blender/draw/engines/overlay/shaders/edit_mesh_geom.glsl
@@ -1,26 +1,18 @@
-layout(lines) in;
-layout(triangle_strip, max_vertices = 4) out;
-
-in vec4 finalColor[2];
-in vec4 finalColorOuter[2];
-in int selectOverride[2];
-
-flat out vec4 finalColorOuter_f;
-out vec4 finalColor_f;
-noperspective out float edgeCoord_f;
+#pragma BLENDER_REQUIRE(common_view_clipping_lib.glsl)
+#pragma BLENDER_REQUIRE(common_view_lib.glsl)
void do_vertex(vec4 color, vec4 pos, float coord, vec2 offset)
{
- finalColor_f = color;
- edgeCoord_f = coord;
+ geometry_out.finalColor = color;
+ geometry_out.edgeCoord = coord;
gl_Position = pos;
/* Multiply offset by 2 because gl_Position range is [-1..1]. */
gl_Position.xy += offset * 2.0 * pos.w;
/* Correct but fails due to an AMD compiler bug, see: T62792.
* Do inline instead. */
#if 0
- world_clip_planes_set_clip_distance(gl_in[i].gl_ClipDistance);
+ view_clipping_distances_set(gl_in[i]);
#endif
EmitVertex();
}
@@ -54,33 +46,30 @@ void main()
vec2 line = ss_pos[0] - ss_pos[1];
line = abs(line) * sizeViewport.xy;
- finalColorOuter_f = finalColorOuter[0];
+ geometry_out.finalColorOuter = geometry_in[0].finalColorOuter;
float half_size = sizeEdge;
/* Enlarge edge for flag display. */
- half_size += (finalColorOuter_f.a > 0.0) ? max(sizeEdge, 1.0) : 0.0;
+ half_size += (geometry_out.finalColorOuter.a > 0.0) ? max(sizeEdge, 1.0) : 0.0;
-#ifdef USE_SMOOTH_WIRE
- /* Add 1 px for AA */
- half_size += 0.5;
-#endif
+ if (do_smooth_wire) {
+ /* Add 1 px for AA */
+ half_size += 0.5;
+ }
- vec3 edge_ofs = vec3(half_size * sizeViewportInv.xy, 0.0);
+ vec3 edge_ofs = vec3(half_size * drw_view.viewport_size_inverse, 0.0);
bool horizontal = line.x > line.y;
edge_ofs = (horizontal) ? edge_ofs.zyz : edge_ofs.xzz;
-#ifdef USE_WORLD_CLIP_PLANES
/* Due to an AMD glitch, this line was moved out of the `do_vertex`
* function (see T62792). */
- world_clip_planes_set_clip_distance(gl_in[0].gl_ClipDistance);
-#endif
- do_vertex(finalColor[0], pos0, half_size, edge_ofs.xy);
- do_vertex(finalColor[0], pos0, -half_size, -edge_ofs.xy);
+ view_clipping_distances_set(gl_in[0]);
+ do_vertex(geometry_in[0].finalColor, pos0, half_size, edge_ofs.xy);
+ do_vertex(geometry_in[0].finalColor, pos0, -half_size, -edge_ofs.xy);
-#ifdef USE_WORLD_CLIP_PLANES
- world_clip_planes_set_clip_distance(gl_in[1].gl_ClipDistance);
-#endif
- vec4 final_color = (selectOverride[0] == 0) ? finalColor[1] : finalColor[0];
+ view_clipping_distances_set(gl_in[1]);
+ vec4 final_color = (geometry_in[0].selectOverride == 0) ? geometry_in[1].finalColor :
+ geometry_in[0].finalColor;
do_vertex(final_color, pos1, half_size, edge_ofs.xy);
do_vertex(final_color, pos1, -half_size, -edge_ofs.xy);
diff --git a/source/blender/draw/engines/overlay/shaders/edit_mesh_normal_vert.glsl b/source/blender/draw/engines/overlay/shaders/edit_mesh_normal_vert.glsl
index d370943db03..6ff8d0665d1 100644
--- a/source/blender/draw/engines/overlay/shaders/edit_mesh_normal_vert.glsl
+++ b/source/blender/draw/engines/overlay/shaders/edit_mesh_normal_vert.glsl
@@ -1,16 +1,6 @@
-uniform float normalSize;
-uniform float normalScreenSize;
-uniform bool isConstantScreenSizeNormals;
-uniform sampler2D depthTex;
-uniform float alpha = 1.0;
-
-in vec3 pos;
-in vec4 lnor;
-in vec4 vnor;
-in vec4 norAndFlag;
-
-flat out vec4 finalColor;
+#pragma BLENDER_REQUIRE(common_view_clipping_lib.glsl)
+#pragma BLENDER_REQUIRE(common_view_lib.glsl)
bool test_occlusion()
{
@@ -75,7 +65,5 @@ void main()
finalColor.a *= (test_occlusion()) ? alpha : 1.0;
-#ifdef USE_WORLD_CLIP_PLANES
- world_clip_planes_calc_clip_distance(world_pos);
-#endif
+ view_clipping_distances(world_pos);
}
diff --git a/source/blender/draw/engines/overlay/shaders/edit_mesh_skin_root_vert.glsl b/source/blender/draw/engines/overlay/shaders/edit_mesh_skin_root_vert.glsl
index 944eb41058e..f1fbdac7847 100644
--- a/source/blender/draw/engines/overlay/shaders/edit_mesh_skin_root_vert.glsl
+++ b/source/blender/draw/engines/overlay/shaders/edit_mesh_skin_root_vert.glsl
@@ -1,12 +1,6 @@
-/* ---- Instantiated Attrs ---- */
-in vec3 pos;
-
-/* ---- Per instance Attrs ---- */
-in float size;
-in vec3 local_pos;
-
-flat out vec4 finalColor;
+#pragma BLENDER_REQUIRE(common_view_clipping_lib.glsl)
+#pragma BLENDER_REQUIRE(common_view_lib.glsl)
void main()
{
@@ -19,7 +13,5 @@ void main()
/* Manual stipple: one segment out of 2 is transparent. */
finalColor = ((gl_VertexID & 1) == 0) ? colorSkinRoot : vec4(0.0);
-#ifdef USE_WORLD_CLIP_PLANES
- world_clip_planes_calc_clip_distance(pos_4d.xyz);
-#endif
+ view_clipping_distances(pos_4d.xyz);
}
diff --git a/source/blender/draw/engines/overlay/shaders/edit_mesh_vert.glsl b/source/blender/draw/engines/overlay/shaders/edit_mesh_vert.glsl
index 5cee976f9a8..77826e26c8a 100644
--- a/source/blender/draw/engines/overlay/shaders/edit_mesh_vert.glsl
+++ b/source/blender/draw/engines/overlay/shaders/edit_mesh_vert.glsl
@@ -1,26 +1,13 @@
-uniform sampler2D depthTex;
-uniform float alpha = 1.0;
-uniform ivec4 dataMask = ivec4(0xFF);
-
-in ivec4 data;
-in vec3 pos;
-#ifndef FACEDOT
-in vec3 vnor;
-#else
-in vec4 norAndFlag;
-# define vnor norAndFlag.xyz
-#endif
+#pragma BLENDER_REQUIRE(common_view_clipping_lib.glsl)
+#pragma BLENDER_REQUIRE(common_view_lib.glsl)
+#pragma BLENDER_REQUIRE(edit_mesh_common_lib.glsl)
-out vec4 finalColor;
-#ifdef VERT
-out float vertexCrease;
-#endif
#ifdef EDGE
-out vec4 finalColorOuter;
-#endif
-#ifdef USE_GEOM_SHADER
-out int selectOverride;
+/* Ugly but needed to keep the same vertex shader code for other passes. */
+# define finalColor geometry_in.finalColor
+# define finalColorOuter geometry_in.finalColorOuter
+# define selectOverride geometry_in.selectOverride
#endif
bool test_occlusion()
@@ -108,7 +95,5 @@ void main()
finalColor.rgb = non_linear_blend_color(colorEditMeshMiddle.rgb, finalColor.rgb, facing);
#endif
-#ifdef USE_WORLD_CLIP_PLANES
- world_clip_planes_calc_clip_distance(world_pos);
-#endif
+ view_clipping_distances(world_pos);
}
diff --git a/source/blender/draw/engines/overlay/shaders/extra_lightprobe_grid_vert.glsl b/source/blender/draw/engines/overlay/shaders/extra_lightprobe_grid_vert.glsl
index 1f3a23324bb..8006c51a946 100644
--- a/source/blender/draw/engines/overlay/shaders/extra_lightprobe_grid_vert.glsl
+++ b/source/blender/draw/engines/overlay/shaders/extra_lightprobe_grid_vert.glsl
@@ -1,6 +1,6 @@
-uniform sampler2D depthBuffer;
-uniform vec4 gridModelMatrix[4];
+uniform depth2D depthBuffer;
+uniform mat4 gridModelMatrix;
uniform bool isTransform;
out vec4 finalColor;
@@ -27,8 +27,7 @@ vec4 color_from_id(float color_id)
void main()
{
- mat4 model_mat = mat4(
- gridModelMatrix[0], gridModelMatrix[1], gridModelMatrix[2], gridModelMatrix[3]);
+ mat4 model_mat = gridModelMatrix;
model_mat[0][3] = model_mat[1][3] = model_mat[2][3] = 0.0;
model_mat[3][3] = 1.0;
float color_id = gridModelMatrix[3].w;
diff --git a/source/blender/draw/engines/overlay/shaders/grid_frag.glsl b/source/blender/draw/engines/overlay/shaders/grid_frag.glsl
index 9feca644bd3..4a9b8d15528 100644
--- a/source/blender/draw/engines/overlay/shaders/grid_frag.glsl
+++ b/source/blender/draw/engines/overlay/shaders/grid_frag.glsl
@@ -12,7 +12,7 @@ uniform vec3 planeAxes;
uniform float gridDistance;
uniform vec3 gridSize;
uniform float lineKernel = 0.0;
-uniform sampler2D depthBuffer;
+uniform depth2D depthBuffer;
uniform int gridFlag;
uniform float zoomFactor;
@@ -49,7 +49,7 @@ float get_grid(vec2 co, vec2 fwidthCos, float grid_size)
{
float half_size = grid_size / 2.0;
/* triangular wave pattern, amplitude is [0, half_size] */
- vec2 grid_domain = abs(mod(co + half_size, grid_size) - half_size);
+ vec2 grid_domain = abs(mod(co + half_size, vec2(grid_size)) - half_size);
/* modulate by the absolute rate of change of the coordinates
* (make lines have the same width under perspective) */
grid_domain /= fwidthCos;
diff --git a/source/blender/draw/engines/overlay/shaders/infos/armature_info.hh b/source/blender/draw/engines/overlay/shaders/infos/armature_info.hh
new file mode 100644
index 00000000000..f417fbe1fd4
--- /dev/null
+++ b/source/blender/draw/engines/overlay/shaders/infos/armature_info.hh
@@ -0,0 +1,262 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#include "gpu_shader_create_info.hh"
+
+GPU_SHADER_CREATE_INFO(overlay_frag_output)
+ .fragment_out(0, Type::VEC4, "fragColor")
+ .fragment_out(1, Type::VEC4, "lineOutput");
+
+GPU_SHADER_INTERFACE_INFO(overlay_armature_wire_iface, "")
+ .flat(Type::VEC4, "finalColor")
+ .flat(Type::VEC2, "edgeStart")
+ .no_perspective(Type::VEC2, "edgePos");
+
+GPU_SHADER_CREATE_INFO(overlay_armature_common)
+ .push_constant(Type::FLOAT, "alpha")
+ .additional_info("draw_view");
+
+/* -------------------------------------------------------------------- */
+/** \name Armature Sphere
+ * \{ */
+
+GPU_SHADER_CREATE_INFO(overlay_armature_sphere_outline)
+ .do_static_compilation(true)
+ .vertex_in(0, Type::VEC2, "pos")
+ /* Per instance. */
+ .vertex_in(1, Type::MAT4, "inst_obmat")
+ .vertex_out(overlay_armature_wire_iface)
+ .vertex_source("armature_sphere_outline_vert.glsl")
+ .fragment_source("armature_wire_frag.glsl")
+ .additional_info("overlay_frag_output", "overlay_armature_common", "draw_globals");
+
+GPU_SHADER_CREATE_INFO(overlay_armature_sphere_outline_clipped)
+ .do_static_compilation(true)
+ .additional_info("overlay_armature_sphere_outline", "drw_clipped");
+
+GPU_SHADER_INTERFACE_INFO(overlay_armature_sphere_solid_iface, "")
+ .flat(Type::VEC3, "finalStateColor")
+ .flat(Type::VEC3, "finalBoneColor")
+ .flat(Type::MAT4, "sphereMatrix")
+ .smooth(Type::VEC3, "viewPosition");
+
+GPU_SHADER_CREATE_INFO(overlay_armature_sphere_solid)
+ .do_static_compilation(true)
+ .vertex_in(0, Type::VEC2, "pos")
+ /* Per instance. */
+ .vertex_in(1, Type::MAT4, "inst_obmat")
+ .vertex_in(2, Type::VEC4, "color")
+ // .depth_layout(DepthLayout::GREATER) /* TODO */
+ .vertex_out(overlay_armature_sphere_solid_iface)
+ .vertex_source("armature_sphere_solid_vert.glsl")
+ .fragment_source("armature_sphere_solid_frag.glsl")
+ .additional_info("overlay_frag_output", "overlay_armature_common", "draw_globals");
+
+GPU_SHADER_CREATE_INFO(overlay_armature_sphere_solid_clipped)
+ .do_static_compilation(true)
+ .additional_info("overlay_armature_sphere_solid", "drw_clipped");
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Armature Shapes
+ * \{ */
+
+GPU_SHADER_INTERFACE_INFO(overlay_armature_shape_outline_iface, "geom_in")
+ .smooth(Type::VEC4, "pPos")
+ .smooth(Type::VEC3, "vPos")
+ .smooth(Type::VEC2, "ssPos")
+ .smooth(Type::VEC2, "ssNor")
+ .smooth(Type::VEC4, "vColSize")
+ .flat(Type::INT, "inverted");
+
+GPU_SHADER_CREATE_INFO(overlay_armature_shape_outline)
+ .do_static_compilation(true)
+ .vertex_in(0, Type::VEC3, "pos")
+ .vertex_in(1, Type::VEC3, "snor")
+ /* Per instance. */
+ .vertex_in(2, Type::VEC4, "color")
+ .vertex_in(3, Type::MAT4, "inst_obmat")
+ .vertex_out(overlay_armature_shape_outline_iface)
+ .geometry_layout(PrimitiveIn::LINES_ADJACENCY, PrimitiveOut::LINE_STRIP, 2)
+ .geometry_out(overlay_armature_wire_iface)
+ .vertex_source("armature_shape_outline_vert.glsl")
+ .geometry_source("armature_shape_outline_geom.glsl")
+ .fragment_source("armature_wire_frag.glsl")
+ .additional_info("overlay_frag_output", "overlay_armature_common", "draw_globals");
+
+GPU_SHADER_CREATE_INFO(overlay_armature_shape_outline_clipped)
+ .do_static_compilation(true)
+ .additional_info("overlay_armature_shape_outline", "drw_clipped");
+
+GPU_SHADER_INTERFACE_INFO(overlay_armature_shape_solid_iface, "")
+ .smooth(Type::VEC4, "finalColor")
+ .flat(Type::INT, "inverted");
+
+GPU_SHADER_CREATE_INFO(overlay_armature_shape_solid)
+ .do_static_compilation(true)
+ .vertex_in(0, Type::VEC3, "pos")
+ .vertex_in(1, Type::VEC3, "nor")
+ /* Per instance. */
+ .vertex_in(2, Type::MAT4, "inst_obmat")
+ .depth_write(DepthWrite::GREATER)
+ .vertex_out(overlay_armature_shape_solid_iface)
+ .vertex_source("armature_shape_solid_vert.glsl")
+ .fragment_source("armature_shape_solid_frag.glsl")
+ .additional_info("overlay_frag_output", "overlay_armature_common", "draw_globals");
+
+GPU_SHADER_CREATE_INFO(overlay_armature_shape_solid_clipped)
+ .do_static_compilation(true)
+ .additional_info("overlay_armature_shape_solid", "drw_clipped");
+
+GPU_SHADER_CREATE_INFO(overlay_armature_shape_wire)
+ .do_static_compilation(true)
+ .vertex_in(0, Type::VEC3, "pos")
+ .vertex_in(1, Type::VEC3, "nor")
+ /* Per instance. */
+ .vertex_in(2, Type::MAT4, "inst_obmat")
+ .vertex_out(overlay_armature_wire_iface)
+ .vertex_source("armature_shape_wire_vert.glsl")
+ .fragment_source("armature_wire_frag.glsl")
+ .additional_info("overlay_frag_output", "overlay_armature_common", "draw_globals");
+
+GPU_SHADER_CREATE_INFO(overlay_armature_shape_wire_clipped)
+ .do_static_compilation(true)
+ .additional_info("overlay_armature_shape_wire", "drw_clipped");
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Armature Envelope
+ * \{ */
+
+GPU_SHADER_CREATE_INFO(overlay_armature_envelope_outline)
+ .do_static_compilation(true)
+ .vertex_in(0, Type::VEC2, "pos0")
+ .vertex_in(1, Type::VEC2, "pos1")
+ .vertex_in(2, Type::VEC2, "pos2")
+ /* Per instance. */
+ .vertex_in(3, Type::VEC4, "headSphere")
+ .vertex_in(4, Type::VEC4, "tailSphere")
+ .vertex_in(5, Type::VEC4, "outlineColorSize")
+ .vertex_in(6, Type::VEC3, "xAxis")
+ .vertex_out(overlay_armature_wire_iface)
+ .vertex_source("armature_envelope_outline_vert.glsl")
+ .fragment_source("armature_wire_frag.glsl")
+ .additional_info("overlay_frag_output", "overlay_armature_common", "draw_globals");
+
+GPU_SHADER_CREATE_INFO(overlay_armature_envelope_outline_clipped)
+ .do_static_compilation(true)
+ .additional_info("overlay_armature_envelope_outline", "drw_clipped");
+
+GPU_SHADER_INTERFACE_INFO(overlay_armature_envelope_solid_iface, "")
+ .flat(Type::VEC3, "finalStateColor")
+ .flat(Type::VEC3, "finalBoneColor")
+ .smooth(Type::VEC3, "normalView");
+
+GPU_SHADER_CREATE_INFO(overlay_armature_envelope_solid)
+ .do_static_compilation(true)
+ .vertex_in(0, Type::VEC3, "pos")
+ /* Per instance. Assumed to be in world coordinate already. */
+ .vertex_in(1, Type::VEC4, "headSphere")
+ .vertex_in(2, Type::VEC4, "tailSphere")
+ .vertex_in(3, Type::VEC3, "xAxis")
+ .vertex_in(4, Type::VEC3, "stateColor")
+ .vertex_in(5, Type::VEC3, "boneColor")
+ .vertex_out(overlay_armature_envelope_solid_iface)
+ .push_constant(Type::BOOL, "isDistance")
+ .vertex_source("armature_envelope_solid_vert.glsl")
+ .fragment_source("armature_envelope_solid_frag.glsl")
+ .additional_info("overlay_frag_output", "overlay_armature_common");
+
+GPU_SHADER_CREATE_INFO(overlay_armature_envelope_solid_clipped)
+ .do_static_compilation(true)
+ .additional_info("overlay_armature_envelope_solid", "drw_clipped");
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Armature Stick
+ * \{ */
+
+GPU_SHADER_INTERFACE_INFO(overlay_armature_stick_iface, "")
+ .no_perspective(Type::FLOAT, "colorFac")
+ .flat(Type::VEC4, "finalWireColor")
+ .flat(Type::VEC4, "finalInnerColor");
+
+GPU_SHADER_CREATE_INFO(overlay_armature_stick)
+ .do_static_compilation(true)
+ /* Bone aligned screen space. */
+ .vertex_in(0, Type::VEC2, "pos")
+ .vertex_in(1, Type::UINT, "flag")
+ /* Per instance. Assumed to be in world coordinate already. */
+ .vertex_in(2, Type::VEC3, "boneStart")
+ .vertex_in(3, Type::VEC3, "boneEnd")
+ /* alpha encode if we do wire. If 0.0 we don't. */
+ .vertex_in(4, Type::VEC4, "wireColor")
+ .vertex_in(5, Type::VEC4, "boneColor")
+ .vertex_in(6, Type::VEC4, "headColor")
+ .vertex_in(7, Type::VEC4, "tailColor")
+ .define("do_wire", "(wireColor.a > 0.0)")
+ .vertex_out(overlay_armature_stick_iface)
+ .vertex_source("armature_stick_vert.glsl")
+ .fragment_source("armature_stick_frag.glsl")
+ .additional_info("overlay_frag_output", "overlay_armature_common", "draw_globals");
+
+GPU_SHADER_CREATE_INFO(overlay_armature_stick_clipped)
+ .do_static_compilation(true)
+ .additional_info("overlay_armature_stick", "drw_clipped");
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Armature Degrees of Freedom
+ * \{ */
+
+GPU_SHADER_CREATE_INFO(overlay_armature_dof)
+ .vertex_in(0, Type::VEC2, "pos")
+ /* Per instance. Assumed to be in world coordinate already. */
+ .vertex_in(1, Type::VEC4, "color")
+ .vertex_in(2, Type::MAT4, "inst_obmat")
+ .vertex_out(overlay_armature_wire_iface)
+ .vertex_source("armature_dof_vert.glsl")
+ .additional_info("overlay_frag_output", "overlay_armature_common", "draw_globals");
+
+GPU_SHADER_CREATE_INFO(overlay_armature_dof_wire)
+ .do_static_compilation(true)
+ .fragment_source("armature_dof_solid_frag.glsl")
+ .additional_info("overlay_armature_dof");
+
+GPU_SHADER_CREATE_INFO(overlay_armature_dof_wire_clipped)
+ .do_static_compilation(true)
+ .additional_info("overlay_armature_dof_wire", "drw_clipped");
+
+GPU_SHADER_CREATE_INFO(overlay_armature_dof_solid)
+ .do_static_compilation(true)
+ .fragment_source("armature_dof_solid_frag.glsl")
+ .additional_info("overlay_armature_dof");
+
+GPU_SHADER_CREATE_INFO(overlay_armature_dof_solid_clipped)
+ .do_static_compilation(true)
+ .additional_info("overlay_armature_dof_solid", "drw_clipped");
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Armature Wire
+ * \{ */
+
+GPU_SHADER_CREATE_INFO(overlay_armature_wire)
+ .do_static_compilation(true)
+ .vertex_in(0, Type::VEC3, "pos")
+ .vertex_in(1, Type::VEC4, "color")
+ .push_constant(Type::FLOAT, "alpha")
+ .vertex_out(overlay_armature_wire_iface)
+ .vertex_source("armature_wire_vert.glsl")
+ .fragment_source("armature_wire_frag.glsl")
+ .additional_info("overlay_frag_output", "draw_mesh", "draw_globals");
+
+GPU_SHADER_CREATE_INFO(overlay_armature_wire_clipped)
+ .do_static_compilation(true)
+ .additional_info("overlay_armature_wire", "drw_clipped");
+
+/** \} */
diff --git a/source/blender/draw/engines/overlay/shaders/infos/edit_mode_info.hh b/source/blender/draw/engines/overlay/shaders/infos/edit_mode_info.hh
new file mode 100644
index 00000000000..c756b9473a3
--- /dev/null
+++ b/source/blender/draw/engines/overlay/shaders/infos/edit_mode_info.hh
@@ -0,0 +1,164 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#include "gpu_shader_create_info.hh"
+
+/* -------------------------------------------------------------------- */
+/** \name Edit Mesh
+ * \{ */
+
+GPU_SHADER_INTERFACE_INFO(overlay_edit_mesh_color_iface, "").flat(Type::VEC4, "finalColor");
+
+GPU_SHADER_CREATE_INFO(overlay_edit_mesh_common)
+ .define("blender_srgb_to_framebuffer_space(a)", "a")
+ .sampler(0, ImageType::DEPTH_2D, "depthTex")
+ .fragment_out(0, Type::VEC4, "fragColor")
+ .push_constant(Type::BOOL, "selectFaces")
+ .push_constant(Type::BOOL, "selectEdges")
+ .push_constant(Type::FLOAT, "alpha")
+ .push_constant(Type::IVEC4, "dataMask")
+ .vertex_source("edit_mesh_vert.glsl")
+ .additional_info("draw_modelmat", "draw_globals");
+
+GPU_SHADER_INTERFACE_INFO(overlay_edit_mesh_vert_iface, "")
+ .smooth(Type::VEC4, "finalColor")
+ .smooth(Type::FLOAT, "vertexCrease");
+
+GPU_SHADER_CREATE_INFO(overlay_edit_mesh_vert)
+ .do_static_compilation(true)
+ .builtins(BuiltinBits::POINT_SIZE)
+ .define("srgbTarget", "false") /* Colors are already in linear space. */
+ .define("VERT")
+ .vertex_in(0, Type::VEC3, "pos")
+ .vertex_in(1, Type::IVEC4, "data")
+ .vertex_in(2, Type::VEC3, "vnor")
+ .vertex_out(overlay_edit_mesh_vert_iface)
+ .fragment_source("gpu_shader_point_varying_color_frag.glsl")
+ .additional_info("overlay_edit_mesh_common");
+
+GPU_SHADER_INTERFACE_INFO(overlay_edit_mesh_edge_iface, "geometry_in")
+ .smooth(Type::VEC4, "finalColor")
+ .smooth(Type::VEC4, "finalColorOuter")
+ .smooth(Type::INT, "selectOverride");
+
+GPU_SHADER_INTERFACE_INFO(overlay_edit_mesh_edge_geom_iface, "geometry_out")
+ .smooth(Type::VEC4, "finalColor")
+ .flat(Type::VEC4, "finalColorOuter")
+ .no_perspective(Type::FLOAT, "edgeCoord");
+
+GPU_SHADER_CREATE_INFO(overlay_edit_mesh_edge)
+ .do_static_compilation(true)
+ .define("EDGE")
+ .vertex_in(0, Type::VEC3, "pos")
+ .vertex_in(1, Type::IVEC4, "data")
+ .vertex_in(2, Type::VEC3, "vnor")
+ .push_constant(Type::BOOL, "do_smooth_wire")
+ .vertex_out(overlay_edit_mesh_edge_iface)
+ .geometry_out(overlay_edit_mesh_edge_geom_iface)
+ .geometry_layout(PrimitiveIn::LINES, PrimitiveOut::TRIANGLE_STRIP, 4)
+ .geometry_source("edit_mesh_geom.glsl")
+ .fragment_source("edit_mesh_frag.glsl")
+ .additional_info("overlay_edit_mesh_common");
+
+GPU_SHADER_CREATE_INFO(overlay_edit_mesh_edge_flat)
+ .do_static_compilation(true)
+ .define("FLAT")
+ .additional_info("overlay_edit_mesh_edge");
+
+GPU_SHADER_CREATE_INFO(overlay_edit_mesh_face)
+ .do_static_compilation(true)
+ .define("srgbTarget", "false") /* Colors are already in linear space. */
+ .define("FACE")
+ .vertex_in(0, Type::VEC3, "pos")
+ .vertex_in(1, Type::IVEC4, "data")
+ .vertex_in(2, Type::VEC3, "vnor")
+ .vertex_out(overlay_edit_mesh_color_iface)
+ .fragment_source("gpu_shader_3D_smooth_color_frag.glsl")
+ .additional_info("overlay_edit_mesh_common");
+
+GPU_SHADER_CREATE_INFO(overlay_edit_mesh_facedot)
+ .do_static_compilation(true)
+ .define("FACEDOT")
+ .vertex_in(0, Type::VEC3, "pos")
+ .vertex_in(1, Type::IVEC4, "data")
+ .vertex_in(2, Type::VEC4, "norAndFlag")
+ .define("vnor", "norAndFlag.xyz")
+ .vertex_out(overlay_edit_mesh_color_iface)
+ .fragment_source("gpu_shader_point_varying_color_frag.glsl")
+ .additional_info("overlay_edit_mesh_common");
+
+GPU_SHADER_CREATE_INFO(overlay_edit_mesh_normal)
+ .do_static_compilation(true)
+ .define("srgbTarget", "false") /* Colors are already in linear space. */
+ .vertex_in(0, Type::VEC3, "pos")
+ .vertex_in(1, Type::VEC4, "lnor")
+ .vertex_in(2, Type::VEC4, "vnor")
+ .vertex_in(3, Type::VEC4, "norAndFlag")
+ .sampler(0, ImageType::DEPTH_2D, "depthTex")
+ .push_constant(Type::FLOAT, "normalSize")
+ .push_constant(Type::FLOAT, "normalScreenSize")
+ .push_constant(Type::FLOAT, "alpha")
+ .push_constant(Type::BOOL, "isConstantScreenSizeNormals")
+ .vertex_out(overlay_edit_mesh_color_iface)
+ .fragment_out(0, Type::VEC4, "fragColor")
+ .vertex_source("edit_mesh_normal_vert.glsl")
+ .fragment_source("gpu_shader_flat_color_frag.glsl")
+ .additional_info("draw_modelmat_instanced_attr", "draw_globals");
+
+GPU_SHADER_INTERFACE_INFO(overlay_edit_mesh_analysis_iface, "").smooth(Type::VEC4, "weightColor");
+
+GPU_SHADER_CREATE_INFO(overlay_edit_mesh_analysis)
+ .do_static_compilation(true)
+ .vertex_in(0, Type::VEC3, "pos")
+ .vertex_in(1, Type::FLOAT, "weight")
+ .sampler(0, ImageType::FLOAT_1D, "weightTex")
+ .fragment_out(0, Type::VEC4, "fragColor")
+ .vertex_out(overlay_edit_mesh_analysis_iface)
+ .vertex_source("edit_mesh_analysis_vert.glsl")
+ .fragment_source("edit_mesh_analysis_frag.glsl")
+ .additional_info("draw_modelmat");
+
+GPU_SHADER_CREATE_INFO(overlay_edit_mesh_skin_root)
+ .do_static_compilation(true)
+ .define("srgbTarget", "false") /* Colors are already in linear space. */
+ .vertex_in(0, Type::VEC3, "pos")
+ .vertex_in(1, Type::FLOAT, "size")
+ .vertex_in(2, Type::VEC3, "local_pos")
+ .vertex_out(overlay_edit_mesh_color_iface)
+ .fragment_out(0, Type::VEC4, "fragColor")
+ .vertex_source("edit_mesh_skin_root_vert.glsl")
+ .fragment_source("gpu_shader_flat_color_frag.glsl")
+ .additional_info("draw_modelmat_instanced_attr", "draw_globals");
+
+GPU_SHADER_CREATE_INFO(overlay_edit_mesh_vert_clipped)
+ .do_static_compilation(true)
+ .additional_info("overlay_edit_mesh_vert", "drw_clipped");
+
+GPU_SHADER_CREATE_INFO(overlay_edit_mesh_edge_clipped)
+ .do_static_compilation(true)
+ .additional_info("overlay_edit_mesh_edge", "drw_clipped");
+
+GPU_SHADER_CREATE_INFO(overlay_edit_mesh_edge_flat_clipped)
+ .do_static_compilation(true)
+ .additional_info("overlay_edit_mesh_edge_flat", "drw_clipped");
+
+GPU_SHADER_CREATE_INFO(overlay_edit_mesh_face_clipped)
+ .do_static_compilation(true)
+ .additional_info("overlay_edit_mesh_face", "drw_clipped");
+
+GPU_SHADER_CREATE_INFO(overlay_edit_mesh_facedot_clipped)
+ .do_static_compilation(true)
+ .additional_info("overlay_edit_mesh_facedot", "drw_clipped");
+
+GPU_SHADER_CREATE_INFO(overlay_edit_mesh_normal_clipped)
+ .do_static_compilation(true)
+ .additional_info("overlay_edit_mesh_normal", "drw_clipped");
+
+GPU_SHADER_CREATE_INFO(overlay_edit_mesh_analysis_clipped)
+ .do_static_compilation(true)
+ .additional_info("overlay_edit_mesh_analysis", "drw_clipped");
+
+GPU_SHADER_CREATE_INFO(overlay_edit_mesh_skin_root_clipped)
+ .do_static_compilation(true)
+ .additional_info("overlay_edit_mesh_skin_root", "drw_clipped");
+
+/** \} */
diff --git a/source/blender/draw/engines/overlay/shaders/wireframe_vert.glsl b/source/blender/draw/engines/overlay/shaders/wireframe_vert.glsl
index 060b7a957c1..8d26aa89f13 100644
--- a/source/blender/draw/engines/overlay/shaders/wireframe_vert.glsl
+++ b/source/blender/draw/engines/overlay/shaders/wireframe_vert.glsl
@@ -6,7 +6,7 @@ uniform bool isTransform;
uniform bool isObjectColor;
uniform bool isRandomColor;
uniform bool isHair;
-uniform vec4 hairDupliMatrix[4];
+uniform mat4 hairDupliMatrix;
in vec3 pos;
in vec3 nor;
@@ -94,9 +94,7 @@ void main()
vec3 wpos = point_object_to_world(pos);
if (isHair) {
- mat4 obmat = mat4(
- hairDupliMatrix[0], hairDupliMatrix[1], hairDupliMatrix[2], hairDupliMatrix[3]);
-
+ mat4 obmat = hairDupliMatrix;
wpos = (obmat * vec4(pos, 1.0)).xyz;
wnor = -normalize(mat3(obmat) * nor);
}
diff --git a/source/blender/draw/engines/select/select_draw_utils.c b/source/blender/draw/engines/select/select_draw_utils.c
index 7615b5bb39c..613b60f8829 100644
--- a/source/blender/draw/engines/select/select_draw_utils.c
+++ b/source/blender/draw/engines/select/select_draw_utils.c
@@ -31,7 +31,7 @@
void select_id_object_min_max(Object *obj, float r_min[3], float r_max[3])
{
- BoundBox *bb;
+ const BoundBox *bb;
BMEditMesh *em = BKE_editmesh_from_object(obj);
if (em) {
bb = BKE_editmesh_cage_boundbox_get(obj, em);
diff --git a/source/blender/draw/engines/workbench/shaders/infos/workbench_prepass_info.hh b/source/blender/draw/engines/workbench/shaders/infos/workbench_prepass_info.hh
index 6e1da090f9f..d3766da23cf 100644
--- a/source/blender/draw/engines/workbench/shaders/infos/workbench_prepass_info.hh
+++ b/source/blender/draw/engines/workbench/shaders/infos/workbench_prepass_info.hh
@@ -74,7 +74,7 @@ GPU_SHADER_INTERFACE_INFO(workbench_material_iface, "")
.smooth(Type::FLOAT, "alpha_interp")
.smooth(Type::VEC2, "uv_interp")
.flat(Type::INT, "object_id")
- .flat(Type::FLOAT, "roughness")
+ .flat(Type::FLOAT, "_roughness")
.flat(Type::FLOAT, "metallic");
GPU_SHADER_CREATE_INFO(workbench_material)
diff --git a/source/blender/draw/engines/workbench/shaders/workbench_prepass_frag.glsl b/source/blender/draw/engines/workbench/shaders/workbench_prepass_frag.glsl
index 1b20171b3ff..82fa65449eb 100644
--- a/source/blender/draw/engines/workbench/shaders/workbench_prepass_frag.glsl
+++ b/source/blender/draw/engines/workbench/shaders/workbench_prepass_frag.glsl
@@ -7,7 +7,7 @@ void main()
{
normalData = workbench_normal_encode(gl_FrontFacing, normal_interp);
- materialData = vec4(color_interp, workbench_float_pair_encode(roughness, metallic));
+ materialData = vec4(color_interp, workbench_float_pair_encode(_roughness, metallic));
objectId = uint(object_id);
diff --git a/source/blender/draw/engines/workbench/shaders/workbench_prepass_hair_vert.glsl b/source/blender/draw/engines/workbench/shaders/workbench_prepass_hair_vert.glsl
index 65b9f4de4b6..71cf08b7e8c 100644
--- a/source/blender/draw/engines/workbench/shaders/workbench_prepass_hair_vert.glsl
+++ b/source/blender/draw/engines/workbench/shaders/workbench_prepass_hair_vert.glsl
@@ -66,7 +66,7 @@ void main()
normal_interp = normalize(normal_world_to_view(nor));
- workbench_material_data_get(resource_handle, color_interp, alpha_interp, roughness, metallic);
+ workbench_material_data_get(resource_handle, color_interp, alpha_interp, _roughness, metallic);
if (materialIndex == 0) {
color_interp = hair_get_customdata_vec3(ac);
@@ -76,7 +76,7 @@ void main()
* So we lower their alpha artificially. */
alpha_interp *= 0.3;
- workbench_hair_random_material(hair_rand, color_interp, roughness, metallic);
+ workbench_hair_random_material(hair_rand, color_interp, _roughness, metallic);
object_id = int(uint(resource_handle) & 0xFFFFu) + 1;
}
diff --git a/source/blender/draw/engines/workbench/shaders/workbench_prepass_pointcloud_vert.glsl b/source/blender/draw/engines/workbench/shaders/workbench_prepass_pointcloud_vert.glsl
index 911d6f5b036..366bc2f9105 100644
--- a/source/blender/draw/engines/workbench/shaders/workbench_prepass_pointcloud_vert.glsl
+++ b/source/blender/draw/engines/workbench/shaders/workbench_prepass_pointcloud_vert.glsl
@@ -19,7 +19,7 @@ void main()
uv_interp = vec2(0.0);
- workbench_material_data_get(resource_handle, color_interp, alpha_interp, roughness, metallic);
+ workbench_material_data_get(resource_handle, color_interp, alpha_interp, _roughness, metallic);
if (materialIndex == 0) {
color_interp = vec3(1.0);
diff --git a/source/blender/draw/engines/workbench/shaders/workbench_prepass_vert.glsl b/source/blender/draw/engines/workbench/shaders/workbench_prepass_vert.glsl
index 3a63b141c5f..0637f669961 100644
--- a/source/blender/draw/engines/workbench/shaders/workbench_prepass_vert.glsl
+++ b/source/blender/draw/engines/workbench/shaders/workbench_prepass_vert.glsl
@@ -16,7 +16,7 @@ void main()
normal_interp = normalize(normal_object_to_view(nor));
- workbench_material_data_get(resource_handle, color_interp, alpha_interp, roughness, metallic);
+ workbench_material_data_get(resource_handle, color_interp, alpha_interp, _roughness, metallic);
if (materialIndex == 0) {
color_interp = ac.rgb;
diff --git a/source/blender/draw/engines/workbench/shaders/workbench_transparent_accum_frag.glsl b/source/blender/draw/engines/workbench/shaders/workbench_transparent_accum_frag.glsl
index 9c0f93c67d9..d8f1b83d747 100644
--- a/source/blender/draw/engines/workbench/shaders/workbench_transparent_accum_frag.glsl
+++ b/source/blender/draw/engines/workbench/shaders/workbench_transparent_accum_frag.glsl
@@ -62,7 +62,7 @@ void main()
#endif
#ifdef V3D_LIGHTING_STUDIO
- vec3 shaded_color = get_world_lighting(color, roughness, metallic, N, I);
+ vec3 shaded_color = get_world_lighting(color, _roughness, metallic, N, I);
#endif
#ifdef V3D_LIGHTING_FLAT
diff --git a/source/blender/draw/engines/workbench/workbench_shadow.c b/source/blender/draw/engines/workbench/workbench_shadow.c
index 432e571d74b..588c7240ab2 100644
--- a/source/blender/draw/engines/workbench/workbench_shadow.c
+++ b/source/blender/draw/engines/workbench/workbench_shadow.c
@@ -166,7 +166,7 @@ void workbench_shadow_cache_init(WORKBENCH_Data *data)
}
}
-static BoundBox *workbench_shadow_object_shadow_bbox_get(WORKBENCH_PrivateData *wpd,
+static const BoundBox *workbench_shadow_object_shadow_bbox_get(WORKBENCH_PrivateData *wpd,
Object *ob,
WORKBENCH_ObjectData *oed)
{
@@ -178,7 +178,7 @@ static BoundBox *workbench_shadow_object_shadow_bbox_get(WORKBENCH_PrivateData *
INIT_MINMAX(oed->shadow_min, oed->shadow_max);
/* From object space to shadow space */
- BoundBox *bbox = BKE_object_boundbox_get(ob);
+ const BoundBox *bbox = BKE_object_boundbox_get(ob);
for (int i = 0; i < 8; i++) {
float corner[3];
mul_v3_m4v3(corner, tmp_mat, bbox->vec[i]);
@@ -203,7 +203,7 @@ static bool workbench_shadow_object_cast_visible_shadow(WORKBENCH_PrivateData *w
Object *ob,
WORKBENCH_ObjectData *oed)
{
- BoundBox *shadow_bbox = workbench_shadow_object_shadow_bbox_get(wpd, ob, oed);
+ const BoundBox *shadow_bbox = workbench_shadow_object_shadow_bbox_get(wpd, ob, oed);
const DRWView *default_view = DRW_view_default_get();
return DRW_culling_box_test(default_view, shadow_bbox);
}
@@ -212,7 +212,7 @@ static float workbench_shadow_object_shadow_distance(WORKBENCH_PrivateData *wpd,
Object *ob,
WORKBENCH_ObjectData *oed)
{
- BoundBox *shadow_bbox = workbench_shadow_object_shadow_bbox_get(wpd, ob, oed);
+ const BoundBox *shadow_bbox = workbench_shadow_object_shadow_bbox_get(wpd, ob, oed);
const int corners[4] = {0, 3, 4, 7};
float dist = 1e4f, dist_isect;
diff --git a/source/blender/draw/intern/DRW_render.h b/source/blender/draw/intern/DRW_render.h
index 8dbf5483d47..d3b1d2e74a2 100644
--- a/source/blender/draw/intern/DRW_render.h
+++ b/source/blender/draw/intern/DRW_render.h
@@ -634,10 +634,9 @@ void DRW_shgroup_uniform_float_copy(DRWShadingGroup *shgroup, const char *name,
void DRW_shgroup_uniform_vec2_copy(DRWShadingGroup *shgroup, const char *name, const float *value);
void DRW_shgroup_uniform_vec3_copy(DRWShadingGroup *shgroup, const char *name, const float *value);
void DRW_shgroup_uniform_vec4_copy(DRWShadingGroup *shgroup, const char *name, const float *value);
-void DRW_shgroup_uniform_vec4_array_copy(DRWShadingGroup *shgroup,
- const char *name,
- const float (*value)[4],
- int arraysize);
+void DRW_shgroup_uniform_mat4_copy(DRWShadingGroup *shgroup,
+ const char *name,
+ const float (*value)[4]);
void DRW_shgroup_vertex_buffer_ex(DRWShadingGroup *shgroup,
const char *name,
struct GPUVertBuf *vertex_buffer DRW_DEBUG_FILE_LINE_ARGS);
diff --git a/source/blender/draw/intern/draw_cache.c b/source/blender/draw/intern/draw_cache.c
index 8fc97ddcfc2..1c2a580e26d 100644
--- a/source/blender/draw/intern/draw_cache.c
+++ b/source/blender/draw/intern/draw_cache.c
@@ -26,6 +26,7 @@
#include "GPU_batch.h"
#include "GPU_batch_utils.h"
+#include "GPU_capabilities.h"
#include "MEM_guardedalloc.h"
@@ -395,12 +396,12 @@ GPUBatch *DRW_cache_quad_get(void)
int v = 0;
int flag = VCLASS_EMPTY_SCALED;
- const float p[4][2] = {{-1.0f, -1.0f}, {-1.0f, 1.0f}, {1.0f, 1.0f}, {1.0f, -1.0f}};
+ const float p[4][2] = {{-1.0f, 1.0f}, {1.0f, 1.0f}, {-1.0f, -1.0f}, {1.0f, -1.0f}};
for (int a = 0; a < 4; a++) {
GPU_vertbuf_vert_set(vbo, v++, &(Vert){{p[a][0], p[a][1], 0.0f}, flag});
}
- SHC.drw_quad = GPU_batch_create_ex(GPU_PRIM_TRI_FAN, vbo, NULL, GPU_BATCH_OWNS_VBO);
+ SHC.drw_quad = GPU_batch_create_ex(GPU_PRIM_TRI_STRIP, vbo, NULL, GPU_BATCH_OWNS_VBO);
}
return SHC.drw_quad;
}
diff --git a/source/blender/draw/intern/draw_cache_extract_mesh.cc b/source/blender/draw/intern/draw_cache_extract_mesh.cc
index e84f2c7a327..717ea00fc0c 100644
--- a/source/blender/draw/intern/draw_cache_extract_mesh.cc
+++ b/source/blender/draw/intern/draw_cache_extract_mesh.cc
@@ -842,6 +842,7 @@ static void mesh_buffer_cache_create_requested_subdiv(MeshBatchCache *cache,
EXTRACT_ADD_REQUESTED(vbo, tan);
EXTRACT_ADD_REQUESTED(vbo, edituv_stretch_area);
EXTRACT_ADD_REQUESTED(vbo, edituv_stretch_angle);
+ EXTRACT_ADD_REQUESTED(ibo, lines_paint_mask);
EXTRACT_ADD_REQUESTED(ibo, lines_adjacency);
EXTRACT_ADD_REQUESTED(vbo, vcol);
EXTRACT_ADD_REQUESTED(vbo, weights);
diff --git a/source/blender/draw/intern/draw_cache_extract_mesh_render_data.c b/source/blender/draw/intern/draw_cache_extract_mesh_render_data.c
index a2995d6cd3f..0a93f346b37 100644
--- a/source/blender/draw/intern/draw_cache_extract_mesh_render_data.c
+++ b/source/blender/draw/intern/draw_cache_extract_mesh_render_data.c
@@ -461,7 +461,14 @@ MeshRenderData *mesh_render_data_create(Object *object,
mr->bm_poly_centers = mr->edit_data->polyCos;
}
- bool has_mdata = is_mode_active && (mr->me->runtime.wrapper_type == ME_WRAPPER_TYPE_MDATA);
+ /* A subdivision wrapper may be created in edit mode when X-ray is turned on to ensure that the
+ * topology seen by the user matches the one used for the selection routines. This wrapper
+ * seemingly takes precedence over the MDATA one, however the mesh we use for rendering is not
+ * the subdivided one, but the one where the MDATA wrapper would have been added. So consider
+ * the subdivision wrapper as well for the `has_mdata` case. */
+ bool has_mdata = is_mode_active && ELEM(mr->me->runtime.wrapper_type,
+ ME_WRAPPER_TYPE_MDATA,
+ ME_WRAPPER_TYPE_SUBD);
bool use_mapped = is_mode_active &&
(has_mdata && !do_uvedit && mr->me && !mr->me->runtime.is_original);
diff --git a/source/blender/draw/intern/draw_cache_impl_curves.cc b/source/blender/draw/intern/draw_cache_impl_curves.cc
index a21a6409ca5..0b8913402e6 100644
--- a/source/blender/draw/intern/draw_cache_impl_curves.cc
+++ b/source/blender/draw/intern/draw_cache_impl_curves.cc
@@ -4,7 +4,7 @@
/** \file
* \ingroup draw
*
- * \brief Hair API for render engines
+ * \brief Curves API for render engines
*/
#include <cstring>
@@ -35,33 +35,29 @@ using blender::float3;
using blender::IndexRange;
using blender::Span;
-static void curves_batch_cache_clear(Curves *curves);
-
/* ---------------------------------------------------------------------- */
-/* Hair GPUBatch Cache */
+/* Curves GPUBatch Cache */
-struct HairBatchCache {
+struct CurvesBatchCache {
ParticleHairCache hair;
- /* settings to determine if cache is invalid */
+ /* To determine if cache is invalid. */
bool is_dirty;
};
-/* GPUBatch cache management. */
-
-static bool curves_batch_cache_valid(Curves *curves)
+static bool curves_batch_cache_valid(const Curves &curves)
{
- HairBatchCache *cache = static_cast<HairBatchCache *>(curves->batch_cache);
+ const CurvesBatchCache *cache = static_cast<CurvesBatchCache *>(curves.batch_cache);
return (cache && cache->is_dirty == false);
}
-static void curves_batch_cache_init(Curves *curves)
+static void curves_batch_cache_init(Curves &curves)
{
- HairBatchCache *cache = static_cast<HairBatchCache *>(curves->batch_cache);
+ CurvesBatchCache *cache = static_cast<CurvesBatchCache *>(curves.batch_cache);
if (!cache) {
- cache = MEM_cnew<HairBatchCache>(__func__);
- curves->batch_cache = cache;
+ cache = MEM_cnew<CurvesBatchCache>(__func__);
+ curves.batch_cache = cache;
}
else {
memset(cache, 0, sizeof(*cache));
@@ -70,23 +66,33 @@ static void curves_batch_cache_init(Curves *curves)
cache->is_dirty = false;
}
+static void curves_batch_cache_clear(Curves &curves)
+{
+ CurvesBatchCache *cache = static_cast<CurvesBatchCache *>(curves.batch_cache);
+ if (!cache) {
+ return;
+ }
+
+ particle_batch_cache_clear_hair(&cache->hair);
+}
+
void DRW_curves_batch_cache_validate(Curves *curves)
{
- if (!curves_batch_cache_valid(curves)) {
- curves_batch_cache_clear(curves);
- curves_batch_cache_init(curves);
+ if (!curves_batch_cache_valid(*curves)) {
+ curves_batch_cache_clear(*curves);
+ curves_batch_cache_init(*curves);
}
}
-static HairBatchCache *curves_batch_cache_get(Curves *curves)
+static CurvesBatchCache &curves_batch_cache_get(Curves &curves)
{
- DRW_curves_batch_cache_validate(curves);
- return static_cast<HairBatchCache *>(curves->batch_cache);
+ DRW_curves_batch_cache_validate(&curves);
+ return *static_cast<CurvesBatchCache *>(curves.batch_cache);
}
void DRW_curves_batch_cache_dirty_tag(Curves *curves, int mode)
{
- HairBatchCache *cache = static_cast<HairBatchCache *>(curves->batch_cache);
+ CurvesBatchCache *cache = static_cast<CurvesBatchCache *>(curves->batch_cache);
if (cache == nullptr) {
return;
}
@@ -99,52 +105,42 @@ void DRW_curves_batch_cache_dirty_tag(Curves *curves, int mode)
}
}
-static void curves_batch_cache_clear(Curves *curves)
-{
- HairBatchCache *cache = static_cast<HairBatchCache *>(curves->batch_cache);
- if (!cache) {
- return;
- }
-
- particle_batch_cache_clear_hair(&cache->hair);
-}
-
void DRW_curves_batch_cache_free(Curves *curves)
{
- curves_batch_cache_clear(curves);
+ curves_batch_cache_clear(*curves);
MEM_SAFE_FREE(curves->batch_cache);
}
-static void ensure_seg_pt_count(Curves *curves, ParticleHairCache *curves_cache)
+static void ensure_seg_pt_count(const Curves &curves, ParticleHairCache &curves_cache)
{
- if ((curves_cache->pos != nullptr && curves_cache->indices != nullptr) ||
- (curves_cache->proc_point_buf != nullptr)) {
+ if ((curves_cache.pos != nullptr && curves_cache.indices != nullptr) ||
+ (curves_cache.proc_point_buf != nullptr)) {
return;
}
- curves_cache->strands_len = curves->geometry.curve_size;
- curves_cache->elems_len = curves->geometry.point_size + curves->geometry.curve_size;
- curves_cache->point_len = curves->geometry.point_size;
+ curves_cache.strands_len = curves.geometry.curve_size;
+ curves_cache.elems_len = curves.geometry.point_size + curves.geometry.curve_size;
+ curves_cache.point_len = curves.geometry.point_size;
}
-static void curves_batch_cache_fill_segments_proc_pos(Curves *curves,
- GPUVertBufRaw *attr_step,
- GPUVertBufRaw *length_step)
+static void curves_batch_cache_fill_segments_proc_pos(const Curves &curves_id,
+ GPUVertBufRaw &attr_step,
+ GPUVertBufRaw &length_step)
{
/* TODO: use hair radius layer if available. */
- const int curve_size = curves->geometry.curve_size;
- const blender::bke::CurvesGeometry &geometry = blender::bke::CurvesGeometry::wrap(
- curves->geometry);
- Span<float3> positions = geometry.positions();
+ const int curve_size = curves_id.geometry.curve_size;
+ const blender::bke::CurvesGeometry &curves = blender::bke::CurvesGeometry::wrap(
+ curves_id.geometry);
+ Span<float3> positions = curves.positions();
for (const int i : IndexRange(curve_size)) {
- const IndexRange curve_range = geometry.points_for_curve(i);
+ const IndexRange curve_range = curves.points_for_curve(i);
Span<float3> curve_positions = positions.slice(curve_range);
float total_len = 0.0f;
float *seg_data_first;
for (const int i_curve : curve_positions.index_range()) {
- float *seg_data = (float *)GPU_vertbuf_raw_step(attr_step);
+ float *seg_data = (float *)GPU_vertbuf_raw_step(&attr_step);
copy_v3_v3(seg_data, curve_positions[i_curve]);
if (i_curve == 0) {
seg_data_first = seg_data;
@@ -156,7 +152,7 @@ static void curves_batch_cache_fill_segments_proc_pos(Curves *curves,
seg_data[3] = total_len;
}
/* Assign length value. */
- *(float *)GPU_vertbuf_raw_step(length_step) = total_len;
+ *(float *)GPU_vertbuf_raw_step(&length_step) = total_len;
if (total_len > 0.0f) {
/* Divide by total length to have a [0-1] number. */
for ([[maybe_unused]] const int i_curve : curve_positions.index_range()) {
@@ -167,67 +163,67 @@ static void curves_batch_cache_fill_segments_proc_pos(Curves *curves,
}
}
-static void curves_batch_cache_ensure_procedural_pos(Curves *curves,
- ParticleHairCache *cache,
+static void curves_batch_cache_ensure_procedural_pos(Curves &curves,
+ ParticleHairCache &cache,
GPUMaterial *gpu_material)
{
- if (cache->proc_point_buf == nullptr) {
- /* initialize vertex format */
+ if (cache.proc_point_buf == nullptr) {
+ /* Initialize vertex format. */
GPUVertFormat format = {0};
uint pos_id = GPU_vertformat_attr_add(&format, "posTime", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
- cache->proc_point_buf = GPU_vertbuf_create_with_format(&format);
- GPU_vertbuf_data_alloc(cache->proc_point_buf, cache->point_len);
+ cache.proc_point_buf = GPU_vertbuf_create_with_format(&format);
+ GPU_vertbuf_data_alloc(cache.proc_point_buf, cache.point_len);
GPUVertBufRaw point_step;
- GPU_vertbuf_attr_get_raw_data(cache->proc_point_buf, pos_id, &point_step);
+ GPU_vertbuf_attr_get_raw_data(cache.proc_point_buf, pos_id, &point_step);
GPUVertFormat length_format = {0};
uint length_id = GPU_vertformat_attr_add(
&length_format, "hairLength", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
- cache->proc_length_buf = GPU_vertbuf_create_with_format(&length_format);
- GPU_vertbuf_data_alloc(cache->proc_length_buf, cache->strands_len);
+ cache.proc_length_buf = GPU_vertbuf_create_with_format(&length_format);
+ GPU_vertbuf_data_alloc(cache.proc_length_buf, cache.strands_len);
GPUVertBufRaw length_step;
- GPU_vertbuf_attr_get_raw_data(cache->proc_length_buf, length_id, &length_step);
+ GPU_vertbuf_attr_get_raw_data(cache.proc_length_buf, length_id, &length_step);
- curves_batch_cache_fill_segments_proc_pos(curves, &point_step, &length_step);
+ curves_batch_cache_fill_segments_proc_pos(curves, point_step, length_step);
/* Create vbo immediately to bind to texture buffer. */
- GPU_vertbuf_use(cache->proc_point_buf);
- cache->point_tex = GPU_texture_create_from_vertbuf("hair_point", cache->proc_point_buf);
+ GPU_vertbuf_use(cache.proc_point_buf);
+ cache.point_tex = GPU_texture_create_from_vertbuf("hair_point", cache.proc_point_buf);
}
- if (gpu_material && cache->proc_length_buf != nullptr && cache->length_tex) {
+ if (gpu_material && cache.proc_length_buf != nullptr && cache.length_tex) {
ListBase gpu_attrs = GPU_material_attributes(gpu_material);
LISTBASE_FOREACH (GPUMaterialAttribute *, attr, &gpu_attrs) {
if (attr->type == CD_HAIRLENGTH) {
- GPU_vertbuf_use(cache->proc_length_buf);
- cache->length_tex = GPU_texture_create_from_vertbuf("hair_length", cache->proc_length_buf);
+ GPU_vertbuf_use(cache.proc_length_buf);
+ cache.length_tex = GPU_texture_create_from_vertbuf("hair_length", cache.proc_length_buf);
break;
}
}
}
}
-static void curves_batch_cache_fill_strands_data(Curves *curves,
- GPUVertBufRaw *data_step,
- GPUVertBufRaw *seg_step)
+static void curves_batch_cache_fill_strands_data(const Curves &curves_id,
+ GPUVertBufRaw &data_step,
+ GPUVertBufRaw &seg_step)
{
- const blender::bke::CurvesGeometry &geometry = blender::bke::CurvesGeometry::wrap(
- curves->geometry);
+ const blender::bke::CurvesGeometry &curves = blender::bke::CurvesGeometry::wrap(
+ curves_id.geometry);
- for (const int i : IndexRange(geometry.curves_num())) {
- const IndexRange curve_range = geometry.points_for_curve(i);
+ for (const int i : IndexRange(curves.curves_num())) {
+ const IndexRange curve_range = curves.points_for_curve(i);
- *(uint *)GPU_vertbuf_raw_step(data_step) = curve_range.start();
- *(ushort *)GPU_vertbuf_raw_step(seg_step) = curve_range.size() - 1;
+ *(uint *)GPU_vertbuf_raw_step(&data_step) = curve_range.start();
+ *(ushort *)GPU_vertbuf_raw_step(&seg_step) = curve_range.size() - 1;
}
}
-static void curves_batch_cache_ensure_procedural_strand_data(Curves *curves,
- ParticleHairCache *cache)
+static void curves_batch_cache_ensure_procedural_strand_data(Curves &curves,
+ ParticleHairCache &cache)
{
GPUVertBufRaw data_step, seg_step;
@@ -237,77 +233,76 @@ static void curves_batch_cache_ensure_procedural_strand_data(Curves *curves,
GPUVertFormat format_seg = {0};
uint seg_id = GPU_vertformat_attr_add(&format_seg, "data", GPU_COMP_U16, 1, GPU_FETCH_INT);
- /* Strand Data */
- cache->proc_strand_buf = GPU_vertbuf_create_with_format(&format_data);
- GPU_vertbuf_data_alloc(cache->proc_strand_buf, cache->strands_len);
- GPU_vertbuf_attr_get_raw_data(cache->proc_strand_buf, data_id, &data_step);
+ /* Curve Data. */
+ cache.proc_strand_buf = GPU_vertbuf_create_with_format(&format_data);
+ GPU_vertbuf_data_alloc(cache.proc_strand_buf, cache.strands_len);
+ GPU_vertbuf_attr_get_raw_data(cache.proc_strand_buf, data_id, &data_step);
- cache->proc_strand_seg_buf = GPU_vertbuf_create_with_format(&format_seg);
- GPU_vertbuf_data_alloc(cache->proc_strand_seg_buf, cache->strands_len);
- GPU_vertbuf_attr_get_raw_data(cache->proc_strand_seg_buf, seg_id, &seg_step);
+ cache.proc_strand_seg_buf = GPU_vertbuf_create_with_format(&format_seg);
+ GPU_vertbuf_data_alloc(cache.proc_strand_seg_buf, cache.strands_len);
+ GPU_vertbuf_attr_get_raw_data(cache.proc_strand_seg_buf, seg_id, &seg_step);
- curves_batch_cache_fill_strands_data(curves, &data_step, &seg_step);
+ curves_batch_cache_fill_strands_data(curves, data_step, seg_step);
/* Create vbo immediately to bind to texture buffer. */
- GPU_vertbuf_use(cache->proc_strand_buf);
- cache->strand_tex = GPU_texture_create_from_vertbuf("curves_strand", cache->proc_strand_buf);
+ GPU_vertbuf_use(cache.proc_strand_buf);
+ cache.strand_tex = GPU_texture_create_from_vertbuf("curves_strand", cache.proc_strand_buf);
- GPU_vertbuf_use(cache->proc_strand_seg_buf);
- cache->strand_seg_tex = GPU_texture_create_from_vertbuf("curves_strand_seg",
- cache->proc_strand_seg_buf);
+ GPU_vertbuf_use(cache.proc_strand_seg_buf);
+ cache.strand_seg_tex = GPU_texture_create_from_vertbuf("curves_strand_seg",
+ cache.proc_strand_seg_buf);
}
-static void curves_batch_cache_ensure_procedural_final_points(ParticleHairCache *cache, int subdiv)
+static void curves_batch_cache_ensure_procedural_final_points(ParticleHairCache &cache, int subdiv)
{
/* Same format as point_tex. */
GPUVertFormat format = {0};
GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
- cache->final[subdiv].proc_buf = GPU_vertbuf_create_with_format_ex(&format,
- GPU_USAGE_DEVICE_ONLY);
+ cache.final[subdiv].proc_buf = GPU_vertbuf_create_with_format_ex(&format, GPU_USAGE_DEVICE_ONLY);
/* Create a destination buffer for the transform feedback. Sized appropriately */
/* Those are points! not line segments. */
- GPU_vertbuf_data_alloc(cache->final[subdiv].proc_buf,
- cache->final[subdiv].strands_res * cache->strands_len);
+ GPU_vertbuf_data_alloc(cache.final[subdiv].proc_buf,
+ cache.final[subdiv].strands_res * cache.strands_len);
/* Create vbo immediately to bind to texture buffer. */
- GPU_vertbuf_use(cache->final[subdiv].proc_buf);
+ GPU_vertbuf_use(cache.final[subdiv].proc_buf);
- cache->final[subdiv].proc_tex = GPU_texture_create_from_vertbuf("hair_proc",
- cache->final[subdiv].proc_buf);
+ cache.final[subdiv].proc_tex = GPU_texture_create_from_vertbuf("hair_proc",
+ cache.final[subdiv].proc_buf);
}
-static void curves_batch_cache_fill_segments_indices(Curves *curves,
+static void curves_batch_cache_fill_segments_indices(const Curves &curves,
const int res,
- GPUIndexBufBuilder *elb)
+ GPUIndexBufBuilder &elb)
{
- const int curve_size = curves->geometry.curve_size;
+ const int curves_num = curves.geometry.curve_size;
uint curr_point = 0;
- for ([[maybe_unused]] const int i : IndexRange(curve_size)) {
+ for ([[maybe_unused]] const int i : IndexRange(curves_num)) {
for (int k = 0; k < res; k++) {
- GPU_indexbuf_add_generic_vert(elb, curr_point++);
+ GPU_indexbuf_add_generic_vert(&elb, curr_point++);
}
- GPU_indexbuf_add_primitive_restart(elb);
+ GPU_indexbuf_add_primitive_restart(&elb);
}
}
-static void curves_batch_cache_ensure_procedural_indices(Curves *curves,
- ParticleHairCache *cache,
- int thickness_res,
- int subdiv)
+static void curves_batch_cache_ensure_procedural_indices(Curves &curves,
+ ParticleHairCache &cache,
+ const int thickness_res,
+ const int subdiv)
{
BLI_assert(thickness_res <= MAX_THICKRES); /* Cylinder strip not currently supported. */
- if (cache->final[subdiv].proc_hairs[thickness_res - 1] != nullptr) {
+ if (cache.final[subdiv].proc_hairs[thickness_res - 1] != nullptr) {
return;
}
- int verts_per_hair = cache->final[subdiv].strands_res * thickness_res;
+ int verts_per_curve = cache.final[subdiv].strands_res * thickness_res;
/* +1 for primitive restart */
- int element_count = (verts_per_hair + 1) * cache->strands_len;
+ int element_count = (verts_per_curve + 1) * cache.strands_len;
GPUPrimType prim_type = (thickness_res == 1) ? GPU_PRIM_LINE_STRIP : GPU_PRIM_TRI_STRIP;
static GPUVertFormat format = {0};
@@ -322,46 +317,46 @@ static void curves_batch_cache_ensure_procedural_indices(Curves *curves,
GPUIndexBufBuilder elb;
GPU_indexbuf_init_ex(&elb, prim_type, element_count, element_count);
- curves_batch_cache_fill_segments_indices(curves, verts_per_hair, &elb);
+ curves_batch_cache_fill_segments_indices(curves, verts_per_curve, elb);
- cache->final[subdiv].proc_hairs[thickness_res - 1] = GPU_batch_create_ex(
+ cache.final[subdiv].proc_hairs[thickness_res - 1] = GPU_batch_create_ex(
prim_type, vbo, GPU_indexbuf_build(&elb), GPU_BATCH_OWNS_VBO | GPU_BATCH_OWNS_INDEX);
}
-bool hair_ensure_procedural_data(Object *object,
- ParticleHairCache **r_hair_cache,
- GPUMaterial *gpu_material,
- int subdiv,
- int thickness_res)
+bool curves_ensure_procedural_data(Object *object,
+ ParticleHairCache **r_hair_cache,
+ GPUMaterial *gpu_material,
+ const int subdiv,
+ const int thickness_res)
{
bool need_ft_update = false;
- Curves *curves = static_cast<Curves *>(object->data);
+ Curves &curves = *static_cast<Curves *>(object->data);
- HairBatchCache *cache = curves_batch_cache_get(curves);
- *r_hair_cache = &cache->hair;
+ CurvesBatchCache &cache = curves_batch_cache_get(curves);
+ *r_hair_cache = &cache.hair;
const int steps = 3; /* TODO: don't hard-code? */
(*r_hair_cache)->final[subdiv].strands_res = 1 << (steps + subdiv);
/* Refreshed on combing and simulation. */
if ((*r_hair_cache)->proc_point_buf == nullptr) {
- ensure_seg_pt_count(curves, &cache->hair);
- curves_batch_cache_ensure_procedural_pos(curves, &cache->hair, gpu_material);
+ ensure_seg_pt_count(curves, cache.hair);
+ curves_batch_cache_ensure_procedural_pos(curves, cache.hair, gpu_material);
need_ft_update = true;
}
/* Refreshed if active layer or custom data changes. */
if ((*r_hair_cache)->strand_tex == nullptr) {
- curves_batch_cache_ensure_procedural_strand_data(curves, &cache->hair);
+ curves_batch_cache_ensure_procedural_strand_data(curves, cache.hair);
}
/* Refreshed only on subdiv count change. */
if ((*r_hair_cache)->final[subdiv].proc_buf == nullptr) {
- curves_batch_cache_ensure_procedural_final_points(&cache->hair, subdiv);
+ curves_batch_cache_ensure_procedural_final_points(cache.hair, subdiv);
need_ft_update = true;
}
if ((*r_hair_cache)->final[subdiv].proc_hairs[thickness_res - 1] == nullptr) {
- curves_batch_cache_ensure_procedural_indices(curves, &cache->hair, thickness_res, subdiv);
+ curves_batch_cache_ensure_procedural_indices(curves, cache.hair, thickness_res, subdiv);
}
return need_ft_update;
diff --git a/source/blender/draw/intern/draw_cache_impl_subdivision.cc b/source/blender/draw/intern/draw_cache_impl_subdivision.cc
index 8aa7ff66d65..2653035a39f 100644
--- a/source/blender/draw/intern/draw_cache_impl_subdivision.cc
+++ b/source/blender/draw/intern/draw_cache_impl_subdivision.cc
@@ -544,6 +544,7 @@ void draw_subdiv_cache_free(DRWSubdivCache *cache)
GPU_VERTBUF_DISCARD_SAFE(cache->subdiv_polygon_offset_buffer);
GPU_VERTBUF_DISCARD_SAFE(cache->extra_coarse_face_data);
MEM_SAFE_FREE(cache->subdiv_loop_subdiv_vert_index);
+ MEM_SAFE_FREE(cache->subdiv_loop_subdiv_edge_index);
MEM_SAFE_FREE(cache->subdiv_loop_poly_index);
MEM_SAFE_FREE(cache->subdiv_polygon_offset);
GPU_VERTBUF_DISCARD_SAFE(cache->subdiv_vertex_face_adjacency_offsets);
@@ -630,7 +631,10 @@ static void draw_subdiv_cache_extra_coarse_face_data_mesh(Mesh *mesh, uint32_t *
for (int i = 0; i < mesh->totpoly; i++) {
uint32_t flag = 0;
if ((mesh->mpoly[i].flag & ME_SMOOTH) != 0) {
- flag = SUBDIV_COARSE_FACE_FLAG_SMOOTH;
+ flag |= SUBDIV_COARSE_FACE_FLAG_SMOOTH;
+ }
+ if ((mesh->mpoly[i].flag & ME_FACE_SEL) != 0) {
+ flag |= SUBDIV_COARSE_FACE_FLAG_SELECT;
}
flags_data[i] = (uint)(mesh->mpoly[i].loopstart) | (flag << SUBDIV_COARSE_FACE_FLAG_OFFSET);
}
@@ -720,6 +724,7 @@ struct DRWCacheBuildingContext {
int *subdiv_loop_vert_index;
int *subdiv_loop_subdiv_vert_index;
int *subdiv_loop_edge_index;
+ int *subdiv_loop_subdiv_edge_index;
int *subdiv_loop_poly_index;
/* Temporary buffers used during traversal. */
@@ -781,6 +786,9 @@ static bool draw_subdiv_topology_info_cb(const SubdivForeachContext *foreach_con
cache->subdiv_loop_subdiv_vert_index = static_cast<int *>(
MEM_mallocN(cache->num_subdiv_loops * sizeof(int), "subdiv_loop_subdiv_vert_index"));
+ cache->subdiv_loop_subdiv_edge_index = static_cast<int *>(
+ MEM_mallocN(cache->num_subdiv_loops * sizeof(int), "subdiv_loop_subdiv_edge_index"));
+
cache->subdiv_loop_poly_index = static_cast<int *>(
MEM_mallocN(cache->num_subdiv_loops * sizeof(int), "subdiv_loop_poly_index"));
@@ -789,6 +797,7 @@ static bool draw_subdiv_topology_info_cb(const SubdivForeachContext *foreach_con
ctx->subdiv_loop_vert_index = (int *)GPU_vertbuf_get_data(cache->verts_orig_index);
ctx->subdiv_loop_edge_index = (int *)GPU_vertbuf_get_data(cache->edges_orig_index);
ctx->subdiv_loop_subdiv_vert_index = cache->subdiv_loop_subdiv_vert_index;
+ ctx->subdiv_loop_subdiv_edge_index = cache->subdiv_loop_subdiv_edge_index;
ctx->subdiv_loop_poly_index = cache->subdiv_loop_poly_index;
ctx->v_origindex = static_cast<int *>(
@@ -887,9 +896,7 @@ static void draw_subdiv_loop_cb(const SubdivForeachContext *foreach_context,
int coarse_vertex_index = ctx->vert_origindex_map[subdiv_vertex_index];
ctx->subdiv_loop_subdiv_vert_index[subdiv_loop_index] = subdiv_vertex_index;
- /* For now index the subdiv_edge_index, it will be replaced by the actual coarse edge index
- * at the end of the traversal as some edges are only then traversed. */
- ctx->subdiv_loop_edge_index[subdiv_loop_index] = subdiv_edge_index;
+ ctx->subdiv_loop_subdiv_edge_index[subdiv_loop_index] = subdiv_edge_index;
ctx->subdiv_loop_poly_index[subdiv_loop_index] = coarse_poly_index;
ctx->subdiv_loop_vert_index[subdiv_loop_index] = coarse_vertex_index;
}
@@ -915,12 +922,13 @@ static void do_subdiv_traversal(DRWCacheBuildingContext *cache_building_context,
cache_building_context->settings,
cache_building_context->coarse_mesh);
- /* Now that traversal is done, we can set up the right original indices for the loop-to-edge map.
+ /* Now that traversal is done, we can set up the right original indices for the
+ * subdiv-loop-to-coarse-edge map.
*/
for (int i = 0; i < cache_building_context->cache->num_subdiv_loops; i++) {
cache_building_context->subdiv_loop_edge_index[i] =
cache_building_context
- ->edge_origindex_map[cache_building_context->subdiv_loop_edge_index[i]];
+ ->edge_origindex_map[cache_building_context->subdiv_loop_subdiv_edge_index[i]];
}
}
diff --git a/source/blender/draw/intern/draw_common.c b/source/blender/draw/intern/draw_common.c
index c7edf003346..462ae6f7cf1 100644
--- a/source/blender/draw/intern/draw_common.c
+++ b/source/blender/draw/intern/draw_common.c
@@ -184,9 +184,10 @@ void DRW_globals_update(void)
gb->pixelFac = *DRW_viewport_pixelsize_get();
- copy_v2_v2(gb->sizeViewport, DRW_viewport_size_get());
- copy_v2_v2(gb->sizeViewportInv, gb->sizeViewport);
- invert_v2(gb->sizeViewportInv);
+ /* Deprecated, use drw_view.viewport_size instead */
+ copy_v2_v2(&gb->sizeViewport[0], DRW_viewport_size_get());
+ copy_v2_v2(&gb->sizeViewport[2], &gb->sizeViewport[0]);
+ invert_v2(&gb->sizeViewport[2]);
/* Color management. */
{
diff --git a/source/blender/draw/intern/draw_common.h b/source/blender/draw/intern/draw_common.h
index 53946c0cec5..e2dc91f64be 100644
--- a/source/blender/draw/intern/draw_common.h
+++ b/source/blender/draw/intern/draw_common.h
@@ -7,6 +7,8 @@
#pragma once
+#include "draw_common_shader_shared.h"
+
struct DRWShadingGroup;
struct FluidModifierData;
struct GPUMaterial;
@@ -16,126 +18,6 @@ struct ParticleSystem;
struct RegionView3D;
struct ViewLayer;
-#define UBO_FIRST_COLOR colorWire
-#define UBO_LAST_COLOR colorUVShadow
-
-/* Used as ubo but colors can be directly referenced as well */
-/* Keep in sync with: common_globals_lib.glsl (globalsBlock) */
-/* NOTE: Also keep all color as vec4 and between #UBO_FIRST_COLOR and #UBO_LAST_COLOR. */
-typedef struct GlobalsUboStorage {
- /* UBOs data needs to be 16 byte aligned (size of vec4) */
- float colorWire[4];
- float colorWireEdit[4];
- float colorActive[4];
- float colorSelect[4];
- float colorLibrarySelect[4];
- float colorLibrary[4];
- float colorTransform[4];
- float colorLight[4];
- float colorSpeaker[4];
- float colorCamera[4];
- float colorCameraPath[4];
- float colorEmpty[4];
- float colorVertex[4];
- float colorVertexSelect[4];
- float colorVertexUnreferenced[4];
- float colorVertexMissingData[4];
- float colorEditMeshActive[4];
- float colorEdgeSelect[4];
- float colorEdgeSeam[4];
- float colorEdgeSharp[4];
- float colorEdgeCrease[4];
- float colorEdgeBWeight[4];
- float colorEdgeFaceSelect[4];
- float colorEdgeFreestyle[4];
- float colorFace[4];
- float colorFaceSelect[4];
- float colorFaceFreestyle[4];
- float colorGpencilVertex[4];
- float colorGpencilVertexSelect[4];
- float colorNormal[4];
- float colorVNormal[4];
- float colorLNormal[4];
- float colorFaceDot[4];
- float colorSkinRoot[4];
-
- float colorDeselect[4];
- float colorOutline[4];
- float colorLightNoAlpha[4];
-
- float colorBackground[4];
- float colorBackgroundGradient[4];
- float colorCheckerPrimary[4];
- float colorCheckerSecondary[4];
- float colorClippingBorder[4];
- float colorEditMeshMiddle[4];
-
- float colorHandleFree[4];
- float colorHandleAuto[4];
- float colorHandleVect[4];
- float colorHandleAlign[4];
- float colorHandleAutoclamp[4];
- float colorHandleSelFree[4];
- float colorHandleSelAuto[4];
- float colorHandleSelVect[4];
- float colorHandleSelAlign[4];
- float colorHandleSelAutoclamp[4];
- float colorNurbUline[4];
- float colorNurbVline[4];
- float colorNurbSelUline[4];
- float colorNurbSelVline[4];
- float colorActiveSpline[4];
-
- float colorBonePose[4];
- float colorBonePoseActive[4];
- float colorBonePoseActiveUnsel[4];
- float colorBonePoseConstraint[4];
- float colorBonePoseIK[4];
- float colorBonePoseSplineIK[4];
- float colorBonePoseTarget[4];
- float colorBoneSolid[4];
- float colorBoneLocked[4];
- float colorBoneActive[4];
- float colorBoneActiveUnsel[4];
- float colorBoneSelect[4];
- float colorBoneIKLine[4];
- float colorBoneIKLineNoTarget[4];
- float colorBoneIKLineSpline[4];
-
- float colorText[4];
- float colorTextHi[4];
-
- float colorBundleSolid[4];
-
- float colorMballRadius[4];
- float colorMballRadiusSelect[4];
- float colorMballStiffness[4];
- float colorMballStiffnessSelect[4];
-
- float colorCurrentFrame[4];
-
- float colorGrid[4];
- float colorGridEmphasis[4];
- float colorGridAxisX[4];
- float colorGridAxisY[4];
- float colorGridAxisZ[4];
-
- float colorFaceBack[4];
- float colorFaceFront[4];
-
- float colorUVShadow[4];
-
- /* NOTE: Put all color before #UBO_LAST_COLOR. */
- float screenVecs[2][4]; /* Padded as vec4. */
- float sizeViewport[2], sizeViewportInv[2]; /* Packed as vec4 in GLSL. */
-
- /* Pack individual float at the end of the buffer to avoid alignment errors */
- float sizePixel, pixelFac;
- float sizeObjectCenter, sizeLightCenter, sizeLightCircle, sizeLightCircleShadow;
- float sizeVertex, sizeEdge, sizeEdgeFix, sizeFaceDot;
- float sizeChecker;
- float sizeVertexGpencil;
-} GlobalsUboStorage;
/* Keep in sync with globalsBlock in shaders */
BLI_STATIC_ASSERT_ALIGN(GlobalsUboStorage, 16)
diff --git a/source/blender/draw/intern/draw_common_shader_shared.h b/source/blender/draw/intern/draw_common_shader_shared.h
new file mode 100644
index 00000000000..ecddddded78
--- /dev/null
+++ b/source/blender/draw/intern/draw_common_shader_shared.h
@@ -0,0 +1,268 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later
+ * Copyright 2022 Blender Foundation. */
+
+/** \file
+ * \ingroup draw
+ */
+
+#ifndef GPU_SHADER
+# include "GPU_shader_shared_utils.h"
+
+typedef struct GlobalsUboStorage GlobalsUboStorage;
+#endif
+
+/* Future Plan: These globals were once shared between multiple overlay engines. But now that they
+ * have been merged into one engine, there is no reasons to keep these globals out of the overlay
+ * engine. */
+
+#define UBO_FIRST_COLOR colorWire
+#define UBO_LAST_COLOR colorUVShadow
+
+/* Used as ubo but colors can be directly referenced as well */
+/* NOTE: Also keep all color as vec4 and between #UBO_FIRST_COLOR and #UBO_LAST_COLOR. */
+struct GlobalsUboStorage {
+ /* UBOs data needs to be 16 byte aligned (size of vec4) */
+ float4 colorWire;
+ float4 colorWireEdit;
+ float4 colorActive;
+ float4 colorSelect;
+ float4 colorLibrarySelect;
+ float4 colorLibrary;
+ float4 colorTransform;
+ float4 colorLight;
+ float4 colorSpeaker;
+ float4 colorCamera;
+ float4 colorCameraPath;
+ float4 colorEmpty;
+ float4 colorVertex;
+ float4 colorVertexSelect;
+ float4 colorVertexUnreferenced;
+ float4 colorVertexMissingData;
+ float4 colorEditMeshActive;
+ float4 colorEdgeSelect;
+ float4 colorEdgeSeam;
+ float4 colorEdgeSharp;
+ float4 colorEdgeCrease;
+ float4 colorEdgeBWeight;
+ float4 colorEdgeFaceSelect;
+ float4 colorEdgeFreestyle;
+ float4 colorFace;
+ float4 colorFaceSelect;
+ float4 colorFaceFreestyle;
+ float4 colorGpencilVertex;
+ float4 colorGpencilVertexSelect;
+ float4 colorNormal;
+ float4 colorVNormal;
+ float4 colorLNormal;
+ float4 colorFaceDot;
+ float4 colorSkinRoot;
+
+ float4 colorDeselect;
+ float4 colorOutline;
+ float4 colorLightNoAlpha;
+
+ float4 colorBackground;
+ float4 colorBackgroundGradient;
+ float4 colorCheckerPrimary;
+ float4 colorCheckerSecondary;
+ float4 colorClippingBorder;
+ float4 colorEditMeshMiddle;
+
+ float4 colorHandleFree;
+ float4 colorHandleAuto;
+ float4 colorHandleVect;
+ float4 colorHandleAlign;
+ float4 colorHandleAutoclamp;
+ float4 colorHandleSelFree;
+ float4 colorHandleSelAuto;
+ float4 colorHandleSelVect;
+ float4 colorHandleSelAlign;
+ float4 colorHandleSelAutoclamp;
+ float4 colorNurbUline;
+ float4 colorNurbVline;
+ float4 colorNurbSelUline;
+ float4 colorNurbSelVline;
+ float4 colorActiveSpline;
+
+ float4 colorBonePose;
+ float4 colorBonePoseActive;
+ float4 colorBonePoseActiveUnsel;
+ float4 colorBonePoseConstraint;
+ float4 colorBonePoseIK;
+ float4 colorBonePoseSplineIK;
+ float4 colorBonePoseTarget;
+ float4 colorBoneSolid;
+ float4 colorBoneLocked;
+ float4 colorBoneActive;
+ float4 colorBoneActiveUnsel;
+ float4 colorBoneSelect;
+ float4 colorBoneIKLine;
+ float4 colorBoneIKLineNoTarget;
+ float4 colorBoneIKLineSpline;
+
+ float4 colorText;
+ float4 colorTextHi;
+
+ float4 colorBundleSolid;
+
+ float4 colorMballRadius;
+ float4 colorMballRadiusSelect;
+ float4 colorMballStiffness;
+ float4 colorMballStiffnessSelect;
+
+ float4 colorCurrentFrame;
+
+ float4 colorGrid;
+ float4 colorGridEmphasis;
+ float4 colorGridAxisX;
+ float4 colorGridAxisY;
+ float4 colorGridAxisZ;
+
+ float4 colorFaceBack;
+ float4 colorFaceFront;
+
+ float4 colorUVShadow;
+
+ /* NOTE: Put all color before #UBO_LAST_COLOR. */
+ float4 screenVecs[2]; /* Padded as vec4. */
+ float4 sizeViewport; /* Packed as vec4. */
+
+ /* Pack individual float at the end of the buffer to avoid alignment errors */
+ float sizePixel, pixelFac;
+ float sizeObjectCenter, sizeLightCenter, sizeLightCircle, sizeLightCircleShadow;
+ float sizeVertex, sizeEdge, sizeEdgeFix, sizeFaceDot;
+ float sizeChecker;
+ float sizeVertexGpencil;
+};
+BLI_STATIC_ASSERT_ALIGN(GlobalsUboStorage, 16)
+
+#ifdef GPU_SHADER
+/* Keep compatibility_with old global scope syntax. */
+/* TODO(@fclem) Mass rename and remove the camel case. */
+# define colorWire globalsBlock.colorWire
+# define colorWireEdit globalsBlock.colorWireEdit
+# define colorActive globalsBlock.colorActive
+# define colorSelect globalsBlock.colorSelect
+# define colorLibrarySelect globalsBlock.colorLibrarySelect
+# define colorLibrary globalsBlock.colorLibrary
+# define colorTransform globalsBlock.colorTransform
+# define colorLight globalsBlock.colorLight
+# define colorSpeaker globalsBlock.colorSpeaker
+# define colorCamera globalsBlock.colorCamera
+# define colorCameraPath globalsBlock.colorCameraPath
+# define colorEmpty globalsBlock.colorEmpty
+# define colorVertex globalsBlock.colorVertex
+# define colorVertexSelect globalsBlock.colorVertexSelect
+# define colorVertexUnreferenced globalsBlock.colorVertexUnreferenced
+# define colorVertexMissingData globalsBlock.colorVertexMissingData
+# define colorEditMeshActive globalsBlock.colorEditMeshActive
+# define colorEdgeSelect globalsBlock.colorEdgeSelect
+# define colorEdgeSeam globalsBlock.colorEdgeSeam
+# define colorEdgeSharp globalsBlock.colorEdgeSharp
+# define colorEdgeCrease globalsBlock.colorEdgeCrease
+# define colorEdgeBWeight globalsBlock.colorEdgeBWeight
+# define colorEdgeFaceSelect globalsBlock.colorEdgeFaceSelect
+# define colorEdgeFreestyle globalsBlock.colorEdgeFreestyle
+# define colorFace globalsBlock.colorFace
+# define colorFaceSelect globalsBlock.colorFaceSelect
+# define colorFaceFreestyle globalsBlock.colorFaceFreestyle
+# define colorGpencilVertex globalsBlock.colorGpencilVertex
+# define colorGpencilVertexSelect globalsBlock.colorGpencilVertexSelect
+# define colorNormal globalsBlock.colorNormal
+# define colorVNormal globalsBlock.colorVNormal
+# define colorLNormal globalsBlock.colorLNormal
+# define colorFaceDot globalsBlock.colorFaceDot
+# define colorSkinRoot globalsBlock.colorSkinRoot
+# define colorDeselect globalsBlock.colorDeselect
+# define colorOutline globalsBlock.colorOutline
+# define colorLightNoAlpha globalsBlock.colorLightNoAlpha
+# define colorBackground globalsBlock.colorBackground
+# define colorBackgroundGradient globalsBlock.colorBackgroundGradient
+# define colorCheckerPrimary globalsBlock.colorCheckerPrimary
+# define colorCheckerSecondary globalsBlock.colorCheckerSecondary
+# define colorClippingBorder globalsBlock.colorClippingBorder
+# define colorEditMeshMiddle globalsBlock.colorEditMeshMiddle
+# define colorHandleFree globalsBlock.colorHandleFree
+# define colorHandleAuto globalsBlock.colorHandleAuto
+# define colorHandleVect globalsBlock.colorHandleVect
+# define colorHandleAlign globalsBlock.colorHandleAlign
+# define colorHandleAutoclamp globalsBlock.colorHandleAutoclamp
+# define colorHandleSelFree globalsBlock.colorHandleSelFree
+# define colorHandleSelAuto globalsBlock.colorHandleSelAuto
+# define colorHandleSelVect globalsBlock.colorHandleSelVect
+# define colorHandleSelAlign globalsBlock.colorHandleSelAlign
+# define colorHandleSelAutoclamp globalsBlock.colorHandleSelAutoclamp
+# define colorNurbUline globalsBlock.colorNurbUline
+# define colorNurbVline globalsBlock.colorNurbVline
+# define colorNurbSelUline globalsBlock.colorNurbSelUline
+# define colorNurbSelVline globalsBlock.colorNurbSelVline
+# define colorActiveSpline globalsBlock.colorActiveSpline
+# define colorBonePose globalsBlock.colorBonePose
+# define colorBonePoseActive globalsBlock.colorBonePoseActive
+# define colorBonePoseActiveUnsel globalsBlock.colorBonePoseActiveUnsel
+# define colorBonePoseConstraint globalsBlock.colorBonePoseConstraint
+# define colorBonePoseIK globalsBlock.colorBonePoseIK
+# define colorBonePoseSplineIK globalsBlock.colorBonePoseSplineIK
+# define colorBonePoseTarget globalsBlock.colorBonePoseTarget
+# define colorBoneSolid globalsBlock.colorBoneSolid
+# define colorBoneLocked globalsBlock.colorBoneLocked
+# define colorBoneActive globalsBlock.colorBoneActive
+# define colorBoneActiveUnsel globalsBlock.colorBoneActiveUnsel
+# define colorBoneSelect globalsBlock.colorBoneSelect
+# define colorBoneIKLine globalsBlock.colorBoneIKLine
+# define colorBoneIKLineNoTarget globalsBlock.colorBoneIKLineNoTarget
+# define colorBoneIKLineSpline globalsBlock.colorBoneIKLineSpline
+# define colorText globalsBlock.colorText
+# define colorTextHi globalsBlock.colorTextHi
+# define colorBundleSolid globalsBlock.colorBundleSolid
+# define colorMballRadius globalsBlock.colorMballRadius
+# define colorMballRadiusSelect globalsBlock.colorMballRadiusSelect
+# define colorMballStiffness globalsBlock.colorMballStiffness
+# define colorMballStiffnessSelect globalsBlock.colorMballStiffnessSelect
+# define colorCurrentFrame globalsBlock.colorCurrentFrame
+# define colorGrid globalsBlock.colorGrid
+# define colorGridEmphasis globalsBlock.colorGridEmphasis
+# define colorGridAxisX globalsBlock.colorGridAxisX
+# define colorGridAxisY globalsBlock.colorGridAxisY
+# define colorGridAxisZ globalsBlock.colorGridAxisZ
+# define colorFaceBack globalsBlock.colorFaceBack
+# define colorFaceFront globalsBlock.colorFaceFront
+# define colorUVShadow globalsBlock.colorUVShadow
+# define screenVecs globalsBlock.screenVecs
+# define sizeViewport globalsBlock.sizeViewport.xy
+# define sizePixel globalsBlock.sizePixel
+# define pixelFac globalsBlock.pixelFac
+# define sizeObjectCenter globalsBlock.sizeObjectCenter
+# define sizeLightCenter globalsBlock.sizeLightCenter
+# define sizeLightCircle globalsBlock.sizeLightCircle
+# define sizeLightCircleShadow globalsBlock.sizeLightCircleShadow
+# define sizeVertex globalsBlock.sizeVertex
+# define sizeEdge globalsBlock.sizeEdge
+# define sizeEdgeFix globalsBlock.sizeEdgeFix
+# define sizeFaceDot globalsBlock.sizeFaceDot
+# define sizeChecker globalsBlock.sizeChecker
+# define sizeVertexGpencil globalsBlock.sizeVertexGpencil
+#endif
+
+/* See: 'draw_cache_impl.h' for matching includes. */
+#define VERT_GPENCIL_BEZT_HANDLE (1 << 30)
+/* data[0] (1st byte flags) */
+#define FACE_ACTIVE (1 << 0)
+#define FACE_SELECTED (1 << 1)
+#define FACE_FREESTYLE (1 << 2)
+#define VERT_UV_SELECT (1 << 3)
+#define VERT_UV_PINNED (1 << 4)
+#define EDGE_UV_SELECT (1 << 5)
+#define FACE_UV_ACTIVE (1 << 6)
+#define FACE_UV_SELECT (1 << 7)
+/* data[1] (2st byte flags) */
+#define VERT_ACTIVE (1 << 0)
+#define VERT_SELECTED (1 << 1)
+#define VERT_SELECTED_BEZT_HANDLE (1 << 2)
+#define EDGE_ACTIVE (1 << 3)
+#define EDGE_SELECTED (1 << 4)
+#define EDGE_SEAM (1 << 5)
+#define EDGE_SHARP (1 << 6)
+#define EDGE_FREESTYLE (1 << 7)
+
+#define COMMON_GLOBALS_LIB
diff --git a/source/blender/draw/intern/draw_hair.c b/source/blender/draw/intern/draw_hair.c
index 7e2ab2c6193..e06df334d23 100644
--- a/source/blender/draw/intern/draw_hair.c
+++ b/source/blender/draw/intern/draw_hair.c
@@ -172,8 +172,8 @@ static ParticleHairCache *drw_hair_particle_cache_get(Object *object,
object, psys, md, &cache, gpu_material, subdiv, thickness_res);
}
else {
- /* New hair object. */
- update = hair_ensure_procedural_data(object, &cache, gpu_material, subdiv, thickness_res);
+ /* New curves object. */
+ update = curves_ensure_procedural_data(object, &cache, gpu_material, subdiv, thickness_res);
}
if (update) {
@@ -230,7 +230,7 @@ void DRW_hair_duplimat_get(Object *object,
}
}
else {
- /* New hair object. */
+ /* New curves object. */
copy_m4_m4(dupli_mat, object->obmat);
}
}
@@ -291,7 +291,7 @@ DRWShadingGroup *DRW_shgroup_hair_create_sub(Object *object,
hair_close_tip = (part->shape_flag & PART_SHAPE_CLOSE_TIP) != 0;
}
else {
- /* TODO: implement for new hair object. */
+ /* TODO: implement for new curves object. */
hair_rad_shape = 1.0f;
hair_rad_root = 0.005f;
hair_rad_tip = 0.0f;
@@ -305,7 +305,7 @@ DRWShadingGroup *DRW_shgroup_hair_create_sub(Object *object,
DRW_shgroup_uniform_int(shgrp, "hairStrandsRes", &hair_cache->final[subdiv].strands_res, 1);
DRW_shgroup_uniform_int_copy(shgrp, "hairThicknessRes", thickness_res);
DRW_shgroup_uniform_float_copy(shgrp, "hairRadShape", hair_rad_shape);
- DRW_shgroup_uniform_vec4_array_copy(shgrp, "hairDupliMatrix", dupli_mat, 4);
+ DRW_shgroup_uniform_mat4_copy(shgrp, "hairDupliMatrix", dupli_mat);
DRW_shgroup_uniform_float_copy(shgrp, "hairRadRoot", hair_rad_root);
DRW_shgroup_uniform_float_copy(shgrp, "hairRadTip", hair_rad_tip);
DRW_shgroup_uniform_bool_copy(shgrp, "hairCloseTip", hair_close_tip);
diff --git a/source/blender/draw/intern/draw_hair_private.h b/source/blender/draw/intern/draw_hair_private.h
index 98a55d76373..58e8609106b 100644
--- a/source/blender/draw/intern/draw_hair_private.h
+++ b/source/blender/draw/intern/draw_hair_private.h
@@ -91,11 +91,11 @@ bool particles_ensure_procedural_data(struct Object *object,
/**
* Ensure all textures and buffers needed for GPU accelerated drawing.
*/
-bool hair_ensure_procedural_data(struct Object *object,
- struct ParticleHairCache **r_hair_cache,
- struct GPUMaterial *gpu_material,
- int subdiv,
- int thickness_res);
+bool curves_ensure_procedural_data(struct Object *object,
+ struct ParticleHairCache **r_hair_cache,
+ struct GPUMaterial *gpu_material,
+ int subdiv,
+ int thickness_res);
#ifdef __cplusplus
}
diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c
index 39ae01697a1..75c27937f25 100644
--- a/source/blender/draw/intern/draw_manager.c
+++ b/source/blender/draw/intern/draw_manager.c
@@ -55,6 +55,7 @@
#include "GPU_framebuffer.h"
#include "GPU_immediate.h"
#include "GPU_matrix.h"
+#include "GPU_platform.h"
#include "GPU_shader_shared.h"
#include "GPU_state.h"
#include "GPU_uniform_buffer.h"
@@ -1706,7 +1707,9 @@ void DRW_draw_render_loop_ex(struct Depsgraph *depsgraph,
drw_engines_draw_scene();
/* Fix 3D view "lagging" on APPLE and WIN32+NVIDIA. (See T56996, T61474) */
- GPU_flush();
+ if (GPU_type_matches_ex(GPU_DEVICE_ANY, GPU_OS_ANY, GPU_DRIVER_ANY, GPU_BACKEND_OPENGL)) {
+ GPU_flush();
+ }
DRW_stats_reset();
@@ -1938,6 +1941,9 @@ void DRW_render_to_image(RenderEngine *engine, struct Depsgraph *depsgraph)
};
drw_context_state_init();
+ /* Begin GPU workload Boundary */
+ GPU_render_begin();
+
const int size[2] = {engine->resolution_x, engine->resolution_y};
drw_manager_init(&DST, NULL, size);
@@ -1993,6 +1999,9 @@ void DRW_render_to_image(RenderEngine *engine, struct Depsgraph *depsgraph)
/* Reset state after drawing */
DRW_state_reset();
+
+ /* End GPU workload Boundary */
+ GPU_render_end();
}
void DRW_render_object_iter(
@@ -2072,7 +2081,10 @@ void DRW_custom_pipeline(DrawEngineType *draw_engine_type,
* resources as the main thread (viewport) may lead to data
* races and undefined behavior on certain drivers. Using
* GPU_finish to sync seems to fix the issue. (see T62997) */
- GPU_finish();
+ eGPUBackendType type = GPU_backend_get_type();
+ if (type == GPU_BACKEND_OPENGL) {
+ GPU_finish();
+ }
drw_manager_exit(&DST);
}
@@ -2173,7 +2185,9 @@ void DRW_draw_render_loop_2d_ex(struct Depsgraph *depsgraph,
drw_engines_draw_scene();
/* Fix 3D view being "laggy" on macos and win+nvidia. (See T56996, T61474) */
- GPU_flush();
+ if (GPU_type_matches_ex(GPU_DEVICE_ANY, GPU_OS_ANY, GPU_DRIVER_ANY, GPU_BACKEND_OPENGL)) {
+ GPU_flush();
+ }
if (DST.draw_ctx.evil_C) {
DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get();
@@ -3094,6 +3108,7 @@ void DRW_opengl_context_enable_ex(bool UNUSED(restore))
* This shall remain in effect until immediate mode supports
* multiple threads. */
BLI_ticket_mutex_lock(DST.gl_context_mutex);
+ GPU_render_begin();
WM_opengl_context_activate(DST.gl_context);
GPU_context_active_set(DST.gpu_context);
}
@@ -3105,7 +3120,9 @@ void DRW_opengl_context_disable_ex(bool restore)
#ifdef __APPLE__
/* Need to flush before disabling draw context, otherwise it does not
* always finish drawing and viewport can be empty or partially drawn */
- GPU_flush();
+ if (GPU_type_matches_ex(GPU_DEVICE_ANY, GPU_OS_MAC, GPU_DRIVER_ANY, GPU_BACKEND_OPENGL)) {
+ GPU_flush();
+ }
#endif
if (BLI_thread_is_main() && restore) {
@@ -3116,6 +3133,10 @@ void DRW_opengl_context_disable_ex(bool restore)
GPU_context_active_set(NULL);
}
+ /* Render boundaries are opened and closed here as this may be
+ * called outside of an existing render loop. */
+ GPU_render_end();
+
BLI_ticket_mutex_unlock(DST.gl_context_mutex);
}
}
diff --git a/source/blender/draw/intern/draw_manager_data.c b/source/blender/draw/intern/draw_manager_data.c
index b01c901c77f..8c7cd6d1648 100644
--- a/source/blender/draw/intern/draw_manager_data.c
+++ b/source/blender/draw/intern/draw_manager_data.c
@@ -485,10 +485,9 @@ void DRW_shgroup_uniform_vec4_copy(DRWShadingGroup *shgroup, const char *name, c
drw_shgroup_uniform(shgroup, name, DRW_UNIFORM_FLOAT_COPY, value, 4, 1);
}
-void DRW_shgroup_uniform_vec4_array_copy(DRWShadingGroup *shgroup,
- const char *name,
- const float (*value)[4],
- int arraysize)
+void DRW_shgroup_uniform_mat4_copy(DRWShadingGroup *shgroup,
+ const char *name,
+ const float (*value)[4])
{
int location = GPU_shader_get_uniform(shgroup->shader, name);
@@ -498,9 +497,12 @@ void DRW_shgroup_uniform_vec4_array_copy(DRWShadingGroup *shgroup,
return;
}
- for (int i = 0; i < arraysize; i++) {
- drw_shgroup_uniform_create_ex(
- shgroup, location + i, DRW_UNIFORM_FLOAT_COPY, &value[i], 0, 4, 1);
+ /* Each array element stored as an individual entry in the uniform list.
+ * All entries from the same array share the same base location,
+ * and array-size used to determine the number of elements
+ * copied in draw_update_uniforms. */
+ for (int i = 0; i < 4; i++) {
+ drw_shgroup_uniform_create_ex(shgroup, location, DRW_UNIFORM_FLOAT_COPY, &value[i], 0, 4, 4);
}
}
@@ -612,7 +614,7 @@ static void drw_call_obinfos_init(DRWObjectInfos *ob_infos, Object *ob)
drw_call_calc_orco(ob, ob_infos->orcotexfac);
/* Random float value. */
uint random = (DST.dupli_source) ?
- DST.dupli_source->random_id :
+ DST.dupli_source->random_id :
/* TODO(fclem): this is rather costly to do at runtime. Maybe we can
* put it in ob->runtime and make depsgraph ensure it is up to date. */
BLI_hash_int_2d(BLI_hash_string(ob->id.name + 2), 0);
@@ -636,7 +638,7 @@ static void drw_call_obinfos_init(DRWObjectInfos *ob_infos, Object *ob)
static void drw_call_culling_init(DRWCullingState *cull, Object *ob)
{
- BoundBox *bbox;
+ const BoundBox *bbox;
if (ob != NULL && (bbox = BKE_object_boundbox_get(ob))) {
float corner[3];
/* Get BoundSphere center and radius from the BoundBox. */
diff --git a/source/blender/draw/intern/draw_manager_exec.c b/source/blender/draw/intern/draw_manager_exec.c
index 7d6ce51ff35..2c5b02f88a9 100644
--- a/source/blender/draw/intern/draw_manager_exec.c
+++ b/source/blender/draw/intern/draw_manager_exec.c
@@ -584,21 +584,60 @@ static void draw_update_uniforms(DRWShadingGroup *shgroup,
DRWCommandsState *state,
bool *use_tfeedback)
{
+#define MAX_UNIFORM_STACK_SIZE 64
+
+ /* Uniform array elements stored as separate entries. We need to batch these together */
+ int array_uniform_loc = -1;
+ int array_index = 0;
+ float mat4_stack[4 * 4];
+
+ /* Loop through uniforms in reverse order. */
for (DRWUniformChunk *unichunk = shgroup->uniforms; unichunk; unichunk = unichunk->next) {
- DRWUniform *uni = unichunk->uniforms;
- for (int i = 0; i < unichunk->uniform_used; i++, uni++) {
+ DRWUniform *uni = unichunk->uniforms + unichunk->uniform_used - 1;
+
+ for (int i = 0; i < unichunk->uniform_used; i++, uni--) {
+ /* For uniform array copies, copy per-array-element data into local buffer before upload. */
+ if (uni->arraysize > 1 && uni->type == DRW_UNIFORM_FLOAT_COPY) {
+ /* Only written for mat4 copy for now and is not meant to become generalized. */
+ /* TODO(@fclem): Use UBOs/SSBOs instead of inline mat4 copies. */
+ BLI_assert(uni->arraysize == 4 && uni->length == 4);
+ /* Begin copying uniform array. */
+ if (array_uniform_loc == -1) {
+ array_uniform_loc = uni->location;
+ array_index = uni->arraysize * uni->length;
+ }
+ /* Debug check same array loc. */
+ BLI_assert(array_uniform_loc > -1 && array_uniform_loc == uni->location);
+ /* Copy array element data to local buffer. */
+ array_index -= uni->length;
+ memcpy(&mat4_stack[array_index], uni->fvalue, sizeof(float) * uni->length);
+ /* Flush array data to shader. */
+ if (array_index <= 0) {
+ GPU_shader_uniform_vector(shgroup->shader, uni->location, 16, 1, mat4_stack);
+ array_uniform_loc = -1;
+ }
+ continue;
+ }
+
+ /* Handle standard cases. */
switch (uni->type) {
case DRW_UNIFORM_INT_COPY:
- GPU_shader_uniform_vector_int(
- shgroup->shader, uni->location, uni->length, uni->arraysize, uni->ivalue);
+ BLI_assert(uni->arraysize == 1);
+ if (uni->arraysize == 1) {
+ GPU_shader_uniform_vector_int(
+ shgroup->shader, uni->location, uni->length, uni->arraysize, uni->ivalue);
+ }
break;
case DRW_UNIFORM_INT:
GPU_shader_uniform_vector_int(
shgroup->shader, uni->location, uni->length, uni->arraysize, uni->pvalue);
break;
case DRW_UNIFORM_FLOAT_COPY:
- GPU_shader_uniform_vector(
- shgroup->shader, uni->location, uni->length, uni->arraysize, uni->fvalue);
+ BLI_assert(uni->arraysize == 1);
+ if (uni->arraysize == 1) {
+ GPU_shader_uniform_vector(
+ shgroup->shader, uni->location, uni->length, uni->arraysize, uni->fvalue);
+ }
break;
case DRW_UNIFORM_FLOAT:
GPU_shader_uniform_vector(
@@ -673,6 +712,10 @@ static void draw_update_uniforms(DRWShadingGroup *shgroup,
}
}
}
+ /* Ensure uniform arrays copied. */
+ BLI_assert(array_index == 0);
+ BLI_assert(array_uniform_loc == -1);
+ UNUSED_VARS_NDEBUG(array_uniform_loc);
}
BLI_INLINE void draw_select_buffer(DRWShadingGroup *shgroup,
diff --git a/source/blender/draw/intern/draw_manager_shader.c b/source/blender/draw/intern/draw_manager_shader.c
index 618d2f46e91..1936aa599ff 100644
--- a/source/blender/draw/intern/draw_manager_shader.c
+++ b/source/blender/draw/intern/draw_manager_shader.c
@@ -91,6 +91,7 @@ static void drw_deferred_shader_compilation_exec(
short *do_update,
float *progress)
{
+ GPU_render_begin();
DRWShaderCompiler *comp = (DRWShaderCompiler *)custom_data;
void *gl_context = comp->gl_context;
GPUContext *gpu_context = comp->gpu_context;
@@ -138,7 +139,9 @@ static void drw_deferred_shader_compilation_exec(
*progress = (float)comp->shaders_done / (float)total;
*do_update = true;
- GPU_flush();
+ if (GPU_type_matches_ex(GPU_DEVICE_ANY, GPU_OS_ANY, GPU_DRIVER_ANY, GPU_BACKEND_OPENGL)) {
+ GPU_flush();
+ }
BLI_mutex_unlock(&comp->compilation_lock);
BLI_spin_lock(&comp->list_lock);
@@ -157,6 +160,7 @@ static void drw_deferred_shader_compilation_exec(
if (use_main_context_workaround) {
GPU_context_main_unlock();
}
+ GPU_render_end();
}
static void drw_deferred_shader_compilation_free(void *custom_data)
diff --git a/source/blender/draw/intern/draw_subdivision.h b/source/blender/draw/intern/draw_subdivision.h
index 41d177a644a..8d7bc3dc495 100644
--- a/source/blender/draw/intern/draw_subdivision.h
+++ b/source/blender/draw/intern/draw_subdivision.h
@@ -130,6 +130,8 @@ typedef struct DRWSubdivCache {
/* Maps subdivision loop to subdivided vertex index. */
int *subdiv_loop_subdiv_vert_index;
+ /* Maps subdivision loop to subdivided edge index. */
+ int *subdiv_loop_subdiv_edge_index;
/* Maps subdivision loop to original coarse poly index. */
int *subdiv_loop_poly_index;
diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_lines_paint_mask.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_lines_paint_mask.cc
index 9d799feabc6..286c7ea9c43 100644
--- a/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_lines_paint_mask.cc
+++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_lines_paint_mask.cc
@@ -11,6 +11,7 @@
#include "MEM_guardedalloc.h"
+#include "draw_subdivision.h"
#include "extract_mesh.h"
namespace blender::draw {
@@ -87,12 +88,88 @@ static void extract_lines_paint_mask_finish(const MeshRenderData *UNUSED(mr),
MEM_freeN(data->select_map);
}
+static void extract_lines_paint_mask_init_subdiv(const DRWSubdivCache *subdiv_cache,
+ const MeshRenderData *mr,
+ MeshBatchCache *UNUSED(cache),
+ void *UNUSED(buf),
+ void *tls_data)
+{
+ MeshExtract_LinePaintMask_Data *data = static_cast<MeshExtract_LinePaintMask_Data *>(tls_data);
+ data->select_map = BLI_BITMAP_NEW(mr->edge_len, __func__);
+ GPU_indexbuf_init(&data->elb,
+ GPU_PRIM_LINES,
+ subdiv_cache->num_subdiv_edges,
+ subdiv_cache->num_subdiv_loops * 2);
+}
+
+static void extract_lines_paint_mask_iter_subdiv_mesh(const DRWSubdivCache *subdiv_cache,
+ const MeshRenderData *mr,
+ void *_data,
+ uint subdiv_quad_index,
+ const MPoly *coarse_quad)
+{
+ MeshExtract_LinePaintMask_Data *data = static_cast<MeshExtract_LinePaintMask_Data *>(_data);
+ int *subdiv_loop_edge_index = (int *)GPU_vertbuf_get_data(subdiv_cache->edges_orig_index);
+ int *subdiv_loop_subdiv_edge_index = subdiv_cache->subdiv_loop_subdiv_edge_index;
+
+ uint start_loop_idx = subdiv_quad_index * 4;
+ uint end_loop_idx = (subdiv_quad_index + 1) * 4;
+ for (uint loop_idx = start_loop_idx; loop_idx < end_loop_idx; loop_idx++) {
+ const uint coarse_edge_index = (uint)subdiv_loop_edge_index[loop_idx];
+ const uint subdiv_edge_index = (uint)subdiv_loop_subdiv_edge_index[loop_idx];
+
+ if (coarse_edge_index == -1u) {
+ GPU_indexbuf_set_line_restart(&data->elb, subdiv_edge_index);
+ }
+ else {
+ const MEdge *me = &mr->medge[coarse_edge_index];
+ if (!((mr->use_hide && (me->flag & ME_HIDE)) ||
+ ((mr->extract_type == MR_EXTRACT_MAPPED) && (mr->e_origindex) &&
+ (mr->e_origindex[coarse_edge_index] == ORIGINDEX_NONE)))) {
+ const uint ml_index_other = (loop_idx == end_loop_idx) ? start_loop_idx : loop_idx + 1;
+ if (coarse_quad->flag & ME_FACE_SEL) {
+ if (BLI_BITMAP_TEST_AND_SET_ATOMIC(data->select_map, coarse_edge_index)) {
+ /* Hide edge as it has more than 2 selected loop. */
+ GPU_indexbuf_set_line_restart(&data->elb, subdiv_edge_index);
+ }
+ else {
+ /* First selected loop. Set edge visible, overwriting any unselected loop. */
+ GPU_indexbuf_set_line_verts(&data->elb, subdiv_edge_index, loop_idx, ml_index_other);
+ }
+ }
+ else {
+ /* Set these unselected loop only if this edge has no other selected loop. */
+ if (!BLI_BITMAP_TEST(data->select_map, coarse_edge_index)) {
+ GPU_indexbuf_set_line_verts(&data->elb, subdiv_edge_index, loop_idx, ml_index_other);
+ }
+ }
+ }
+ else {
+ GPU_indexbuf_set_line_restart(&data->elb, subdiv_edge_index);
+ }
+ }
+ }
+}
+
+static void extract_lines_paint_mask_finish_subdiv(
+ const struct DRWSubdivCache *UNUSED(subdiv_cache),
+ const MeshRenderData *mr,
+ struct MeshBatchCache *cache,
+ void *buf,
+ void *_data)
+{
+ extract_lines_paint_mask_finish(mr, cache, buf, _data);
+}
+
constexpr MeshExtract create_extractor_lines_paint_mask()
{
MeshExtract extractor = {nullptr};
extractor.init = extract_lines_paint_mask_init;
extractor.iter_poly_mesh = extract_lines_paint_mask_iter_poly_mesh;
extractor.finish = extract_lines_paint_mask_finish;
+ extractor.init_subdiv = extract_lines_paint_mask_init_subdiv;
+ extractor.iter_subdiv_mesh = extract_lines_paint_mask_iter_subdiv_mesh;
+ extractor.finish_subdiv = extract_lines_paint_mask_finish_subdiv;
extractor.data_type = MR_DATA_NONE;
extractor.data_size = sizeof(MeshExtract_LinePaintMask_Data);
extractor.use_threading = false;
diff --git a/source/blender/draw/intern/shaders/common_colormanagement_lib.glsl b/source/blender/draw/intern/shaders/common_colormanagement_lib.glsl
index 45f711296f3..92d13c6d48b 100644
--- a/source/blender/draw/intern/shaders/common_colormanagement_lib.glsl
+++ b/source/blender/draw/intern/shaders/common_colormanagement_lib.glsl
@@ -12,19 +12,19 @@ vec4 texture_read_as_linearrgb(sampler2D tex, bool premultiplied, vec2 co)
{
/* By convention image textures return scene linear colors, but
* overlays still assume srgb. */
- vec4 color = texture(tex, co);
+ vec4 col = texture(tex, co);
/* Unpremultiply if stored multiplied, since straight alpha is expected by shaders. */
- if (premultiplied && !(color.a == 0.0 || color.a == 1.0)) {
- color.rgb = color.rgb / color.a;
+ if (premultiplied && !(col.a == 0.0 || col.a == 1.0)) {
+ col.rgb = col.rgb / col.a;
}
- return color;
+ return col;
}
vec4 texture_read_as_srgb(sampler2D tex, bool premultiplied, vec2 co)
{
- vec4 color = texture_read_as_linearrgb(tex, premultiplied, co);
- color.r = linearrgb_to_srgb(color.r);
- color.g = linearrgb_to_srgb(color.g);
- color.b = linearrgb_to_srgb(color.b);
- return color;
+ vec4 col = texture_read_as_linearrgb(tex, premultiplied, co);
+ col.r = linearrgb_to_srgb(col.r);
+ col.g = linearrgb_to_srgb(col.g);
+ col.b = linearrgb_to_srgb(col.b);
+ return col;
}
diff --git a/source/blender/draw/intern/shaders/common_gpencil_lib.glsl b/source/blender/draw/intern/shaders/common_gpencil_lib.glsl
index 9e3c219a30b..0610bc4e57d 100644
--- a/source/blender/draw/intern/shaders/common_gpencil_lib.glsl
+++ b/source/blender/draw/intern/shaders/common_gpencil_lib.glsl
@@ -81,7 +81,7 @@ float gpencil_stroke_thickness_modulate(float thickness, vec4 ndc_pos, vec4 view
float gpencil_clamp_small_stroke_thickness(float thickness, vec4 ndc_pos)
{
/* To avoid aliasing artifacts, we clamp the line thickness and
- * reduce its opacity in the fragment shader.*/
+ * reduce its opacity in the fragment shader. */
float min_thickness = ndc_pos.w * 1.3;
thickness = max(min_thickness, thickness);
@@ -169,7 +169,7 @@ vec4 gpencil_vertex(ivec4 ma,
if (GPENCIL_IS_STROKE_VERTEX) {
bool is_dot = flag_test(material_flags, GP_STROKE_ALIGNMENT);
- bool is_squares = !flag_test(material_flags, GP_STROKE_ALIGNMENT);
+ bool is_squares = !flag_test(material_flags, GP_STROKE_DOTS);
/* Special Case. Stroke with single vert are rendered as dots. Do not discard them. */
if (!is_dot && ma.x == -1 && ma2.x == -1) {
diff --git a/source/blender/draw/intern/shaders/common_hair_lib.glsl b/source/blender/draw/intern/shaders/common_hair_lib.glsl
index 7f94b7ea1c1..6a8f1132e1b 100644
--- a/source/blender/draw/intern/shaders/common_hair_lib.glsl
+++ b/source/blender/draw/intern/shaders/common_hair_lib.glsl
@@ -29,7 +29,7 @@ uniform float hairRadTip = 0.0;
uniform float hairRadShape = 0.5;
uniform bool hairCloseTip = true;
-uniform vec4 hairDupliMatrix[4];
+uniform mat4 hairDupliMatrix;
/* Strand batch offset when used in compute shaders. */
uniform int hairStrandOffset = 0;
@@ -192,9 +192,7 @@ void hair_get_pos_tan_binor_time(bool is_persp,
wtan = wpos - texelFetch(hairPointBuffer, id - 1).point_position;
}
- mat4 obmat = mat4(
- hairDupliMatrix[0], hairDupliMatrix[1], hairDupliMatrix[2], hairDupliMatrix[3]);
-
+ mat4 obmat = hairDupliMatrix;
wpos = (obmat * vec4(wpos, 1.0)).xyz;
wtan = -normalize(mat3(obmat) * wtan);
diff --git a/source/blender/draw/intern/shaders/common_subdiv_lib.glsl b/source/blender/draw/intern/shaders/common_subdiv_lib.glsl
index 5d71c5e4bb8..ce324249446 100644
--- a/source/blender/draw/intern/shaders/common_subdiv_lib.glsl
+++ b/source/blender/draw/intern/shaders/common_subdiv_lib.glsl
@@ -107,6 +107,10 @@ struct PosNorLoop {
float flag;
};
+struct LoopNormal {
+ float nx, ny, nz, flag;
+};
+
vec3 get_vertex_pos(PosNorLoop vertex_data)
{
return vec3(vertex_data.x, vertex_data.y, vertex_data.z);
@@ -117,6 +121,16 @@ vec3 get_vertex_nor(PosNorLoop vertex_data)
return vec3(vertex_data.nx, vertex_data.ny, vertex_data.nz);
}
+LoopNormal get_normal_and_flag(PosNorLoop vertex_data)
+{
+ LoopNormal loop_nor;
+ loop_nor.nx = vertex_data.nx;
+ loop_nor.ny = vertex_data.ny;
+ loop_nor.nz = vertex_data.nz;
+ loop_nor.flag = vertex_data.flag;
+ return loop_nor;
+}
+
void set_vertex_pos(inout PosNorLoop vertex_data, vec3 pos)
{
vertex_data.x = pos.x;
diff --git a/source/blender/draw/intern/shaders/common_subdiv_vbo_lnor_comp.glsl b/source/blender/draw/intern/shaders/common_subdiv_vbo_lnor_comp.glsl
index b7e04e240fb..b7bcfd2d369 100644
--- a/source/blender/draw/intern/shaders/common_subdiv_vbo_lnor_comp.glsl
+++ b/source/blender/draw/intern/shaders/common_subdiv_vbo_lnor_comp.glsl
@@ -13,9 +13,14 @@ layout(std430, binding = 2) readonly buffer extraCoarseFaceData
layout(std430, binding = 3) writeonly buffer outputLoopNormals
{
- vec3 output_lnor[];
+ LoopNormal output_lnor[];
};
+bool is_face_selected(uint coarse_quad_index)
+{
+ return (extra_coarse_face_data[coarse_quad_index] & coarse_face_select_mask) != 0;
+}
+
void main()
{
/* We execute for each quad. */
@@ -34,7 +39,7 @@ void main()
/* Face is smooth, use vertex normals. */
for (int i = 0; i < 4; i++) {
PosNorLoop pos_nor_loop = pos_nor[start_loop_index + i];
- output_lnor[start_loop_index + i] = get_vertex_nor(pos_nor_loop);
+ output_lnor[start_loop_index + i] = get_normal_and_flag(pos_nor_loop);
}
}
else {
@@ -50,8 +55,19 @@ void main()
add_newell_cross_v3_v3v3(face_normal, v3, v0);
face_normal = normalize(face_normal);
+
+ LoopNormal loop_normal;
+ loop_normal.nx = face_normal.x;
+ loop_normal.ny = face_normal.y;
+ loop_normal.nz = face_normal.z;
+ loop_normal.flag = 0.0;
+
+ if (is_face_selected(coarse_quad_index)) {
+ loop_normal.flag = 1.0;
+ }
+
for (int i = 0; i < 4; i++) {
- output_lnor[start_loop_index + i] = face_normal;
+ output_lnor[start_loop_index + i] = loop_normal;
}
}
}
diff --git a/source/blender/draw/intern/shaders/common_view_clipping_lib.glsl b/source/blender/draw/intern/shaders/common_view_clipping_lib.glsl
index d55808c42d2..bae818cf9f3 100644
--- a/source/blender/draw/intern/shaders/common_view_clipping_lib.glsl
+++ b/source/blender/draw/intern/shaders/common_view_clipping_lib.glsl
@@ -6,13 +6,13 @@
void view_clipping_distances(vec3 wpos)
{
# ifdef USE_WORLD_CLIP_PLANES
- vec4 pos = vec4(wpos, 1.0);
- gl_ClipDistance[0] = dot(drw_view.clip_planes[0], pos);
- gl_ClipDistance[1] = dot(drw_view.clip_planes[1], pos);
- gl_ClipDistance[2] = dot(drw_view.clip_planes[2], pos);
- gl_ClipDistance[3] = dot(drw_view.clip_planes[3], pos);
- gl_ClipDistance[4] = dot(drw_view.clip_planes[4], pos);
- gl_ClipDistance[5] = dot(drw_view.clip_planes[5], pos);
+ vec4 pos_4d = vec4(wpos, 1.0);
+ gl_ClipDistance[0] = dot(drw_view.clip_planes[0], pos_4d);
+ gl_ClipDistance[1] = dot(drw_view.clip_planes[1], pos_4d);
+ gl_ClipDistance[2] = dot(drw_view.clip_planes[2], pos_4d);
+ gl_ClipDistance[3] = dot(drw_view.clip_planes[3], pos_4d);
+ gl_ClipDistance[4] = dot(drw_view.clip_planes[4], pos_4d);
+ gl_ClipDistance[5] = dot(drw_view.clip_planes[5], pos_4d);
# endif
}
diff --git a/source/blender/draw/intern/shaders/common_view_lib.glsl b/source/blender/draw/intern/shaders/common_view_lib.glsl
index 6c58752c8bb..a2b8cb4bbd6 100644
--- a/source/blender/draw/intern/shaders/common_view_lib.glsl
+++ b/source/blender/draw/intern/shaders/common_view_lib.glsl
@@ -47,6 +47,7 @@ layout(std140) uniform viewBlock
#endif
#ifdef COMMON_GLOBALS_LIB
+/* TODO move to overlay engine. */
float mul_project_m4_v3_zfac(in vec3 co)
{
return pixelFac * ((ViewProjectionMatrix[0][3] * co.x) + (ViewProjectionMatrix[1][3] * co.y) +
diff --git a/source/blender/draw/intern/shaders/draw_hair_refine_info.hh b/source/blender/draw/intern/shaders/draw_hair_refine_info.hh
index 16766ffee18..b80537f9deb 100644
--- a/source/blender/draw/intern/shaders/draw_hair_refine_info.hh
+++ b/source/blender/draw/intern/shaders/draw_hair_refine_info.hh
@@ -13,7 +13,7 @@ GPU_SHADER_CREATE_INFO(draw_hair_refine_compute)
.sampler(0, ImageType::FLOAT_BUFFER, "hairPointBuffer")
.sampler(1, ImageType::UINT_BUFFER, "hairStrandBuffer")
.sampler(2, ImageType::UINT_BUFFER, "hairStrandSegBuffer")
- .push_constant(Type::VEC4, "hairDupliMatrix", 4)
+ .push_constant(Type::MAT4, "hairDupliMatrix")
.push_constant(Type::BOOL, "hairCloseTip")
.push_constant(Type::FLOAT, "hairRadShape")
.push_constant(Type::FLOAT, "hairRadTip")
diff --git a/source/blender/draw/intern/shaders/draw_view_info.hh b/source/blender/draw/intern/shaders/draw_view_info.hh
index a699b9013ef..7329f2ed677 100644
--- a/source/blender/draw/intern/shaders/draw_view_info.hh
+++ b/source/blender/draw/intern/shaders/draw_view_info.hh
@@ -75,6 +75,16 @@ GPU_SHADER_CREATE_INFO(drw_clipped).define("USE_WORLD_CLIP_PLANES");
/** \} */
/* -------------------------------------------------------------------- */
+/** \name Draw Globals
+ * \{ */
+
+GPU_SHADER_CREATE_INFO(draw_globals)
+ .typedef_source("draw_common_shader_shared.h")
+ .uniform_buf(1, "GlobalsUboStorage", "globalsBlock", Frequency::PASS);
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
/** \name Geometry Type
* \{ */
@@ -92,7 +102,7 @@ GPU_SHADER_CREATE_INFO(draw_hair)
.push_constant(Type::FLOAT, "hairRadShape")
.push_constant(Type::BOOL, "hairCloseTip")
.push_constant(Type::INT, "hairStrandOffset")
- .push_constant(Type::VEC4, "hairDupliMatrix", 4)
+ .push_constant(Type::MAT4, "hairDupliMatrix")
.additional_info("draw_modelmat", "draw_resource_id");
GPU_SHADER_CREATE_INFO(draw_pointcloud)
diff --git a/source/blender/editors/animation/anim_channels_defines.c b/source/blender/editors/animation/anim_channels_defines.c
index 5169d6904f5..ed0befbcc24 100644
--- a/source/blender/editors/animation/anim_channels_defines.c
+++ b/source/blender/editors/animation/anim_channels_defines.c
@@ -5117,8 +5117,9 @@ static void draw_setting_widget(bAnimContext *ac,
break;
}
- if ((ale->fcurve_owner_id != NULL && ID_IS_LINKED(ale->fcurve_owner_id)) ||
- (ale->id != NULL && ID_IS_LINKED(ale->id))) {
+ if ((ale->fcurve_owner_id != NULL &&
+ (ID_IS_LINKED(ale->fcurve_owner_id) || ID_IS_OVERRIDE_LIBRARY(ale->fcurve_owner_id))) ||
+ (ale->id != NULL && (ID_IS_LINKED(ale->id) || ID_IS_OVERRIDE_LIBRARY(ale->id)))) {
if (setting != ACHANNEL_SETTING_EXPAND) {
UI_but_flag_enable(but, UI_BUT_DISABLED);
}
diff --git a/source/blender/editors/animation/anim_channels_edit.c b/source/blender/editors/animation/anim_channels_edit.c
index 08379be36fa..31d90c8bfec 100644
--- a/source/blender/editors/animation/anim_channels_edit.c
+++ b/source/blender/editors/animation/anim_channels_edit.c
@@ -2789,8 +2789,9 @@ static bool rename_anim_channels(bAnimContext *ac, int channel_index)
}
/* don't allow renaming linked channels */
- if ((ale->fcurve_owner_id != NULL && ID_IS_LINKED(ale->fcurve_owner_id)) ||
- (ale->id != NULL && ID_IS_LINKED(ale->id))) {
+ if ((ale->fcurve_owner_id != NULL &&
+ (ID_IS_LINKED(ale->fcurve_owner_id) || ID_IS_OVERRIDE_LIBRARY(ale->fcurve_owner_id))) ||
+ (ale->id != NULL && (ID_IS_LINKED(ale->id) || ID_IS_OVERRIDE_LIBRARY(ale->id)))) {
ANIM_animdata_freelist(&anim_data);
return false;
}
diff --git a/source/blender/editors/animation/anim_filter.c b/source/blender/editors/animation/anim_filter.c
index 0389e57627a..a75944fa2f2 100644
--- a/source/blender/editors/animation/anim_filter.c
+++ b/source/blender/editors/animation/anim_filter.c
@@ -1462,7 +1462,7 @@ static size_t animfilter_action(bAnimContext *ac,
/* don't include anything from this action if it is linked in from another file,
* and we're getting stuff for editing...
*/
- if ((filter_mode & ANIMFILTER_FOREDIT) && ID_IS_LINKED(act)) {
+ if ((filter_mode & ANIMFILTER_FOREDIT) && (ID_IS_LINKED(act) || ID_IS_OVERRIDE_LIBRARY(act))) {
return 0;
}
diff --git a/source/blender/editors/animation/keyframes_draw.c b/source/blender/editors/animation/keyframes_draw.c
index f40c1b983d7..58d093c678d 100644
--- a/source/blender/editors/animation/keyframes_draw.c
+++ b/source/blender/editors/animation/keyframes_draw.c
@@ -659,7 +659,8 @@ void draw_fcurve_channel(AnimKeylistDrawList *draw_list,
{
const bool locked = (fcu->flag & FCURVE_PROTECTED) ||
((fcu->grp) && (fcu->grp->flag & AGRP_PROTECTED)) ||
- ((adt && adt->action) && ID_IS_LINKED(adt->action));
+ ((adt && adt->action) &&
+ (ID_IS_LINKED(adt->action) || ID_IS_OVERRIDE_LIBRARY(adt->action)));
AnimKeylistDrawListElem *draw_elem = ed_keylist_draw_list_add_elem(
draw_list, ANIM_KEYLIST_FCURVE, ypos, yscale_fac, saction_flag);
@@ -676,7 +677,8 @@ void draw_agroup_channel(AnimKeylistDrawList *draw_list,
int saction_flag)
{
bool locked = (agrp->flag & AGRP_PROTECTED) ||
- ((adt && adt->action) && ID_IS_LINKED(adt->action));
+ ((adt && adt->action) &&
+ (ID_IS_LINKED(adt->action) || ID_IS_OVERRIDE_LIBRARY(adt->action)));
AnimKeylistDrawListElem *draw_elem = ed_keylist_draw_list_add_elem(
draw_list, ANIM_KEYLIST_AGROUP, ypos, yscale_fac, saction_flag);
@@ -692,7 +694,7 @@ void draw_action_channel(AnimKeylistDrawList *draw_list,
float yscale_fac,
int saction_flag)
{
- const bool locked = (act && ID_IS_LINKED(act));
+ const bool locked = (act && (ID_IS_LINKED(act) || ID_IS_OVERRIDE_LIBRARY(act)));
saction_flag &= ~SACTION_SHOW_EXTREMES;
AnimKeylistDrawListElem *draw_elem = ed_keylist_draw_list_add_elem(
diff --git a/source/blender/editors/armature/meshlaplacian.c b/source/blender/editors/armature/meshlaplacian.c
index 31caa29a02a..7016511111e 100644
--- a/source/blender/editors/armature/meshlaplacian.c
+++ b/source/blender/editors/armature/meshlaplacian.c
@@ -59,7 +59,7 @@ static void error(const char *str)
struct LaplacianSystem {
LinearSolver *context; /* linear solver */
- int totvert, totface;
+ int verts_num, faces_num;
float **verts; /* vertex coordinates */
float *varea; /* vertex weights for laplacian computation */
@@ -76,8 +76,8 @@ struct LaplacianSystem {
struct HeatWeighting {
const MLoopTri *mlooptri;
const MLoop *mloop; /* needed to find vertices by index */
- int totvert;
- int tottri;
+ int verts_num;
+ int tris_num;
float (*verts)[3]; /* vertex coordinates */
float (*vnors)[3]; /* vertex normals */
@@ -202,28 +202,28 @@ static void laplacian_triangle_weights(LaplacianSystem *sys, int f, int i1, int
}
}
-static LaplacianSystem *laplacian_system_construct_begin(int totvert, int totface, int lsq)
+static LaplacianSystem *laplacian_system_construct_begin(int verts_num, int faces_num, int lsq)
{
LaplacianSystem *sys;
sys = MEM_callocN(sizeof(LaplacianSystem), "LaplacianSystem");
- sys->verts = MEM_callocN(sizeof(float *) * totvert, "LaplacianSystemVerts");
- sys->vpinned = MEM_callocN(sizeof(char) * totvert, "LaplacianSystemVpinned");
- sys->faces = MEM_callocN(sizeof(int[3]) * totface, "LaplacianSystemFaces");
+ sys->verts = MEM_callocN(sizeof(float *) * verts_num, "LaplacianSystemVerts");
+ sys->vpinned = MEM_callocN(sizeof(char) * verts_num, "LaplacianSystemVpinned");
+ sys->faces = MEM_callocN(sizeof(int[3]) * faces_num, "LaplacianSystemFaces");
- sys->totvert = 0;
- sys->totface = 0;
+ sys->verts_num = 0;
+ sys->faces_num = 0;
sys->areaweights = 1;
sys->storeweights = 0;
/* create linear solver */
if (lsq) {
- sys->context = EIG_linear_least_squares_solver_new(0, totvert, 1);
+ sys->context = EIG_linear_least_squares_solver_new(0, verts_num, 1);
}
else {
- sys->context = EIG_linear_solver_new(0, totvert, 1);
+ sys->context = EIG_linear_solver_new(0, verts_num, 1);
}
return sys;
@@ -231,42 +231,43 @@ static LaplacianSystem *laplacian_system_construct_begin(int totvert, int totfac
void laplacian_add_vertex(LaplacianSystem *sys, float *co, int pinned)
{
- sys->verts[sys->totvert] = co;
- sys->vpinned[sys->totvert] = pinned;
- sys->totvert++;
+ sys->verts[sys->verts_num] = co;
+ sys->vpinned[sys->verts_num] = pinned;
+ sys->verts_num++;
}
void laplacian_add_triangle(LaplacianSystem *sys, int v1, int v2, int v3)
{
- sys->faces[sys->totface][0] = v1;
- sys->faces[sys->totface][1] = v2;
- sys->faces[sys->totface][2] = v3;
- sys->totface++;
+ sys->faces[sys->faces_num][0] = v1;
+ sys->faces[sys->faces_num][1] = v2;
+ sys->faces[sys->faces_num][2] = v3;
+ sys->faces_num++;
}
static void laplacian_system_construct_end(LaplacianSystem *sys)
{
int(*face)[3];
- int a, totvert = sys->totvert, totface = sys->totface;
+ int a, verts_num = sys->verts_num, faces_num = sys->faces_num;
laplacian_begin_solve(sys, 0);
- sys->varea = MEM_callocN(sizeof(float) * totvert, "LaplacianSystemVarea");
+ sys->varea = MEM_callocN(sizeof(float) * verts_num, "LaplacianSystemVarea");
- sys->edgehash = BLI_edgehash_new_ex(__func__, BLI_EDGEHASH_SIZE_GUESS_FROM_POLYS(sys->totface));
- for (a = 0, face = sys->faces; a < sys->totface; a++, face++) {
+ sys->edgehash = BLI_edgehash_new_ex(__func__,
+ BLI_EDGEHASH_SIZE_GUESS_FROM_POLYS(sys->faces_num));
+ for (a = 0, face = sys->faces; a < sys->faces_num; a++, face++) {
laplacian_increase_edge_count(sys->edgehash, (*face)[0], (*face)[1]);
laplacian_increase_edge_count(sys->edgehash, (*face)[1], (*face)[2]);
laplacian_increase_edge_count(sys->edgehash, (*face)[2], (*face)[0]);
}
if (sys->areaweights) {
- for (a = 0, face = sys->faces; a < sys->totface; a++, face++) {
+ for (a = 0, face = sys->faces; a < sys->faces_num; a++, face++) {
laplacian_triangle_area(sys, (*face)[0], (*face)[1], (*face)[2]);
}
}
- for (a = 0; a < totvert; a++) {
+ for (a = 0; a < verts_num; a++) {
if (sys->areaweights) {
if (sys->varea[a] != 0.0f) {
sys->varea[a] = 0.5f / sys->varea[a];
@@ -283,10 +284,10 @@ static void laplacian_system_construct_end(LaplacianSystem *sys)
}
if (sys->storeweights) {
- sys->fweights = MEM_callocN(sizeof(float[3]) * totface, "LaplacianFWeight");
+ sys->fweights = MEM_callocN(sizeof(float[3]) * faces_num, "LaplacianFWeight");
}
- for (a = 0, face = sys->faces; a < totface; a++, face++) {
+ for (a = 0, face = sys->faces; a < faces_num; a++, face++) {
laplacian_triangle_weights(sys, a, (*face)[0], (*face)[1], (*face)[2]);
}
@@ -327,7 +328,7 @@ void laplacian_begin_solve(LaplacianSystem *sys, int index)
if (!sys->variablesdone) {
if (index >= 0) {
- for (a = 0; a < sys->totvert; a++) {
+ for (a = 0; a < sys->verts_num; a++) {
if (sys->vpinned[a]) {
EIG_linear_solver_variable_set(sys->context, 0, a, sys->verts[a][index]);
EIG_linear_solver_variable_lock(sys->context, a);
@@ -411,14 +412,14 @@ static void heat_ray_tree_create(LaplacianSystem *sys)
const MLoopTri *looptri = sys->heat.mlooptri;
const MLoop *mloop = sys->heat.mloop;
float(*verts)[3] = sys->heat.verts;
- int tottri = sys->heat.tottri;
- int totvert = sys->heat.totvert;
+ int tris_num = sys->heat.tris_num;
+ int verts_num = sys->heat.verts_num;
int a;
- sys->heat.bvhtree = BLI_bvhtree_new(tottri, 0.0f, 4, 6);
- sys->heat.vltree = MEM_callocN(sizeof(MLoopTri *) * totvert, "HeatVFaces");
+ sys->heat.bvhtree = BLI_bvhtree_new(tris_num, 0.0f, 4, 6);
+ sys->heat.vltree = MEM_callocN(sizeof(MLoopTri *) * verts_num, "HeatVFaces");
- for (a = 0; a < tottri; a++) {
+ for (a = 0; a < tris_num; a++) {
const MLoopTri *lt = &looptri[a];
float bb[6];
int vtri[3];
@@ -552,9 +553,9 @@ static void heat_calc_vnormals(LaplacianSystem *sys)
float fnor[3];
int a, v1, v2, v3, (*face)[3];
- sys->heat.vnors = MEM_callocN(sizeof(float[3]) * sys->totvert, "HeatVNors");
+ sys->heat.vnors = MEM_callocN(sizeof(float[3]) * sys->verts_num, "HeatVNors");
- for (a = 0, face = sys->faces; a < sys->totface; a++, face++) {
+ for (a = 0, face = sys->faces; a < sys->faces_num; a++, face++) {
v1 = (*face)[0];
v2 = (*face)[1];
v3 = (*face)[2];
@@ -566,7 +567,7 @@ static void heat_calc_vnormals(LaplacianSystem *sys)
add_v3_v3(sys->heat.vnors[v3], fnor);
}
- for (a = 0; a < sys->totvert; a++) {
+ for (a = 0; a < sys->verts_num; a++) {
normalize_v3(sys->heat.vnors[a]);
}
}
@@ -575,21 +576,21 @@ static void heat_laplacian_create(LaplacianSystem *sys)
{
const MLoopTri *mlooptri = sys->heat.mlooptri, *lt;
const MLoop *mloop = sys->heat.mloop;
- int tottri = sys->heat.tottri;
- int totvert = sys->heat.totvert;
+ int tris_num = sys->heat.tris_num;
+ int verts_num = sys->heat.verts_num;
int a;
/* heat specific definitions */
- sys->heat.mindist = MEM_callocN(sizeof(float) * totvert, "HeatMinDist");
- sys->heat.H = MEM_callocN(sizeof(float) * totvert, "HeatH");
- sys->heat.p = MEM_callocN(sizeof(float) * totvert, "HeatP");
+ sys->heat.mindist = MEM_callocN(sizeof(float) * verts_num, "HeatMinDist");
+ sys->heat.H = MEM_callocN(sizeof(float) * verts_num, "HeatH");
+ sys->heat.p = MEM_callocN(sizeof(float) * verts_num, "HeatP");
/* add verts and faces to laplacian */
- for (a = 0; a < totvert; a++) {
+ for (a = 0; a < verts_num; a++) {
laplacian_add_vertex(sys, sys->heat.verts[a], 0);
}
- for (a = 0, lt = mlooptri; a < tottri; a++, lt++) {
+ for (a = 0, lt = mlooptri; a < tris_num; a++, lt++) {
int vtri[3];
vtri[0] = mloop[lt->tri[0]].v;
vtri[1] = mloop[lt->tri[1]].v;
@@ -600,7 +601,7 @@ static void heat_laplacian_create(LaplacianSystem *sys)
/* for distance computation in set_H */
heat_calc_vnormals(sys);
- for (a = 0; a < totvert; a++) {
+ for (a = 0; a < verts_num; a++) {
heat_set_H(sys, a);
}
}
@@ -648,7 +649,7 @@ void heat_bone_weighting(Object *ob,
MLoop *ml;
float solution, weight;
int *vertsflipped = NULL, *mask = NULL;
- int a, tottri, j, bbone, firstsegment, lastsegment;
+ int a, tris_num, j, bbone, firstsegment, lastsegment;
bool use_topology = (me->editflag & ME_EDIT_MIRROR_TOPO) != 0;
MVert *mvert = me->mvert;
@@ -658,7 +659,7 @@ void heat_bone_weighting(Object *ob,
*error_str = NULL;
/* bone heat needs triangulated faces */
- tottri = poly_to_tri_count(me->totpoly, me->totloop);
+ tris_num = poly_to_tri_count(me->totpoly, me->totloop);
/* count triangles and create mask */
if (ob->mode & OB_MODE_WEIGHT_PAINT && (use_face_sel || use_vert_sel)) {
@@ -684,16 +685,16 @@ void heat_bone_weighting(Object *ob,
}
/* create laplacian */
- sys = laplacian_system_construct_begin(me->totvert, tottri, 1);
+ sys = laplacian_system_construct_begin(me->totvert, tris_num, 1);
- sys->heat.tottri = poly_to_tri_count(me->totpoly, me->totloop);
- mlooptri = MEM_mallocN(sizeof(*sys->heat.mlooptri) * sys->heat.tottri, __func__);
+ sys->heat.tris_num = poly_to_tri_count(me->totpoly, me->totloop);
+ mlooptri = MEM_mallocN(sizeof(*sys->heat.mlooptri) * sys->heat.tris_num, __func__);
BKE_mesh_recalc_looptri(me->mloop, me->mpoly, me->mvert, me->totloop, me->totpoly, mlooptri);
sys->heat.mlooptri = mlooptri;
sys->heat.mloop = me->mloop;
- sys->heat.totvert = me->totvert;
+ sys->heat.verts_num = me->totvert;
sys->heat.verts = verts;
sys->heat.root = root;
sys->heat.tip = tip;
@@ -886,7 +887,7 @@ typedef struct MeshDeformBind {
Mesh *cagemesh;
float (*cagecos)[3];
float (*vertexcos)[3];
- int totvert, totcagevert;
+ int verts_num, cage_verts_num;
/* grids */
MemArena *memarena;
@@ -1467,7 +1468,7 @@ static void meshdeform_matrix_solve(MeshDeformModifierData *mmd, MeshDeformBind
}
/* solve for each cage vert */
- for (a = 0; a < mdb->totcagevert; a++) {
+ for (a = 0; a < mdb->cage_verts_num; a++) {
/* fill in right hand side and solve */
for (z = 0; z < mdb->size; z++) {
for (y = 0; y < mdb->size; y++) {
@@ -1503,14 +1504,14 @@ static void meshdeform_matrix_solve(MeshDeformModifierData *mmd, MeshDeformBind
if (mdb->weights) {
/* static bind : compute weights for each vertex */
- for (b = 0; b < mdb->totvert; b++) {
+ for (b = 0; b < mdb->verts_num; b++) {
if (mdb->inside[b]) {
copy_v3_v3(vec, mdb->vertexcos[b]);
gridvec[0] = (vec[0] - mdb->min[0] - mdb->halfwidth[0]) / mdb->width[0];
gridvec[1] = (vec[1] - mdb->min[1] - mdb->halfwidth[1]) / mdb->width[1];
gridvec[2] = (vec[2] - mdb->min[2] - mdb->halfwidth[2]) / mdb->width[2];
- mdb->weights[b * mdb->totcagevert + a] = meshdeform_interp_w(mdb, gridvec, vec, a);
+ mdb->weights[b * mdb->cage_verts_num + a] = meshdeform_interp_w(mdb, gridvec, vec, a);
}
}
}
@@ -1536,9 +1537,12 @@ static void meshdeform_matrix_solve(MeshDeformModifierData *mmd, MeshDeformBind
break;
}
- BLI_snprintf(
- message, sizeof(message), "Mesh deform solve %d / %d |||", a + 1, mdb->totcagevert);
- progress_bar((float)(a + 1) / (float)(mdb->totcagevert), message);
+ BLI_snprintf(message,
+ sizeof(message),
+ "Mesh deform solve %d / %d |||",
+ a + 1,
+ mdb->cage_verts_num);
+ progress_bar((float)(a + 1) / (float)(mdb->cage_verts_num), message);
}
#if 0
@@ -1573,7 +1577,7 @@ static void harmonic_coordinates_bind(MeshDeformModifierData *mmd, MeshDeformBin
/* compute bounding box of the cage mesh */
INIT_MINMAX(mdb->min, mdb->max);
- for (a = 0; a < mdb->totcagevert; a++) {
+ for (a = 0; a < mdb->cage_verts_num; a++) {
minmax_v3v3_v3(mdb->min, mdb->max, mdb->cagecos[a]);
}
@@ -1586,13 +1590,14 @@ static void harmonic_coordinates_bind(MeshDeformModifierData *mmd, MeshDeformBin
mdb->boundisect = MEM_callocN(sizeof(*mdb->boundisect) * mdb->size3, "MDefBoundIsect");
mdb->semibound = MEM_callocN(sizeof(int) * mdb->size3, "MDefSemiBound");
mdb->bvhtree = BKE_bvhtree_from_mesh_get(&mdb->bvhdata, mdb->cagemesh, BVHTREE_FROM_LOOPTRI, 4);
- mdb->inside = MEM_callocN(sizeof(int) * mdb->totvert, "MDefInside");
+ mdb->inside = MEM_callocN(sizeof(int) * mdb->verts_num, "MDefInside");
if (mmd->flag & MOD_MDEF_DYNAMIC_BIND) {
mdb->dyngrid = MEM_callocN(sizeof(MDefBindInfluence *) * mdb->size3, "MDefDynGrid");
}
else {
- mdb->weights = MEM_callocN(sizeof(float) * mdb->totvert * mdb->totcagevert, "MDefWeights");
+ mdb->weights = MEM_callocN(sizeof(float) * mdb->verts_num * mdb->cage_verts_num,
+ "MDefWeights");
}
mdb->memarena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, "harmonic coords arena");
@@ -1632,7 +1637,7 @@ static void harmonic_coordinates_bind(MeshDeformModifierData *mmd, MeshDeformBin
progress_bar(0, "Setting up mesh deform system");
totinside = 0;
- for (a = 0; a < mdb->totvert; a++) {
+ for (a = 0; a < mdb->verts_num; a++) {
copy_v3_v3(vec, mdb->vertexcos[a]);
mdb->inside[a] = meshdeform_inside_cage(mdb, vec);
if (mdb->inside[a]) {
@@ -1674,16 +1679,16 @@ static void harmonic_coordinates_bind(MeshDeformModifierData *mmd, MeshDeformBin
/* assign results */
if (mmd->flag & MOD_MDEF_DYNAMIC_BIND) {
- mmd->totinfluence = 0;
+ mmd->influences_num = 0;
for (a = 0; a < mdb->size3; a++) {
for (inf = mdb->dyngrid[a]; inf; inf = inf->next) {
- mmd->totinfluence++;
+ mmd->influences_num++;
}
}
/* convert MDefBindInfluences to smaller MDefInfluences */
mmd->dyngrid = MEM_callocN(sizeof(MDefCell) * mdb->size3, "MDefDynGrid");
- mmd->dyninfluences = MEM_callocN(sizeof(MDefInfluence) * mmd->totinfluence, "MDefInfluence");
+ mmd->dyninfluences = MEM_callocN(sizeof(MDefInfluence) * mmd->influences_num, "MDefInfluence");
offset = 0;
for (a = 0; a < mdb->size3; a++) {
cell = &mmd->dyngrid[a];
@@ -1695,17 +1700,17 @@ static void harmonic_coordinates_bind(MeshDeformModifierData *mmd, MeshDeformBin
mdinf->weight = inf->weight;
mdinf->vertex = inf->vertex;
totweight += mdinf->weight;
- cell->totinfluence++;
+ cell->influences_num++;
}
if (totweight > 0.0f) {
mdinf = mmd->dyninfluences + cell->offset;
- for (b = 0; b < cell->totinfluence; b++, mdinf++) {
+ for (b = 0; b < cell->influences_num; b++, mdinf++) {
mdinf->weight /= totweight;
}
}
- offset += cell->totinfluence;
+ offset += cell->influences_num;
}
mmd->dynverts = mdb->inside;
@@ -1732,7 +1737,7 @@ void ED_mesh_deform_bind_callback(Object *object,
MeshDeformModifierData *mmd,
Mesh *cagemesh,
float *vertexcos,
- int totvert,
+ int verts_num,
float cagemat[4][4])
{
MeshDeformModifierData *mmd_orig = (MeshDeformModifierData *)BKE_modifier_get_original(
@@ -1750,19 +1755,19 @@ void ED_mesh_deform_bind_callback(Object *object,
BKE_mesh_wrapper_ensure_mdata(cagemesh);
/* get mesh and cage mesh */
- mdb.vertexcos = MEM_callocN(sizeof(float[3]) * totvert, "MeshDeformCos");
- mdb.totvert = totvert;
+ mdb.vertexcos = MEM_callocN(sizeof(float[3]) * verts_num, "MeshDeformCos");
+ mdb.verts_num = verts_num;
mdb.cagemesh = cagemesh;
- mdb.totcagevert = mdb.cagemesh->totvert;
- mdb.cagecos = MEM_callocN(sizeof(*mdb.cagecos) * mdb.totcagevert, "MeshDeformBindCos");
+ mdb.cage_verts_num = mdb.cagemesh->totvert;
+ mdb.cagecos = MEM_callocN(sizeof(*mdb.cagecos) * mdb.cage_verts_num, "MeshDeformBindCos");
copy_m4_m4(mdb.cagemat, cagemat);
mvert = mdb.cagemesh->mvert;
- for (a = 0; a < mdb.totcagevert; a++) {
+ for (a = 0; a < mdb.cage_verts_num; a++) {
copy_v3_v3(mdb.cagecos[a], mvert[a].co);
}
- for (a = 0; a < mdb.totvert; a++) {
+ for (a = 0; a < mdb.verts_num; a++) {
mul_v3_m4v3(mdb.vertexcos[a], mdb.cagemat, vertexcos + a * 3);
}
@@ -1771,12 +1776,12 @@ void ED_mesh_deform_bind_callback(Object *object,
/* assign bind variables */
mmd_orig->bindcagecos = (float *)mdb.cagecos;
- mmd_orig->totvert = mdb.totvert;
- mmd_orig->totcagevert = mdb.totcagevert;
+ mmd_orig->verts_num = mdb.verts_num;
+ mmd_orig->cage_verts_num = mdb.cage_verts_num;
copy_m4_m4(mmd_orig->bindmat, mmd_orig->object->obmat);
/* transform bindcagecos to world space */
- for (a = 0; a < mdb.totcagevert; a++) {
+ for (a = 0; a < mdb.cage_verts_num; a++) {
mul_m4_v3(mmd_orig->object->obmat, mmd_orig->bindcagecos + a * 3);
}
diff --git a/source/blender/editors/armature/pose_edit.c b/source/blender/editors/armature/pose_edit.c
index 90ee7c83436..2ad7a373012 100644
--- a/source/blender/editors/armature/pose_edit.c
+++ b/source/blender/editors/armature/pose_edit.c
@@ -23,6 +23,7 @@
#include "BKE_deform.h"
#include "BKE_global.h"
#include "BKE_layer.h"
+#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_object.h"
#include "BKE_report.h"
@@ -78,7 +79,7 @@ Object *ED_pose_object_from_context(bContext *C)
bool ED_object_posemode_enter_ex(struct Main *bmain, Object *ob)
{
- BLI_assert(!ID_IS_LINKED(ob));
+ BLI_assert(BKE_id_is_editable(bmain, &ob->id));
bool ok = false;
switch (ob->type) {
@@ -99,11 +100,11 @@ bool ED_object_posemode_enter_ex(struct Main *bmain, Object *ob)
bool ED_object_posemode_enter(bContext *C, Object *ob)
{
ReportList *reports = CTX_wm_reports(C);
- if (ID_IS_LINKED(ob)) {
+ struct Main *bmain = CTX_data_main(C);
+ if (!BKE_id_is_editable(bmain, &ob->id)) {
BKE_report(reports, RPT_WARNING, "Cannot pose libdata");
return false;
}
- struct Main *bmain = CTX_data_main(C);
bool ok = ED_object_posemode_enter_ex(bmain, ob);
if (ok) {
WM_event_add_notifier(C, NC_SCENE | ND_MODE | NS_MODE_POSE, NULL);
diff --git a/source/blender/editors/armature/pose_lib.c b/source/blender/editors/armature/pose_lib.c
index 9796f6771d2..4b3ece64bf9 100644
--- a/source/blender/editors/armature/pose_lib.c
+++ b/source/blender/editors/armature/pose_lib.c
@@ -170,7 +170,7 @@ static bool has_poselib_pose_data_poll(bContext *C)
static bool has_poselib_pose_data_for_editing_poll(bContext *C)
{
Object *ob = get_poselib_object(C);
- return (ob && ob->poselib && !ID_IS_LINKED(ob->poselib));
+ return (ob && ob->poselib && BKE_id_is_editable(CTX_data_main(C), &ob->poselib->id));
}
/* ----------------------------------- */
@@ -377,7 +377,7 @@ static bool poselib_add_poll(bContext *C)
if (ED_operator_posemode(C)) {
Object *ob = get_poselib_object(C);
if (ob) {
- if ((ob->poselib == NULL) || !ID_IS_LINKED(ob->poselib)) {
+ if ((ob->poselib == NULL) || BKE_id_is_editable(CTX_data_main(C), &ob->poselib->id)) {
return true;
}
}
diff --git a/source/blender/editors/armature/pose_lib_2.c b/source/blender/editors/armature/pose_lib_2.c
index ced99f16794..9ee289145c4 100644
--- a/source/blender/editors/armature/pose_lib_2.c
+++ b/source/blender/editors/armature/pose_lib_2.c
@@ -103,7 +103,8 @@ static void poselib_keytag_pose(bContext *C, Scene *scene, PoseBlendData *pbd)
}
AnimData *adt = BKE_animdata_from_id(&pbd->ob->id);
- if (adt != NULL && adt->action != NULL && ID_IS_LINKED(&adt->action->id)) {
+ if (adt != NULL && adt->action != NULL &&
+ !BKE_id_is_editable(CTX_data_main(C), &adt->action->id)) {
/* Changes to linked-in Actions are not allowed. */
return;
}
diff --git a/source/blender/editors/asset/ED_asset_type.h b/source/blender/editors/asset/ED_asset_type.h
index 88511490b5c..f0cddbdf070 100644
--- a/source/blender/editors/asset/ED_asset_type.h
+++ b/source/blender/editors/asset/ED_asset_type.h
@@ -16,7 +16,7 @@ struct ID;
bool ED_asset_type_id_is_non_experimental(const struct ID *id);
#define ED_ASSET_TYPE_IDS_NON_EXPERIMENTAL_FLAGS \
- (FILTER_ID_MA | FILTER_ID_OB | FILTER_ID_AC | FILTER_ID_WO | FILTER_ID_NT)
+ (FILTER_ID_MA | FILTER_ID_GR | FILTER_ID_OB | FILTER_ID_AC | FILTER_ID_WO | FILTER_ID_NT)
/**
* Check if the asset type for \a id (which doesn't need to be an asset right now) can be an asset,
@@ -39,7 +39,7 @@ int64_t ED_asset_types_supported_as_filter_flags(void);
* Should start with a consonant, so usages can prefix it with "a" (not "an").
*/
#define ED_ASSET_TYPE_IDS_NON_EXPERIMENTAL_UI_STRING \
- "Material, Object, Pose Action, Node Group or World"
+ "Material, Collection, Object, Pose Action, Node Group or World"
#ifdef __cplusplus
}
diff --git a/source/blender/editors/asset/intern/asset_type.cc b/source/blender/editors/asset/intern/asset_type.cc
index 2c219f3dce2..3ecf7df068f 100644
--- a/source/blender/editors/asset/intern/asset_type.cc
+++ b/source/blender/editors/asset/intern/asset_type.cc
@@ -16,7 +16,7 @@ bool ED_asset_type_id_is_non_experimental(const ID *id)
{
/* Remember to update #ED_ASSET_TYPE_IDS_NON_EXPERIMENTAL_UI_STRING and
* #ED_ASSET_TYPE_IDS_NON_EXPERIMENTAL_FLAGS() with this! */
- return ELEM(GS(id->name), ID_MA, ID_OB, ID_AC, ID_WO, ID_NT);
+ return ELEM(GS(id->name), ID_MA, ID_GR, ID_OB, ID_AC, ID_WO, ID_NT);
}
bool ED_asset_type_is_supported(const ID *id)
diff --git a/source/blender/editors/curve/editcurve.c b/source/blender/editors/curve/editcurve.c
index 5ff63e767f6..38c14391273 100644
--- a/source/blender/editors/curve/editcurve.c
+++ b/source/blender/editors/curve/editcurve.c
@@ -1209,7 +1209,7 @@ static void remap_hooks_and_vertex_parents(Main *bmain, Object *obedit)
old_to_new_map = init_index_map(obedit, &old_totvert);
}
- for (i = j = 0; i < hmd->totindex; i++) {
+ for (i = j = 0; i < hmd->indexar_num; i++) {
if (hmd->indexar[i] < old_totvert) {
index = old_to_new_map[hmd->indexar[i]];
if (index != -1) {
@@ -1221,7 +1221,7 @@ static void remap_hooks_and_vertex_parents(Main *bmain, Object *obedit)
}
}
- hmd->totindex = j;
+ hmd->indexar_num = j;
}
}
}
diff --git a/source/blender/editors/curves/intern/curves_ops.cc b/source/blender/editors/curves/intern/curves_ops.cc
index 52a55ae1760..bbd48ccd89a 100644
--- a/source/blender/editors/curves/intern/curves_ops.cc
+++ b/source/blender/editors/curves/intern/curves_ops.cc
@@ -4,8 +4,289 @@
* \ingroup edcurves
*/
+#include "BLI_utildefines.h"
+
#include "ED_curves.h"
+#include "ED_object.h"
+
+#include "WM_api.h"
+
+#include "BKE_context.h"
+#include "BKE_curves.hh"
+#include "BKE_layer.h"
+#include "BKE_mesh.h"
+#include "BKE_mesh_runtime.h"
+#include "BKE_paint.h"
+#include "BKE_particle.h"
+
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_modifier_types.h"
+#include "DNA_object_types.h"
+#include "DNA_particle_types.h"
+#include "DNA_scene_types.h"
+
+#include "DEG_depsgraph.h"
+
+/**
+ * The code below uses a suffix naming convention to indicate the coordinate space:
+ * `cu`: Local space of the curves object that is being edited.
+ * `su`: Local space of the surface object.
+ * `wo`: World space.
+ * `ha`: Local space of an individual hair in the legacy hair system.
+ */
+
+namespace blender::ed::curves {
+
+using bke::CurvesGeometry;
+
+namespace convert_to_particle_system {
+
+static int find_mface_for_root_position(const Mesh &mesh,
+ const Span<int> possible_mface_indices,
+ const float3 &root_pos)
+{
+ BLI_assert(possible_mface_indices.size() >= 1);
+ if (possible_mface_indices.size() == 1) {
+ return possible_mface_indices.first();
+ }
+ /* Find the closest #MFace to #root_pos. */
+ int mface_i;
+ float best_distance_sq = FLT_MAX;
+ for (const int possible_mface_i : possible_mface_indices) {
+ const MFace &possible_mface = mesh.mface[possible_mface_i];
+ {
+ float3 point_in_triangle;
+ closest_on_tri_to_point_v3(point_in_triangle,
+ root_pos,
+ mesh.mvert[possible_mface.v1].co,
+ mesh.mvert[possible_mface.v2].co,
+ mesh.mvert[possible_mface.v3].co);
+ const float distance_sq = len_squared_v3v3(root_pos, point_in_triangle);
+ if (distance_sq < best_distance_sq) {
+ best_distance_sq = distance_sq;
+ mface_i = possible_mface_i;
+ }
+ }
+ /* Optionally check the second triangle if the #MFace is a quad. */
+ if (possible_mface.v4) {
+ float3 point_in_triangle;
+ closest_on_tri_to_point_v3(point_in_triangle,
+ root_pos,
+ mesh.mvert[possible_mface.v1].co,
+ mesh.mvert[possible_mface.v3].co,
+ mesh.mvert[possible_mface.v4].co);
+ const float distance_sq = len_squared_v3v3(root_pos, point_in_triangle);
+ if (distance_sq < best_distance_sq) {
+ best_distance_sq = distance_sq;
+ mface_i = possible_mface_i;
+ }
+ }
+ }
+ return mface_i;
+}
+
+/**
+ * \return Barycentric coordinates in the #MFace.
+ */
+static float4 compute_mface_weights_for_position(const Mesh &mesh,
+ const MFace &mface,
+ const float3 &position)
+{
+ float4 mface_weights;
+ if (mface.v4) {
+ float mface_verts_su[4][3];
+ copy_v3_v3(mface_verts_su[0], mesh.mvert[mface.v1].co);
+ copy_v3_v3(mface_verts_su[1], mesh.mvert[mface.v2].co);
+ copy_v3_v3(mface_verts_su[2], mesh.mvert[mface.v3].co);
+ copy_v3_v3(mface_verts_su[3], mesh.mvert[mface.v4].co);
+ interp_weights_poly_v3(mface_weights, mface_verts_su, 4, position);
+ }
+ else {
+ interp_weights_tri_v3(mface_weights,
+ mesh.mvert[mface.v1].co,
+ mesh.mvert[mface.v2].co,
+ mesh.mvert[mface.v3].co,
+ position);
+ mface_weights[3] = 0.0f;
+ }
+ return mface_weights;
+}
+
+static int curves_convert_to_particle_system_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+
+ CTX_DATA_BEGIN (C, Object *, curves_ob, selected_objects) {
+ if (curves_ob->type != OB_CURVES) {
+ continue;
+ }
+ Curves &curves_id = *static_cast<Curves *>(curves_ob->data);
+ CurvesGeometry &curves = CurvesGeometry::wrap(curves_id.geometry);
+ if (curves_id.surface == nullptr) {
+ continue;
+ }
+ Object &surface_ob = *curves_id.surface;
+ if (surface_ob.type != OB_MESH) {
+ continue;
+ }
+ Mesh &surface_me = *static_cast<Mesh *>(surface_ob.data);
+
+ const Span<float3> positions_cu = curves.positions();
+ const VArray<int> looptri_indices = std::as_const(curves).surface_triangle_indices();
+ const Span<MLoopTri> looptris{BKE_mesh_runtime_looptri_ensure(&surface_me),
+ BKE_mesh_runtime_looptri_len(&surface_me)};
+
+ /* Find indices of curves that can be transferred to the old hair system. */
+ Vector<int> curves_indices_to_transfer;
+ for (const int curve_i : curves.curves_range()) {
+ const int looptri_i = looptri_indices[curve_i];
+ if (looptri_i >= 0 && looptri_i < looptris.size()) {
+ curves_indices_to_transfer.append(curve_i);
+ }
+ }
+
+ const int hairs_num = curves_indices_to_transfer.size();
+ if (hairs_num == 0) {
+ continue;
+ }
+
+ ParticleSystem *particle_system = nullptr;
+ LISTBASE_FOREACH (ParticleSystem *, psys, &surface_ob.particlesystem) {
+ if (STREQ(psys->name, curves_ob->id.name + 2)) {
+ particle_system = psys;
+ break;
+ }
+ }
+ if (particle_system == nullptr) {
+ ParticleSystemModifierData &psmd = *reinterpret_cast<ParticleSystemModifierData *>(
+ object_add_particle_system(bmain, scene, &surface_ob, curves_ob->id.name + 2));
+ particle_system = psmd.psys;
+ }
+
+ ParticleSettings &settings = *particle_system->part;
+
+ psys_free_particles(particle_system);
+ settings.type = PART_HAIR;
+ settings.totpart = 0;
+ psys_changed_type(&surface_ob, particle_system);
+
+ MutableSpan<ParticleData> particles{
+ static_cast<ParticleData *>(MEM_calloc_arrayN(hairs_num, sizeof(ParticleData), __func__)),
+ hairs_num};
+
+ /* The old hair system still uses #MFace, so make sure those are available on the mesh. */
+ BKE_mesh_tessface_calc(&surface_me);
+
+ /* Prepare utility data structure to map hair roots to mfaces. */
+ const Span<int> mface_to_poly_map{
+ static_cast<int *>(CustomData_get_layer(&surface_me.fdata, CD_ORIGINDEX)),
+ surface_me.totface};
+ Array<Vector<int>> poly_to_mface_map(surface_me.totpoly);
+ for (const int mface_i : mface_to_poly_map.index_range()) {
+ const int poly_i = mface_to_poly_map[mface_i];
+ poly_to_mface_map[poly_i].append(mface_i);
+ }
+
+ /* Prepare transformation matrices. */
+ const float4x4 curves_to_world_mat = curves_ob->obmat;
+ const float4x4 surface_to_world_mat = surface_ob.obmat;
+ const float4x4 world_to_surface_mat = surface_to_world_mat.inverted();
+ const float4x4 curves_to_surface_mat = world_to_surface_mat * curves_to_world_mat;
+
+ for (const int new_hair_i : curves_indices_to_transfer.index_range()) {
+ const int curve_i = curves_indices_to_transfer[new_hair_i];
+ const IndexRange points = curves.points_for_curve(curve_i);
+
+ const int looptri_i = looptri_indices[curve_i];
+ const MLoopTri &looptri = looptris[looptri_i];
+ const int poly_i = looptri.poly;
+
+ const float3 &root_pos_cu = positions_cu[points.first()];
+ const float3 root_pos_su = curves_to_surface_mat * root_pos_cu;
+
+ const int mface_i = find_mface_for_root_position(
+ surface_me, poly_to_mface_map[poly_i], root_pos_su);
+ const MFace &mface = surface_me.mface[mface_i];
+
+ const float4 mface_weights = compute_mface_weights_for_position(
+ surface_me, mface, root_pos_su);
+
+ ParticleData &particle = particles[new_hair_i];
+ const int num_keys = points.size();
+ MutableSpan<HairKey> hair_keys{
+ static_cast<HairKey *>(MEM_calloc_arrayN(num_keys, sizeof(HairKey), __func__)),
+ num_keys};
+
+ particle.hair = hair_keys.data();
+ particle.totkey = hair_keys.size();
+ copy_v4_v4(particle.fuv, mface_weights);
+ particle.num = mface_i;
+ /* Not sure if there is a better way to initialize this. */
+ particle.num_dmcache = DMCACHE_NOTFOUND;
+
+ float4x4 hair_to_surface_mat;
+ psys_mat_hair_to_object(
+ &surface_ob, &surface_me, PART_FROM_FACE, &particle, hair_to_surface_mat.values);
+ /* In theory, #psys_mat_hair_to_object should handle this, but it doesn't right now. */
+ copy_v3_v3(hair_to_surface_mat.values[3], root_pos_su);
+ const float4x4 surface_to_hair_mat = hair_to_surface_mat.inverted();
+
+ for (const int key_i : hair_keys.index_range()) {
+ const float3 &key_pos_cu = positions_cu[points[key_i]];
+ const float3 key_pos_su = curves_to_surface_mat * key_pos_cu;
+ const float3 key_pos_ha = surface_to_hair_mat * key_pos_su;
+
+ HairKey &key = hair_keys[key_i];
+ copy_v3_v3(key.co, key_pos_ha);
+ key.time = 100.0f * key_i / (float)(hair_keys.size() - 1);
+ }
+ }
+
+ particle_system->particles = particles.data();
+ particle_system->totpart = particles.size();
+ particle_system->flag |= PSYS_EDITED;
+ particle_system->recalc |= ID_RECALC_PSYS_RESET;
+
+ DEG_id_tag_update(&surface_ob.id, ID_RECALC_GEOMETRY);
+ DEG_id_tag_update(&settings.id, ID_RECALC_COPY_ON_WRITE);
+ }
+ CTX_DATA_END;
+
+ WM_main_add_notifier(NC_OBJECT | ND_PARTICLE | NA_EDITED, NULL);
+
+ return OPERATOR_FINISHED;
+}
+
+static bool curves_convert_to_particle_system_poll(bContext *C)
+{
+ Object *ob = CTX_data_active_object(C);
+ if (ob == nullptr || ob->type != OB_CURVES) {
+ return false;
+ }
+ Curves &curves = *static_cast<Curves *>(ob->data);
+ return curves.surface != nullptr;
+}
+
+} // namespace convert_to_particle_system
+
+static void CURVES_OT_convert_to_particle_system(wmOperatorType *ot)
+{
+ ot->name = "Convert Curves to Particle System";
+ ot->idname = "CURVES_OT_convert_to_particle_system";
+ ot->description = "Add a new or update an existing hair particle system on the surface object";
+
+ ot->poll = convert_to_particle_system::curves_convert_to_particle_system_poll;
+ ot->exec = convert_to_particle_system::curves_convert_to_particle_system_exec;
+
+ ot->flag = OPTYPE_UNDO | OPTYPE_REGISTER;
+}
+
+} // namespace blender::ed::curves
void ED_operatortypes_curves()
{
+ using namespace blender::ed::curves;
+ WM_operatortype_append(CURVES_OT_convert_to_particle_system);
}
diff --git a/source/blender/editors/datafiles/CMakeLists.txt b/source/blender/editors/datafiles/CMakeLists.txt
index d58bbec01cd..e820423cdff 100644
--- a/source/blender/editors/datafiles/CMakeLists.txt
+++ b/source/blender/editors/datafiles/CMakeLists.txt
@@ -191,7 +191,6 @@ set(ICON_NAMES
library_data_broken
boids
strands
- library_data_indirect
greasepencil
line_data
library_data_override
diff --git a/source/blender/editors/geometry/geometry_attributes.cc b/source/blender/editors/geometry/geometry_attributes.cc
index 6225a68f53c..5d9d02db660 100644
--- a/source/blender/editors/geometry/geometry_attributes.cc
+++ b/source/blender/editors/geometry/geometry_attributes.cc
@@ -15,6 +15,7 @@
#include "BKE_context.h"
#include "BKE_deform.h"
#include "BKE_geometry_set.hh"
+#include "BKE_lib_id.h"
#include "BKE_object_deform.h"
#include "BKE_report.h"
@@ -41,8 +42,9 @@ namespace blender::ed::geometry {
static bool geometry_attributes_poll(bContext *C)
{
Object *ob = ED_object_context(C);
+ Main *bmain = CTX_data_main(C);
ID *data = (ob) ? static_cast<ID *>(ob->data) : nullptr;
- return (ob && !ID_IS_LINKED(ob) && data && !ID_IS_LINKED(data)) &&
+ return (ob && BKE_id_is_editable(bmain, &ob->id) && data && BKE_id_is_editable(bmain, data)) &&
BKE_id_attributes_supported(data);
}
diff --git a/source/blender/editors/gpencil/CMakeLists.txt b/source/blender/editors/gpencil/CMakeLists.txt
index f8fa23a54d1..09a3cac0d48 100644
--- a/source/blender/editors/gpencil/CMakeLists.txt
+++ b/source/blender/editors/gpencil/CMakeLists.txt
@@ -28,7 +28,7 @@ set(SRC
gpencil_add_monkey.c
gpencil_add_stroke.c
gpencil_armature.c
- gpencil_bake_animation.c
+ gpencil_bake_animation.cc
gpencil_convert.c
gpencil_data.c
gpencil_edit.c
@@ -36,7 +36,7 @@ set(SRC
gpencil_fill.c
gpencil_interpolate.c
gpencil_merge.c
- gpencil_mesh.c
+ gpencil_mesh.cc
gpencil_ops.c
gpencil_ops_versioning.c
gpencil_paint.c
diff --git a/source/blender/editors/gpencil/gpencil_bake_animation.c b/source/blender/editors/gpencil/gpencil_bake_animation.cc
index 5d33377900f..0667da46e25 100644
--- a/source/blender/editors/gpencil/gpencil_bake_animation.c
+++ b/source/blender/editors/gpencil/gpencil_bake_animation.cc
@@ -61,7 +61,7 @@ const EnumPropertyItem rna_gpencil_reproject_type_items[] = {
0,
"Cursor",
"Reproject the strokes using the orientation of 3D cursor"},
- {0, NULL, 0, NULL, NULL},
+ {0, nullptr, 0, nullptr, nullptr},
};
/* Check frame_end is always > start frame! */
@@ -86,7 +86,7 @@ static bool gpencil_bake_grease_pencil_animation_poll(bContext *C)
}
/* Check if grease pencil or empty for dupli groups. */
- if ((obact == NULL) || (!ELEM(obact->type, OB_GPENCIL, OB_EMPTY))) {
+ if ((obact == nullptr) || (!ELEM(obact->type, OB_GPENCIL, OB_EMPTY))) {
return false;
}
@@ -95,10 +95,10 @@ static bool gpencil_bake_grease_pencil_animation_poll(bContext *C)
return (area && area->spacetype);
}
-typedef struct GpBakeOb {
+struct GpBakeOb {
struct GpBakeOb *next, *prev;
Object *ob;
-} GpBakeOb;
+};
/* Get list of keyframes used by selected objects. */
static void animdata_keyframe_list_get(ListBase *ob_list,
@@ -109,7 +109,7 @@ static void animdata_keyframe_list_get(ListBase *ob_list,
LISTBASE_FOREACH (GpBakeOb *, elem, ob_list) {
Object *ob = elem->ob;
AnimData *adt = BKE_animdata_from_id(&ob->id);
- if ((adt == NULL) || (adt->action == NULL)) {
+ if ((adt == nullptr) || (adt->action == nullptr)) {
continue;
}
LISTBASE_FOREACH (FCurve *, fcurve, &adt->action->curves) {
@@ -131,16 +131,15 @@ static void animdata_keyframe_list_get(ListBase *ob_list,
static void gpencil_bake_duplilist(Depsgraph *depsgraph, Scene *scene, Object *ob, ListBase *list)
{
- GpBakeOb *elem = NULL;
+ GpBakeOb *elem = nullptr;
ListBase *lb;
- DupliObject *dob;
lb = object_duplilist(depsgraph, scene, ob);
- for (dob = lb->first; dob; dob = dob->next) {
+ LISTBASE_FOREACH (DupliObject *, dob, lb) {
if (dob->ob->type != OB_GPENCIL) {
continue;
}
- elem = MEM_callocN(sizeof(GpBakeOb), __func__);
+ elem = MEM_cnew<GpBakeOb>(__func__);
elem->ob = dob->ob;
BLI_addtail(list, elem);
}
@@ -150,13 +149,13 @@ static void gpencil_bake_duplilist(Depsgraph *depsgraph, Scene *scene, Object *o
static void gpencil_bake_ob_list(bContext *C, Depsgraph *depsgraph, Scene *scene, ListBase *list)
{
- GpBakeOb *elem = NULL;
+ GpBakeOb *elem = nullptr;
/* Add active object. In some files this could not be in selected array. */
Object *obact = CTX_data_active_object(C);
if (obact->type == OB_GPENCIL) {
- elem = MEM_callocN(sizeof(GpBakeOb), __func__);
+ elem = MEM_cnew<GpBakeOb>(__func__);
elem->ob = obact;
BLI_addtail(list, elem);
}
@@ -172,7 +171,7 @@ static void gpencil_bake_ob_list(bContext *C, Depsgraph *depsgraph, Scene *scene
}
/* Add selected objects. */
if (ob->type == OB_GPENCIL) {
- elem = MEM_callocN(sizeof(GpBakeOb), __func__);
+ elem = MEM_cnew<GpBakeOb>(__func__);
elem->ob = ob;
BLI_addtail(list, elem);
}
@@ -199,7 +198,7 @@ static int gpencil_bake_grease_pencil_animation_exec(bContext *C, wmOperator *op
Scene *scene = CTX_data_scene(C);
View3D *v3d = CTX_wm_view3d(C);
- ListBase ob_selected_list = {NULL, NULL};
+ ListBase ob_selected_list = {nullptr, nullptr};
gpencil_bake_ob_list(C, depsgraph, scene, &ob_selected_list);
/* Grab all relevant settings. */
@@ -215,10 +214,11 @@ static int gpencil_bake_grease_pencil_animation_exec(bContext *C, wmOperator *op
const bool only_selected = RNA_boolean_get(op->ptr, "only_selected");
const int frame_offset = RNA_int_get(op->ptr, "frame_target") - frame_start;
- const int project_type = RNA_enum_get(op->ptr, "project_type");
+ const eGP_ReprojectModes project_type = (eGP_ReprojectModes)RNA_enum_get(op->ptr,
+ "project_type");
/* Create a new grease pencil object. */
- Object *ob_gpencil = NULL;
+ Object *ob_gpencil = nullptr;
ushort local_view_bits = (v3d && v3d->localvd) ? v3d->local_view_uuid : 0;
ob_gpencil = ED_gpencil_add_object(C, scene->cursor.location, local_view_bits);
float invmat[4][4];
@@ -230,8 +230,8 @@ static int gpencil_bake_grease_pencil_animation_exec(bContext *C, wmOperator *op
/* Set cursor to indicate working. */
WM_cursor_wait(true);
- GP_SpaceConversion gsc = {NULL};
- SnapObjectContext *sctx = NULL;
+ GP_SpaceConversion gsc = {nullptr};
+ SnapObjectContext *sctx = nullptr;
if (project_type != GP_REPROJECT_KEEP) {
/* Init space conversion stuff. */
gpencil_point_conversion_init(C, &gsc);
@@ -271,14 +271,14 @@ static int gpencil_bake_grease_pencil_animation_exec(bContext *C, wmOperator *op
/* Loop all objects in the list. */
LISTBASE_FOREACH (GpBakeOb *, elem, &ob_selected_list) {
Object *ob_eval = (Object *)DEG_get_evaluated_object(depsgraph, elem->ob);
- bGPdata *gpd_src = ob_eval->data;
+ bGPdata *gpd_src = static_cast<bGPdata *>(ob_eval->data);
LISTBASE_FOREACH (bGPDlayer *, gpl_src, &gpd_src->layers) {
/* Create destination layer. */
char *layer_name;
layer_name = BLI_sprintfN("%s_%s", elem->ob->id.name + 2, gpl_src->info);
bGPDlayer *gpl_dst = BKE_gpencil_layer_named_get(gpd_dst, layer_name);
- if (gpl_dst == NULL) {
+ if (gpl_dst == nullptr) {
gpl_dst = BKE_gpencil_layer_addnew(gpd_dst, layer_name, true, false);
}
MEM_freeN(layer_name);
@@ -293,7 +293,7 @@ static int gpencil_bake_grease_pencil_animation_exec(bContext *C, wmOperator *op
/* Duplicate frame. */
bGPDframe *gpf_src = BKE_gpencil_layer_frame_get(
gpl_src, remap_cfra, GP_GETFRAME_USE_PREV);
- if (gpf_src == NULL) {
+ if (gpf_src == nullptr) {
continue;
}
bGPDframe *gpf_dst = BKE_gpencil_frame_duplicate(gpf_src, true);
@@ -346,19 +346,19 @@ static int gpencil_bake_grease_pencil_animation_exec(bContext *C, wmOperator *op
/* Free memory. */
gpencil_bake_free_ob_list(&ob_selected_list);
- if (sctx != NULL) {
+ if (sctx != nullptr) {
ED_transform_snap_object_context_destroy(sctx);
}
/* Free temp hash table. */
- if (keyframe_list != NULL) {
- BLI_ghash_free(keyframe_list, NULL, NULL);
+ if (keyframe_list != nullptr) {
+ BLI_ghash_free(keyframe_list, nullptr, nullptr);
}
/* Notifiers. */
DEG_relations_tag_update(bmain);
DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
DEG_id_tag_update(&gpd_dst->id, ID_RECALC_COPY_ON_WRITE);
- WM_event_add_notifier(C, NC_OBJECT | NA_ADDED, NULL);
+ WM_event_add_notifier(C, NC_OBJECT | NA_ADDED, nullptr);
WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene);
/* Reset cursor. */
@@ -418,12 +418,15 @@ void GPENCIL_OT_bake_grease_pencil_animation(wmOperatorType *ot)
prop = RNA_def_int(
ot->srna, "frame_end", 250, 1, 100000, "End Frame", "The end frame of animation", 1, 100000);
- RNA_def_property_update_runtime(prop, gpencil_bake_set_frame_end);
+ RNA_def_property_update_runtime(prop, (void *)gpencil_bake_set_frame_end);
prop = RNA_def_int(ot->srna, "step", 1, 1, 100, "Step", "Step between generated frames", 1, 100);
- RNA_def_boolean(
- ot->srna, "only_selected", 0, "Only Selected Keyframes", "Convert only selected keyframes");
+ RNA_def_boolean(ot->srna,
+ "only_selected",
+ false,
+ "Only Selected Keyframes",
+ "Convert only selected keyframes");
RNA_def_int(
ot->srna, "frame_target", 1, 1, 100000, "Target Frame", "Destination frame", 1, 100000);
diff --git a/source/blender/editors/gpencil/gpencil_data.c b/source/blender/editors/gpencil/gpencil_data.c
index 338a7c8a51d..6843c42d2d0 100644
--- a/source/blender/editors/gpencil/gpencil_data.c
+++ b/source/blender/editors/gpencil/gpencil_data.c
@@ -2195,8 +2195,9 @@ static bool gpencil_vertex_group_poll(bContext *C)
Object *ob = CTX_data_active_object(C);
if ((ob) && (ob->type == OB_GPENCIL)) {
+ Main *bmain = CTX_data_main(C);
const bGPdata *gpd = (const bGPdata *)ob->data;
- if (!ID_IS_LINKED(ob) && !ID_IS_LINKED(ob->data) &&
+ if (BKE_id_is_editable(bmain, &ob->id) && BKE_id_is_editable(bmain, ob->data) &&
!BLI_listbase_is_empty(&gpd->vertex_group_names)) {
if (ELEM(ob->mode, OB_MODE_EDIT_GPENCIL, OB_MODE_SCULPT_GPENCIL)) {
return true;
@@ -2212,8 +2213,9 @@ static bool gpencil_vertex_group_weight_poll(bContext *C)
Object *ob = CTX_data_active_object(C);
if ((ob) && (ob->type == OB_GPENCIL)) {
+ Main *bmain = CTX_data_main(C);
const bGPdata *gpd = (const bGPdata *)ob->data;
- if (!ID_IS_LINKED(ob) && !ID_IS_LINKED(ob->data) &&
+ if (BKE_id_is_editable(bmain, &ob->id) && BKE_id_is_editable(bmain, ob->data) &&
!BLI_listbase_is_empty(&gpd->vertex_group_names)) {
if (ob->mode == OB_MODE_WEIGHT_GPENCIL) {
return true;
diff --git a/source/blender/editors/gpencil/gpencil_fill.c b/source/blender/editors/gpencil/gpencil_fill.c
index 8fc300412d9..3f06dbfdbb3 100644
--- a/source/blender/editors/gpencil/gpencil_fill.c
+++ b/source/blender/editors/gpencil/gpencil_fill.c
@@ -2108,18 +2108,18 @@ static bool gpencil_do_frame_fill(tGPDfill *tgpf, const bool is_inverted)
int totpoints_prv = 0;
int loop_limit = 0;
while (totpoints > 0) {
- /* analyze outline */
+ /* Analyze outline. */
gpencil_get_outline_points(tgpf, (totpoints == 1) ? true : false);
- /* create array of points from stack */
+ /* Create array of points from stack. */
totpoints = gpencil_points_from_stack(tgpf);
+ if (totpoints > 0) {
+ /* Create z-depth array for reproject. */
+ gpencil_get_depth_array(tgpf);
- /* create z-depth array for reproject */
- gpencil_get_depth_array(tgpf);
-
- /* create stroke and reproject */
- gpencil_stroke_from_buffer(tgpf);
-
+ /* Create stroke and reproject. */
+ gpencil_stroke_from_buffer(tgpf);
+ }
if (is_inverted) {
gpencil_erase_processed_area(tgpf);
}
@@ -2222,7 +2222,7 @@ static int gpencil_fill_modal(bContext *C, wmOperator *op, const wmEvent *event)
/* Hash of selected frames. */
GHash *frame_list = BLI_ghash_int_new_ex(__func__, 64);
- /* If not multiframe and there is no frame in CFRA for the active layer, create
+ /* If not multi-frame and there is no frame in CFRA for the active layer, create
* a new frame. */
if (!is_multiedit) {
tgpf->gpf = BKE_gpencil_layer_frame_get(
diff --git a/source/blender/editors/gpencil/gpencil_intern.h b/source/blender/editors/gpencil/gpencil_intern.h
index 1bb98ce51c7..56c94e4494d 100644
--- a/source/blender/editors/gpencil/gpencil_intern.h
+++ b/source/blender/editors/gpencil/gpencil_intern.h
@@ -13,6 +13,10 @@
#define DEPTH_INVALID 1.0f
+#ifdef __cplusplus
+extern "C" {
+#endif
+
/* internal exports only */
struct Material;
struct bGPDspoint;
@@ -826,3 +830,7 @@ struct GP_EditableStrokes_Iter {
extern const EnumPropertyItem rna_gpencil_reproject_type_items[];
/* ****************************************************** */
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/editors/gpencil/gpencil_mesh.c b/source/blender/editors/gpencil/gpencil_mesh.cc
index 7db55796053..aee00d4ede3 100644
--- a/source/blender/editors/gpencil/gpencil_mesh.c
+++ b/source/blender/editors/gpencil/gpencil_mesh.cc
@@ -67,10 +67,10 @@ static bool gpencil_bake_mesh_animation_poll(bContext *C)
return (area && area->spacetype);
}
-typedef struct GpBakeOb {
+struct GpBakeOb {
struct GpBakeOb *next, *prev;
Object *ob;
-} GpBakeOb;
+};
/* Get list of keyframes used by selected objects. */
static void animdata_keyframe_list_get(ListBase *ob_list,
@@ -81,7 +81,7 @@ static void animdata_keyframe_list_get(ListBase *ob_list,
LISTBASE_FOREACH (GpBakeOb *, elem, ob_list) {
Object *ob = elem->ob;
AnimData *adt = BKE_animdata_from_id(&ob->id);
- if ((adt == NULL) || (adt->action == NULL)) {
+ if ((adt == nullptr) || (adt->action == nullptr)) {
continue;
}
LISTBASE_FOREACH (FCurve *, fcurve, &adt->action->curves) {
@@ -103,15 +103,14 @@ static void animdata_keyframe_list_get(ListBase *ob_list,
static void gpencil_bake_duplilist(Depsgraph *depsgraph, Scene *scene, Object *ob, ListBase *list)
{
- GpBakeOb *elem = NULL;
+ GpBakeOb *elem = nullptr;
ListBase *lb;
- DupliObject *dob;
lb = object_duplilist(depsgraph, scene, ob);
- for (dob = lb->first; dob; dob = dob->next) {
+ LISTBASE_FOREACH (DupliObject *, dob, lb) {
if (dob->ob->type != OB_MESH) {
continue;
}
- elem = MEM_callocN(sizeof(GpBakeOb), __func__);
+ elem = MEM_cnew<GpBakeOb>(__func__);
elem->ob = dob->ob;
BLI_addtail(list, elem);
}
@@ -121,17 +120,17 @@ static void gpencil_bake_duplilist(Depsgraph *depsgraph, Scene *scene, Object *o
static bool gpencil_bake_ob_list(bContext *C, Depsgraph *depsgraph, Scene *scene, ListBase *list)
{
- GpBakeOb *elem = NULL;
+ GpBakeOb *elem = nullptr;
bool simple_material = false;
/* Add active object. In some files this could not be in selected array. */
Object *obact = CTX_data_active_object(C);
- if (obact == NULL) {
+ if (obact == nullptr) {
return false;
}
if (obact->type == OB_MESH) {
- elem = MEM_callocN(sizeof(GpBakeOb), __func__);
+ elem = MEM_cnew<GpBakeOb>(__func__);
elem->ob = obact;
BLI_addtail(list, elem);
}
@@ -148,7 +147,7 @@ static bool gpencil_bake_ob_list(bContext *C, Depsgraph *depsgraph, Scene *scene
}
/* Add selected meshes. */
if (ob->type == OB_MESH) {
- elem = MEM_callocN(sizeof(GpBakeOb), __func__);
+ elem = MEM_cnew<GpBakeOb>(__func__);
elem->ob = ob;
BLI_addtail(list, elem);
}
@@ -177,11 +176,11 @@ static int gpencil_bake_mesh_animation_exec(bContext *C, wmOperator *op)
Scene *scene = CTX_data_scene(C);
View3D *v3d = CTX_wm_view3d(C);
- ListBase ob_selected_list = {NULL, NULL};
+ ListBase ob_selected_list = {nullptr, nullptr};
gpencil_bake_ob_list(C, depsgraph, scene, &ob_selected_list);
/* Cannot check this in poll because the active object changes. */
- if (ob_selected_list.first == NULL) {
+ if (ob_selected_list.first == nullptr) {
BKE_report(op->reports, RPT_INFO, "No valid object selected");
gpencil_bake_free_ob_list(&ob_selected_list);
return OPERATOR_CANCELLED;
@@ -205,28 +204,29 @@ static int gpencil_bake_mesh_animation_exec(bContext *C, wmOperator *op)
const bool only_selected = RNA_boolean_get(op->ptr, "only_selected");
const float offset = RNA_float_get(op->ptr, "offset");
const int frame_offset = RNA_int_get(op->ptr, "frame_target") - frame_start;
- const int project_type = RNA_enum_get(op->ptr, "project_type");
- eGP_TargetObjectMode target = RNA_enum_get(op->ptr, "target");
+ const eGP_ReprojectModes project_type = (eGP_ReprojectModes)RNA_enum_get(op->ptr,
+ "project_type");
+ const eGP_TargetObjectMode target = (eGP_TargetObjectMode)RNA_enum_get(op->ptr, "target");
/* Create a new grease pencil object in origin or reuse selected. */
- Object *ob_gpencil = NULL;
+ Object *ob_gpencil = nullptr;
bool newob = false;
if (target == GP_TARGET_OB_SELECTED) {
ob_gpencil = BKE_view_layer_non_active_selected_object(CTX_data_view_layer(C), v3d);
- if (ob_gpencil != NULL) {
+ if (ob_gpencil != nullptr) {
if (ob_gpencil->type != OB_GPENCIL) {
BKE_report(op->reports, RPT_WARNING, "Target object not a grease pencil, ignoring!");
- ob_gpencil = NULL;
+ ob_gpencil = nullptr;
}
else if (BKE_object_obdata_is_libdata(ob_gpencil)) {
BKE_report(op->reports, RPT_WARNING, "Target object library-data, ignoring!");
- ob_gpencil = NULL;
+ ob_gpencil = nullptr;
}
}
}
- if (ob_gpencil == NULL) {
+ if (ob_gpencil == nullptr) {
ushort local_view_bits = (v3d && v3d->localvd) ? v3d->local_view_uuid : 0;
const float loc[3] = {0.0f, 0.0f, 0.0f};
ob_gpencil = ED_gpencil_add_object(C, loc, local_view_bits);
@@ -239,8 +239,8 @@ static int gpencil_bake_mesh_animation_exec(bContext *C, wmOperator *op)
/* Set cursor to indicate working. */
WM_cursor_wait(true);
- GP_SpaceConversion gsc = {NULL};
- SnapObjectContext *sctx = NULL;
+ GP_SpaceConversion gsc = {nullptr};
+ SnapObjectContext *sctx = nullptr;
if (project_type != GP_REPROJECT_KEEP) {
/* Init space conversion stuff. */
gpencil_point_conversion_init(C, &gsc);
@@ -309,7 +309,7 @@ static int gpencil_bake_mesh_animation_exec(bContext *C, wmOperator *op)
if (project_type != GP_REPROJECT_KEEP) {
LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
bGPDframe *gpf = gpl->actframe;
- if (gpf == NULL) {
+ if (gpf == nullptr) {
continue;
}
LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
@@ -355,12 +355,12 @@ static int gpencil_bake_mesh_animation_exec(bContext *C, wmOperator *op)
/* Free memory. */
gpencil_bake_free_ob_list(&ob_selected_list);
- if (sctx != NULL) {
+ if (sctx != nullptr) {
ED_transform_snap_object_context_destroy(sctx);
}
/* Free temp hash table. */
- if (keyframe_list != NULL) {
- BLI_ghash_free(keyframe_list, NULL, NULL);
+ if (keyframe_list != nullptr) {
+ BLI_ghash_free(keyframe_list, nullptr, nullptr);
}
/* notifiers */
@@ -368,7 +368,7 @@ static int gpencil_bake_mesh_animation_exec(bContext *C, wmOperator *op)
DEG_relations_tag_update(bmain);
}
DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_OBJECT | NA_ADDED, NULL);
+ WM_event_add_notifier(C, NC_OBJECT | NA_ADDED, nullptr);
WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene);
/* Reset cursor. */
@@ -392,7 +392,7 @@ void GPENCIL_OT_bake_mesh_animation(wmOperatorType *ot)
static const EnumPropertyItem target_object_modes[] = {
{GP_TARGET_OB_NEW, "NEW", 0, "New Object", ""},
{GP_TARGET_OB_SELECTED, "SELECTED", 0, "Selected Object", ""},
- {0, NULL, 0, NULL, NULL},
+ {0, nullptr, 0, nullptr, nullptr},
};
PropertyRNA *prop;
@@ -424,7 +424,7 @@ void GPENCIL_OT_bake_mesh_animation(wmOperatorType *ot)
prop = RNA_def_int(
ot->srna, "frame_end", 250, 1, 100000, "End Frame", "The end frame of animation", 1, 100000);
- RNA_def_property_update_runtime(prop, gpencil_bake_set_frame_end);
+ RNA_def_property_update_runtime(prop, (void *)gpencil_bake_set_frame_end);
prop = RNA_def_int(ot->srna, "step", 1, 1, 100, "Step", "Step between generated frames", 1, 100);
@@ -433,7 +433,7 @@ void GPENCIL_OT_bake_mesh_animation(wmOperatorType *ot)
prop = RNA_def_float_rotation(ot->srna,
"angle",
0,
- NULL,
+ nullptr,
DEG2RADF(0.0f),
DEG2RADF(180.0f),
"Threshold Angle",
@@ -452,10 +452,13 @@ void GPENCIL_OT_bake_mesh_animation(wmOperatorType *ot)
0.0,
100.00);
- RNA_def_boolean(ot->srna, "seams", 0, "Only Seam Edges", "Convert only seam edges");
- RNA_def_boolean(ot->srna, "faces", 1, "Export Faces", "Export faces as filled strokes");
- RNA_def_boolean(
- ot->srna, "only_selected", 0, "Only Selected Keyframes", "Convert only selected keyframes");
+ RNA_def_boolean(ot->srna, "seams", false, "Only Seam Edges", "Convert only seam edges");
+ RNA_def_boolean(ot->srna, "faces", true, "Export Faces", "Export faces as filled strokes");
+ RNA_def_boolean(ot->srna,
+ "only_selected",
+ false,
+ "Only Selected Keyframes",
+ "Convert only selected keyframes");
RNA_def_int(
ot->srna, "frame_target", 1, 1, 100000, "Target Frame", "Destination frame", 1, 100000);
diff --git a/source/blender/editors/gpencil/gpencil_primitive.c b/source/blender/editors/gpencil/gpencil_primitive.c
index 57a184b0e8d..b57b8145749 100644
--- a/source/blender/editors/gpencil/gpencil_primitive.c
+++ b/source/blender/editors/gpencil/gpencil_primitive.c
@@ -1401,7 +1401,7 @@ static void gpencil_primitive_interaction_end(bContext *C,
BKE_gpencil_stroke_geometry_update(tgpi->gpd, gps);
}
- /* In Multiframe mode, duplicate the stroke in other frames. */
+ /* In Multi-frame mode, duplicate the stroke in other frames. */
if (GPENCIL_MULTIEDIT_SESSIONS_ON(tgpi->gpd)) {
const bool tail = (ts->gpencil_flags & GP_TOOL_FLAG_PAINT_ONBACK);
BKE_gpencil_stroke_copy_to_keyframes(tgpi->gpd, tgpi->gpl, gpf, gps, tail);
@@ -1481,7 +1481,7 @@ static void gpencil_primitive_edit_event_handling(
break;
}
case MOUSEMOVE: {
- if ((event->val == KM_PRESS) && tgpi->sel_cp != SELECT_NONE) {
+ if (tgpi->sel_cp != SELECT_NONE) {
if (tgpi->sel_cp == SELECT_START && tgpi->tot_stored_edges == 0) {
copy_v2_v2(tgpi->start, tgpi->mval);
}
diff --git a/source/blender/editors/gpencil/gpencil_sculpt_paint.c b/source/blender/editors/gpencil/gpencil_sculpt_paint.c
index 1e7159392e2..7de579993c1 100644
--- a/source/blender/editors/gpencil/gpencil_sculpt_paint.c
+++ b/source/blender/editors/gpencil/gpencil_sculpt_paint.c
@@ -1442,20 +1442,22 @@ static bool gpencil_sculpt_brush_do_stroke(tGP_BrushEditData *gso,
if (gps->totpoints == 1) {
bGPDspoint pt_temp;
pt = &gps->points[0];
- gpencil_point_to_parent_space(gps->points, diff_mat, &pt_temp);
- gpencil_point_to_xy(gsc, gps, &pt_temp, &pc1[0], &pc1[1]);
-
- pt_active = (pt->runtime.pt_orig) ? pt->runtime.pt_orig : pt;
- /* Do bound-box check first. */
- if ((!ELEM(V2D_IS_CLIPPED, pc1[0], pc1[1])) && BLI_rcti_isect_pt(rect, pc1[0], pc1[1])) {
- /* only check if point is inside */
- int mval_i[2];
- round_v2i_v2fl(mval_i, gso->mval);
- if (len_v2v2_int(mval_i, pc1) <= radius) {
- /* apply operation to this point */
- if (pt_active != NULL) {
- rot_eval = gpencil_sculpt_rotation_eval_get(gso, gps, pt, 0);
- changed = apply(gso, gps_active, rot_eval, 0, radius, pc1);
+ if (GPENCIL_ANY_SCULPT_MASK(gso->mask) && (pt->flag & GP_SPOINT_SELECT) != 0) {
+ gpencil_point_to_parent_space(gps->points, diff_mat, &pt_temp);
+ gpencil_point_to_xy(gsc, gps, &pt_temp, &pc1[0], &pc1[1]);
+
+ pt_active = (pt->runtime.pt_orig) ? pt->runtime.pt_orig : pt;
+ /* Do bound-box check first. */
+ if ((!ELEM(V2D_IS_CLIPPED, pc1[0], pc1[1])) && BLI_rcti_isect_pt(rect, pc1[0], pc1[1])) {
+ /* only check if point is inside */
+ int mval_i[2];
+ round_v2i_v2fl(mval_i, gso->mval);
+ if (len_v2v2_int(mval_i, pc1) <= radius) {
+ /* apply operation to this point */
+ if (pt_active != NULL) {
+ rot_eval = gpencil_sculpt_rotation_eval_get(gso, gps, pt, 0);
+ changed = apply(gso, gps_active, rot_eval, 0, radius, pc1);
+ }
}
}
}
diff --git a/source/blender/editors/gpencil/gpencil_select.c b/source/blender/editors/gpencil/gpencil_select.c
index fca4ff84dc5..d962dcdfa10 100644
--- a/source/blender/editors/gpencil/gpencil_select.c
+++ b/source/blender/editors/gpencil/gpencil_select.c
@@ -2651,7 +2651,7 @@ static int gpencil_select_exec(bContext *C, wmOperator *op)
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, NULL);
}
- return OPERATOR_FINISHED;
+ return OPERATOR_PASS_THROUGH | OPERATOR_FINISHED;
}
static int gpencil_select_invoke(bContext *C, wmOperator *op, const wmEvent *event)
@@ -2662,7 +2662,9 @@ static int gpencil_select_invoke(bContext *C, wmOperator *op, const wmEvent *eve
RNA_boolean_set(op->ptr, "use_shift_extend", event->modifier & KM_SHIFT);
}
- return gpencil_select_exec(C, op);
+ const int retval = gpencil_select_exec(C, op);
+
+ return WM_operator_flag_only_pass_through_on_press(retval, event);
}
void GPENCIL_OT_select(wmOperatorType *ot)
diff --git a/source/blender/editors/gpencil/gpencil_utils.c b/source/blender/editors/gpencil/gpencil_utils.c
index 69ea58eee02..2dc12125f40 100644
--- a/source/blender/editors/gpencil/gpencil_utils.c
+++ b/source/blender/editors/gpencil/gpencil_utils.c
@@ -1423,7 +1423,7 @@ void ED_gpencil_add_defaults(bContext *C, Object *ob)
/* ensure a color exists and is assigned to object */
BKE_gpencil_object_material_ensure_from_active_input_toolsettings(bmain, ob, ts);
- /* ensure multiframe falloff curve */
+ /* Ensure multi-frame falloff curve. */
if (ts->gp_sculpt.cur_falloff == NULL) {
ts->gp_sculpt.cur_falloff = BKE_curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f);
CurveMapping *gp_falloff_curve = ts->gp_sculpt.cur_falloff;
diff --git a/source/blender/editors/gpencil/gpencil_vertex_paint.c b/source/blender/editors/gpencil/gpencil_vertex_paint.c
index b4cfc7f3a08..c221d8e25e4 100644
--- a/source/blender/editors/gpencil/gpencil_vertex_paint.c
+++ b/source/blender/editors/gpencil/gpencil_vertex_paint.c
@@ -738,7 +738,7 @@ static bool gpencil_vertexpaint_brush_init(bContext *C, wmOperator *op)
/* Save mask. */
gso->mask = ts->gpencil_selectmode_vertex;
- /* Multiframe settings. */
+ /* Multi-frame settings. */
gso->is_multiframe = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gso->gpd);
gso->use_multiframe_falloff = (ts->gp_sculpt.flag & GP_SCULPT_SETT_FLAG_FRAME_FALLOFF) != 0;
diff --git a/source/blender/editors/gpencil/gpencil_weight_paint.c b/source/blender/editors/gpencil/gpencil_weight_paint.c
index bceec7a638e..22fbf0021fc 100644
--- a/source/blender/editors/gpencil/gpencil_weight_paint.c
+++ b/source/blender/editors/gpencil/gpencil_weight_paint.c
@@ -322,7 +322,7 @@ static bool gpencil_weightpaint_brush_init(bContext *C, wmOperator *op)
gso->region = CTX_wm_region(C);
- /* Multiframe settings. */
+ /* Multi-frame settings. */
gso->is_multiframe = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gso->gpd);
gso->use_multiframe_falloff = (ts->gp_sculpt.flag & GP_SCULPT_SETT_FLAG_FRAME_FALLOFF) != 0;
diff --git a/source/blender/editors/include/ED_fileselect.h b/source/blender/editors/include/ED_fileselect.h
index 6a207a6e453..c367072e6e7 100644
--- a/source/blender/editors/include/ED_fileselect.h
+++ b/source/blender/editors/include/ED_fileselect.h
@@ -216,6 +216,8 @@ typedef enum FSMenuInsert {
FS_INSERT_FIRST = (1 << 2),
/** just append to preserve delivered order */
FS_INSERT_LAST = (1 << 3),
+ /** Do not validate the link when inserted. */
+ FS_INSERT_NO_VALIDATE = (1 << 4),
} FSMenuInsert;
struct FSMenu;
diff --git a/source/blender/editors/include/ED_node.h b/source/blender/editors/include/ED_node.h
index 8c9fa7e4494..c30b8c5ec6a 100644
--- a/source/blender/editors/include/ED_node.h
+++ b/source/blender/editors/include/ED_node.h
@@ -33,7 +33,7 @@ typedef enum {
NODE_RIGHT = 8,
} NodeBorder;
-#define NODE_GRID_STEP_SIZE 10
+#define NODE_GRID_STEP_SIZE U.widget_unit /* Based on the grid nodes snap to. */
#define NODE_EDGE_PAN_INSIDE_PAD 2
#define NODE_EDGE_PAN_OUTSIDE_PAD 0 /* Disable clamping for node panning, use whole screen. */
#define NODE_EDGE_PAN_SPEED_RAMP 1
diff --git a/source/blender/editors/include/ED_object.h b/source/blender/editors/include/ED_object.h
index abadbe5a5c6..54e434e0db5 100644
--- a/source/blender/editors/include/ED_object.h
+++ b/source/blender/editors/include/ED_object.h
@@ -381,6 +381,8 @@ struct Object *ED_object_add_type(struct bContext *C,
*/
void ED_object_single_user(struct Main *bmain, struct Scene *scene, struct Object *ob);
+void ED_object_single_obdata_user(struct Main *bmain, struct Scene *scene, struct Object *ob);
+
/* object motion paths */
/**
diff --git a/source/blender/editors/include/ED_select_utils.h b/source/blender/editors/include/ED_select_utils.h
index b9ef5c283aa..dbe1b582132 100644
--- a/source/blender/editors/include/ED_select_utils.h
+++ b/source/blender/editors/include/ED_select_utils.h
@@ -6,11 +6,14 @@
#pragma once
+#include "BLI_compiler_attrs.h"
+
#ifdef __cplusplus
extern "C" {
#endif
struct KDTree_1d;
+struct wmOperator;
enum {
SEL_TOGGLE = 0,
@@ -93,7 +96,15 @@ struct SelectPick_Params {
/**
* Utility to get #eSelectPickMode from booleans for convenience.
*/
-eSelectOp ED_select_op_from_booleans(bool extend, bool deselect, bool toggle);
+eSelectOp ED_select_op_from_operator(struct wmOperator *op)
+ ATTR_NONNULL(1) ATTR_WARN_UNUSED_RESULT;
+
+/**
+ * Initialize `params` from `op`,
+ * these properties are defined by #WM_operator_properties_mouse_select.
+ */
+void ED_select_pick_params_from_operator(struct wmOperator *op, struct SelectPick_Params *params)
+ ATTR_NONNULL(1, 2);
#ifdef __cplusplus
}
diff --git a/source/blender/editors/include/ED_transform_snap_object_context.h b/source/blender/editors/include/ED_transform_snap_object_context.h
index fa53e7a76e4..2919001c5ce 100644
--- a/source/blender/editors/include/ED_transform_snap_object_context.h
+++ b/source/blender/editors/include/ED_transform_snap_object_context.h
@@ -21,19 +21,19 @@ struct Object;
struct Scene;
struct View3D;
-/* transform_snap_object.c */
+/* transform_snap_object.cc */
/* ED_transform_snap_object_*** API */
-typedef enum {
+typedef enum eSnapSelect {
SNAP_ALL = 0,
SNAP_NOT_SELECTED = 1,
SNAP_NOT_ACTIVE = 2,
- SNAP_ONLY_ACTIVE = 3,
+ SNAP_NOT_EDITED = 3,
SNAP_SELECTABLE = 4,
} eSnapSelect;
-typedef enum {
+typedef enum eSnapEditType {
SNAP_GEOM_FINAL = 0,
SNAP_GEOM_CAGE = 1,
SNAP_GEOM_EDIT = 2, /* Bmesh for mesh-type. */
@@ -59,13 +59,13 @@ struct SnapObjectHitDepth {
/** parameters that define which objects will be used to snap. */
struct SnapObjectParams {
/* Special context sensitive handling for the active or selected object. */
- char snap_select;
+ eSnapSelect snap_select;
/* Geometry for snapping in edit mode. */
- char edit_mode_type;
+ eSnapEditType edit_mode_type;
/* snap to the closest element, use when using more than one snap type */
- unsigned int use_occlusion_test : 1;
+ bool use_occlusion_test : true;
/* exclude back facing geometry from snapping */
- unsigned int use_backface_culling : 1;
+ bool use_backface_culling : true;
};
typedef struct SnapObjectContext SnapObjectContext;
diff --git a/source/blender/editors/include/ED_view3d.h b/source/blender/editors/include/ED_view3d.h
index 14cb02121bf..b10dbf3084a 100644
--- a/source/blender/editors/include/ED_view3d.h
+++ b/source/blender/editors/include/ED_view3d.h
@@ -273,9 +273,8 @@ typedef enum {
V3D_SNAPCURSOR_TOGGLE_ALWAYS_TRUE = 1 << 0,
V3D_SNAPCURSOR_OCCLUSION_ALWAYS_TRUE = 1 << 1,
V3D_SNAPCURSOR_OCCLUSION_ALWAYS_FALSE = 1 << 2, /* TODO. */
- V3D_SNAPCURSOR_SNAP_ONLY_ACTIVE = 1 << 3,
- V3D_SNAPCURSOR_SNAP_EDIT_GEOM_FINAL = 1 << 4,
- V3D_SNAPCURSOR_SNAP_EDIT_GEOM_CAGE = 1 << 5,
+ V3D_SNAPCURSOR_SNAP_EDIT_GEOM_FINAL = 1 << 3,
+ V3D_SNAPCURSOR_SNAP_EDIT_GEOM_CAGE = 1 << 4,
} eV3DSnapCursor;
typedef enum {
diff --git a/source/blender/editors/include/UI_icons.h b/source/blender/editors/include/UI_icons.h
index a560208ac1e..94232a5108d 100644
--- a/source/blender/editors/include/UI_icons.h
+++ b/source/blender/editors/include/UI_icons.h
@@ -246,7 +246,7 @@ DEF_ICON(RENDER_STILL)
DEF_ICON(LIBRARY_DATA_BROKEN)
DEF_ICON(BOIDS)
DEF_ICON(STRANDS)
-DEF_ICON(LIBRARY_DATA_INDIRECT)
+DEF_ICON_BLANK(263)
DEF_ICON(GREASEPENCIL)
DEF_ICON_SHADING(LINE_DATA)
DEF_ICON(LIBRARY_DATA_OVERRIDE)
@@ -981,6 +981,9 @@ DEF_ICON_VECTOR(SEQUENCE_COLOR_07)
DEF_ICON_VECTOR(SEQUENCE_COLOR_08)
DEF_ICON_VECTOR(SEQUENCE_COLOR_09)
+DEF_ICON_VECTOR(LIBRARY_DATA_INDIRECT)
+DEF_ICON_VECTOR(LIBRARY_DATA_OVERRIDE_NONEDITABLE)
+
/* Events. */
DEF_ICON_COLOR(EVENT_A)
DEF_ICON_COLOR(EVENT_B)
diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h
index d8415064d2f..ce86cdfc226 100644
--- a/source/blender/editors/include/UI_interface.h
+++ b/source/blender/editors/include/UI_interface.h
@@ -634,7 +634,7 @@ uiPopupMenu *UI_popup_menu_begin_ex(struct bContext *C,
* Set the whole structure to work.
*/
void UI_popup_menu_end(struct bContext *C, struct uiPopupMenu *pup);
-bool UI_popup_menu_end_or_cancel(struct bContext *C, struct uiPopupMenu *head);
+bool UI_popup_menu_end_or_cancel(struct bContext *C, struct uiPopupMenu *pup);
struct uiLayout *UI_popup_menu_layout(uiPopupMenu *pup);
void UI_popup_menu_reports(struct bContext *C, struct ReportList *reports) ATTR_NONNULL();
@@ -1595,13 +1595,15 @@ typedef enum {
} eButLabelAlign;
/* Return info for uiDefAutoButsRNA */
-typedef enum {
+typedef enum eAutoPropButsReturn {
/* Returns when no buttons were added */
UI_PROP_BUTS_NONE_ADDED = 1 << 0,
/* Returned when any property failed the custom check callback (check_prop) */
UI_PROP_BUTS_ANY_FAILED_CHECK = 1 << 1,
} eAutoPropButsReturn;
+ENUM_OPERATORS(eAutoPropButsReturn, UI_PROP_BUTS_ANY_FAILED_CHECK);
+
uiBut *uiDefAutoButR(uiBlock *block,
struct PointerRNA *ptr,
struct PropertyRNA *prop,
diff --git a/source/blender/editors/include/UI_view2d.h b/source/blender/editors/include/UI_view2d.h
index b69d3008f1d..4282465c0ca 100644
--- a/source/blender/editors/include/UI_view2d.h
+++ b/source/blender/editors/include/UI_view2d.h
@@ -178,12 +178,12 @@ void UI_view2d_multi_grid_draw(
* \param grid_color_id: The theme color used for the points. Faded dynamically based on zoom.
* \param min_step: The base size of the grid. At different zoom levels, the visible grid may have
* a larger step size.
- * \param grid_levels: The maximum grid depth. Larger grid levels will subdivide the grid more.
+ * \param grid_subdivisions: The maximum number of sub-levels drawn at once.
*/
void UI_view2d_dot_grid_draw(const struct View2D *v2d,
int grid_color_id,
float min_step,
- int grid_levels);
+ int grid_subdivisions);
void UI_view2d_draw_lines_y__values(const struct View2D *v2d);
void UI_view2d_draw_lines_x__values(const struct View2D *v2d);
diff --git a/source/blender/editors/interface/CMakeLists.txt b/source/blender/editors/interface/CMakeLists.txt
index 14d8e136061..8a45768f3dc 100644
--- a/source/blender/editors/interface/CMakeLists.txt
+++ b/source/blender/editors/interface/CMakeLists.txt
@@ -46,17 +46,17 @@ set(SRC
interface_layout.c
interface_ops.c
interface_panel.c
- interface_query.c
- interface_region_color_picker.c
- interface_region_hud.c
- interface_region_menu_pie.c
- interface_region_menu_popup.c
- interface_region_popover.c
- interface_region_popup.c
+ interface_query.cc
+ interface_region_color_picker.cc
+ interface_region_hud.cc
+ interface_region_menu_pie.cc
+ interface_region_menu_popup.cc
+ interface_region_popover.cc
+ interface_region_popup.cc
interface_region_search.cc
interface_region_tooltip.c
- interface_regions.c
- interface_style.c
+ interface_regions.cc
+ interface_style.cc
interface_template_asset_view.cc
interface_template_attribute_search.cc
interface_template_list.cc
@@ -64,7 +64,7 @@ set(SRC
interface_template_search_operator.c
interface_templates.c
interface_undo.c
- interface_utils.c
+ interface_utils.cc
interface_view.cc
interface_widgets.c
resources.c
diff --git a/source/blender/editors/interface/interface_draw.c b/source/blender/editors/interface/interface_draw.c
index c02024bc82d..695f34a448f 100644
--- a/source/blender/editors/interface/interface_draw.c
+++ b/source/blender/editors/interface/interface_draw.c
@@ -38,6 +38,7 @@
#include "GPU_batch.h"
#include "GPU_batch_presets.h"
+#include "GPU_context.h"
#include "GPU_immediate.h"
#include "GPU_immediate_util.h"
#include "GPU_matrix.h"
@@ -1084,12 +1085,23 @@ static void ui_draw_colorband_handle_tri(
static void ui_draw_colorband_handle_box(
uint pos, float x1, float y1, float x2, float y2, bool fill)
{
- immBegin(fill ? GPU_PRIM_TRI_FAN : GPU_PRIM_LINE_LOOP, 4);
- immVertex2f(pos, x1, y1);
- immVertex2f(pos, x1, y2);
- immVertex2f(pos, x2, y2);
- immVertex2f(pos, x2, y1);
- immEnd();
+ if (fill) {
+ immBegin(GPU_PRIM_TRI_STRIP, 4);
+ immVertex2f(pos, x2, y1);
+ immVertex2f(pos, x1, y1);
+ immVertex2f(pos, x2, y2);
+ immVertex2f(pos, x1, y2);
+ immEnd();
+ }
+ else {
+ immBegin(GPU_PRIM_LINE_STRIP, 5);
+ immVertex2f(pos, x1, y1);
+ immVertex2f(pos, x1, y2);
+ immVertex2f(pos, x2, y2);
+ immVertex2f(pos, x2, y1);
+ immVertex2f(pos, x1, y1);
+ immEnd();
+ }
}
static void ui_draw_colorband_handle(uint shdr_pos,
diff --git a/source/blender/editors/interface/interface_eyedropper_depth.c b/source/blender/editors/interface/interface_eyedropper_depth.c
index 4710bada8e0..56bc1a6d956 100644
--- a/source/blender/editors/interface/interface_eyedropper_depth.c
+++ b/source/blender/editors/interface/interface_eyedropper_depth.c
@@ -22,6 +22,7 @@
#include "BLI_string.h"
#include "BKE_context.h"
+#include "BKE_lib_id.h"
#include "BKE_screen.h"
#include "BKE_unit.h"
@@ -88,7 +89,8 @@ static int depthdropper_init(bContext *C, wmOperator *op)
RegionView3D *rv3d = CTX_wm_region_view3d(C);
if (rv3d && rv3d->persp == RV3D_CAMOB) {
View3D *v3d = CTX_wm_view3d(C);
- if (v3d->camera && v3d->camera->data && !ID_IS_LINKED(v3d->camera->data)) {
+ if (v3d->camera && v3d->camera->data &&
+ BKE_id_is_editable(CTX_data_main(C), v3d->camera->data)) {
Camera *camera = (Camera *)v3d->camera->data;
RNA_pointer_create(&camera->id, &RNA_CameraDOFSettings, &camera->dof, &ddr->ptr);
ddr->prop = RNA_struct_find_property(&ddr->ptr, "focus_distance");
@@ -348,7 +350,8 @@ static bool depthdropper_poll(bContext *C)
RegionView3D *rv3d = CTX_wm_region_view3d(C);
if (rv3d && rv3d->persp == RV3D_CAMOB) {
View3D *v3d = CTX_wm_view3d(C);
- if (v3d->camera && v3d->camera->data && !ID_IS_LINKED(v3d->camera->data)) {
+ if (v3d->camera && v3d->camera->data &&
+ BKE_id_is_editable(CTX_data_main(C), v3d->camera->data)) {
return true;
}
}
diff --git a/source/blender/editors/interface/interface_icons.c b/source/blender/editors/interface/interface_icons.c
index 07e4f6c2a24..e3bf1a48907 100644
--- a/source/blender/editors/interface/interface_icons.c
+++ b/source/blender/editors/interface/interface_icons.c
@@ -465,6 +465,32 @@ DEF_ICON_STRIP_COLOR_DRAW(09, SEQUENCE_COLOR_09);
# undef DEF_ICON_STRIP_COLOR_DRAW
+# define ICON_INDIRECT_DATA_ALPHA 0.6f
+
+static void vicon_strip_color_draw_library_data_indirect(
+ int x, int y, int w, int UNUSED(h), float alpha)
+{
+ const float aspect = (float)ICON_DEFAULT_WIDTH / (float)w;
+
+ UI_icon_draw_ex(
+ x, y, ICON_LIBRARY_DATA_DIRECT, aspect, ICON_INDIRECT_DATA_ALPHA * alpha, 0.0f, NULL, false);
+}
+
+static void vicon_strip_color_draw_library_data_override_noneditable(
+ int x, int y, int w, int UNUSED(h), float alpha)
+{
+ const float aspect = (float)ICON_DEFAULT_WIDTH / (float)w;
+
+ UI_icon_draw_ex(x,
+ y,
+ ICON_LIBRARY_DATA_OVERRIDE,
+ aspect,
+ ICON_INDIRECT_DATA_ALPHA * alpha * 0.75f,
+ 0.0f,
+ NULL,
+ false);
+}
+
/* Dynamically render icon instead of rendering a plain color to a texture/buffer
* This is not strictly a "vicon", as it needs access to icon->obj to get the color info,
* but it works in a very similar way.
@@ -974,6 +1000,10 @@ static void init_internal_icons(void)
def_internal_vicon(ICON_SEQUENCE_COLOR_07, vicon_strip_color_draw_07);
def_internal_vicon(ICON_SEQUENCE_COLOR_08, vicon_strip_color_draw_08);
def_internal_vicon(ICON_SEQUENCE_COLOR_09, vicon_strip_color_draw_09);
+
+ def_internal_vicon(ICON_LIBRARY_DATA_INDIRECT, vicon_strip_color_draw_library_data_indirect);
+ def_internal_vicon(ICON_LIBRARY_DATA_OVERRIDE_NONEDITABLE,
+ vicon_strip_color_draw_library_data_override_noneditable);
}
static void init_iconfile_list(struct ListBase *list)
@@ -2179,6 +2209,10 @@ int UI_icon_from_library(const ID *id)
return ICON_LIBRARY_DATA_DIRECT;
}
if (ID_IS_OVERRIDE_LIBRARY(id)) {
+ if (!ID_IS_OVERRIDE_LIBRARY_REAL(id) ||
+ (id->override_library->flag & IDOVERRIDE_LIBRARY_FLAG_SYSTEM_DEFINED) != 0) {
+ return ICON_LIBRARY_DATA_OVERRIDE_NONEDITABLE;
+ }
return ICON_LIBRARY_DATA_OVERRIDE;
}
if (ID_IS_ASSET(id)) {
diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h
index a7a2409ef17..e619b14fb69 100644
--- a/source/blender/editors/interface/interface_intern.h
+++ b/source/blender/editors/interface/interface_intern.h
@@ -214,8 +214,8 @@ struct uiBut {
BIFIconID icon;
/** Copied from the #uiBlock.emboss */
eUIEmbossType emboss;
- /** direction in a pie menu, used for collision detection (RadialDirection) */
- signed char pie_dir;
+ /** direction in a pie menu, used for collision detection. */
+ RadialDirection pie_dir;
/** could be made into a single flag */
bool changed;
/** so buttons can support unit systems which are not RNA */
@@ -954,7 +954,7 @@ void ui_pie_menu_level_create(uiBlock *block,
const EnumPropertyItem *items,
int totitem,
wmOperatorCallContext context,
- int flag);
+ wmOperatorCallContext flag);
/* interface_region_popup.c */
diff --git a/source/blender/editors/interface/interface_query.c b/source/blender/editors/interface/interface_query.cc
index 4703367671d..2767a184619 100644
--- a/source/blender/editors/interface/interface_query.c
+++ b/source/blender/editors/interface/interface_query.cc
@@ -61,7 +61,7 @@ bool ui_but_is_toggle(const uiBut *but)
bool ui_but_is_interactive(const uiBut *but, const bool labeledit)
{
/* NOTE: #UI_BTYPE_LABEL is included for highlights, this allows drags. */
- if ((but->type == UI_BTYPE_LABEL) && but->dragpoin == NULL) {
+ if ((but->type == UI_BTYPE_LABEL) && but->dragpoin == nullptr) {
return false;
}
if (ELEM(but->type, UI_BTYPE_ROUNDBOX, UI_BTYPE_SEPR, UI_BTYPE_SEPR_LINE, UI_BTYPE_LISTBOX)) {
@@ -119,12 +119,12 @@ bool ui_but_has_array_value(const uiBut *but)
PROP_COORDS));
}
-static wmOperatorType *g_ot_tool_set_by_id = NULL;
+static wmOperatorType *g_ot_tool_set_by_id = nullptr;
bool UI_but_is_tool(const uiBut *but)
{
/* very evil! */
- if (but->optype != NULL) {
- if (g_ot_tool_set_by_id == NULL) {
+ if (but->optype != nullptr) {
+ if (g_ot_tool_set_by_id == nullptr) {
g_ot_tool_set_by_id = WM_operatortype_find("WM_OT_tool_set_by_id", false);
}
if (but->optype == g_ot_tool_set_by_id) {
@@ -198,7 +198,7 @@ bool ui_but_contains_pt(const uiBut *but, float mx, float my)
bool ui_but_contains_rect(const uiBut *but, const rctf *rect)
{
- return BLI_rctf_isect(&but->rect, rect, NULL);
+ return BLI_rctf_isect(&but->rect, rect, nullptr);
}
bool ui_but_contains_point_px(const uiBut *but, const ARegion *region, const int xy[2])
@@ -260,7 +260,7 @@ static uiBut *ui_but_find(const ARegion *region,
}
}
- return NULL;
+ return nullptr;
}
uiBut *ui_but_find_mouse_over_ex(const ARegion *region,
@@ -269,10 +269,10 @@ uiBut *ui_but_find_mouse_over_ex(const ARegion *region,
const uiButFindPollFn find_poll,
const void *find_custom_data)
{
- uiBut *butover = NULL;
+ uiBut *butover = nullptr;
if (!ui_region_contains_point_px(region, xy)) {
- return NULL;
+ return nullptr;
}
LISTBASE_FOREACH (uiBlock *, block, &region->uiblocks) {
float mx = xy[0], my = xy[1];
@@ -310,20 +310,20 @@ uiBut *ui_but_find_mouse_over_ex(const ARegion *region,
uiBut *ui_but_find_mouse_over(const ARegion *region, const wmEvent *event)
{
- return ui_but_find_mouse_over_ex(region, event->xy, event->modifier & KM_CTRL, NULL, NULL);
+ return ui_but_find_mouse_over_ex(region, event->xy, event->modifier & KM_CTRL, nullptr, nullptr);
}
uiBut *ui_but_find_rect_over(const struct ARegion *region, const rcti *rect_px)
{
if (!ui_region_contains_rect_px(region, rect_px)) {
- return NULL;
+ return nullptr;
}
/* Currently no need to expose this at the moment. */
const bool labeledit = true;
rctf rect_px_fl;
BLI_rctf_rcti_copy(&rect_px_fl, rect_px);
- uiBut *butover = NULL;
+ uiBut *butover = nullptr;
LISTBASE_FOREACH (uiBlock *, block, &region->uiblocks) {
rctf rect_block;
@@ -343,7 +343,7 @@ uiBut *ui_but_find_rect_over(const struct ARegion *region, const rcti *rect_px)
/* CLIP_EVENTS prevents the event from reaching other blocks */
if (block->flag & UI_BLOCK_CLIP_EVENTS) {
/* check if mouse is inside block */
- if (BLI_rctf_isect(&block->rect, &rect_block, NULL)) {
+ if (BLI_rctf_isect(&block->rect, &rect_block, nullptr)) {
break;
}
}
@@ -354,7 +354,7 @@ uiBut *ui_but_find_rect_over(const struct ARegion *region, const rcti *rect_px)
uiBut *ui_list_find_mouse_over_ex(const ARegion *region, const int xy[2])
{
if (!ui_region_contains_point_px(region, xy)) {
- return NULL;
+ return nullptr;
}
LISTBASE_FOREACH (uiBlock *, block, &region->uiblocks) {
float mx = xy[0], my = xy[1];
@@ -366,14 +366,14 @@ uiBut *ui_list_find_mouse_over_ex(const ARegion *region, const int xy[2])
}
}
- return NULL;
+ return nullptr;
}
uiBut *ui_list_find_mouse_over(const ARegion *region, const wmEvent *event)
{
- if (event == NULL) {
+ if (event == nullptr) {
/* If there is no info about the mouse, just act as if there is nothing underneath it. */
- return NULL;
+ return nullptr;
}
return ui_list_find_mouse_over_ex(region, event->xy);
}
@@ -382,10 +382,10 @@ uiList *UI_list_find_mouse_over(const ARegion *region, const wmEvent *event)
{
uiBut *list_but = ui_list_find_mouse_over(region, event);
if (!list_but) {
- return NULL;
+ return nullptr;
}
- return list_but->custom_data;
+ return static_cast<uiList *>(list_but->custom_data);
}
static bool ui_list_contains_row(const uiBut *listbox_but, const uiBut *listrow_but)
@@ -398,7 +398,7 @@ static bool ui_list_contains_row(const uiBut *listbox_but, const uiBut *listrow_
static bool ui_but_is_listbox_with_row(const uiBut *but, const void *customdata)
{
- const uiBut *row_but = customdata;
+ const uiBut *row_but = static_cast<const uiBut *>(customdata);
return (but->type == UI_BTYPE_LISTBOX) && ui_list_contains_row(but, row_but);
}
@@ -414,7 +414,7 @@ static bool ui_but_is_listrow(const uiBut *but, const void *UNUSED(customdata))
uiBut *ui_list_row_find_mouse_over(const ARegion *region, const int xy[2])
{
- return ui_but_find_mouse_over_ex(region, xy, false, ui_but_is_listrow, NULL);
+ return ui_but_find_mouse_over_ex(region, xy, false, ui_but_is_listrow, nullptr);
}
struct ListRowFindIndexData {
@@ -424,19 +424,18 @@ struct ListRowFindIndexData {
static bool ui_but_is_listrow_at_index(const uiBut *but, const void *customdata)
{
- const struct ListRowFindIndexData *find_data = customdata;
+ const ListRowFindIndexData *find_data = static_cast<const ListRowFindIndexData *>(customdata);
- return ui_but_is_listrow(but, NULL) && ui_list_contains_row(find_data->listbox, but) &&
+ return ui_but_is_listrow(but, nullptr) && ui_list_contains_row(find_data->listbox, but) &&
(but->hardmax == find_data->index);
}
uiBut *ui_list_row_find_from_index(const ARegion *region, const int index, uiBut *listbox)
{
BLI_assert(listbox->type == UI_BTYPE_LISTBOX);
- struct ListRowFindIndexData data = {
- .index = index,
- .listbox = listbox,
- };
+ ListRowFindIndexData data = {};
+ data.index = index;
+ data.listbox = listbox;
return ui_but_find(region, ui_but_is_listrow_at_index, &data);
}
@@ -447,7 +446,7 @@ static bool ui_but_is_treerow(const uiBut *but, const void *UNUSED(customdata))
uiBut *ui_tree_row_find_mouse_over(const ARegion *region, const int xy[2])
{
- return ui_but_find_mouse_over_ex(region, xy, false, ui_but_is_treerow, NULL);
+ return ui_but_find_mouse_over_ex(region, xy, false, ui_but_is_treerow, nullptr);
}
static bool ui_but_is_active_treerow(const uiBut *but, const void *customdata)
@@ -462,7 +461,7 @@ static bool ui_but_is_active_treerow(const uiBut *but, const void *customdata)
uiBut *ui_tree_row_find_active(const ARegion *region)
{
- return ui_but_find(region, ui_but_is_active_treerow, NULL);
+ return ui_but_find(region, ui_but_is_active_treerow, nullptr);
}
/** \} */
@@ -479,7 +478,7 @@ uiBut *ui_but_prev(uiBut *but)
return but;
}
}
- return NULL;
+ return nullptr;
}
uiBut *ui_but_next(uiBut *but)
@@ -490,7 +489,7 @@ uiBut *ui_but_next(uiBut *but)
return but;
}
}
- return NULL;
+ return nullptr;
}
uiBut *ui_but_first(uiBlock *block)
@@ -500,21 +499,19 @@ uiBut *ui_but_first(uiBlock *block)
return but;
}
}
- return NULL;
+ return nullptr;
}
uiBut *ui_but_last(uiBlock *block)
{
- uiBut *but;
-
- but = block->buttons.last;
+ uiBut *but = static_cast<uiBut *>(block->buttons.last);
while (but) {
if (ui_but_is_editable(but)) {
return but;
}
but = but->prev;
}
- return NULL;
+ return nullptr;
}
bool ui_but_is_cursor_warp(const uiBut *but)
@@ -550,7 +547,7 @@ size_t ui_but_drawstr_len_without_sep_char(const uiBut *but)
{
if (but->flag & UI_BUT_HAS_SEP_CHAR) {
const char *str_sep = strrchr(but->drawstr, UI_SEP_CHAR);
- if (str_sep != NULL) {
+ if (str_sep != nullptr) {
return (str_sep - but->drawstr);
}
}
@@ -565,12 +562,12 @@ size_t ui_but_drawstr_without_sep_char(const uiBut *but, char *str, size_t str_m
size_t ui_but_tip_len_only_first_line(const uiBut *but)
{
- if (but->tip == NULL) {
+ if (but->tip == nullptr) {
return 0;
}
const char *str_sep = strchr(but->tip, '\n');
- if (str_sep != NULL) {
+ if (str_sep != nullptr) {
return (str_sep - but->tip);
}
return strlen(but->tip);
@@ -590,7 +587,7 @@ uiBut *ui_block_active_but_get(const uiBlock *block)
}
}
- return NULL;
+ return nullptr;
}
bool ui_block_is_menu(const uiBlock *block)
@@ -622,12 +619,12 @@ static const uiBut *ui_but_next_non_separator(const uiBut *but)
return but;
}
}
- return NULL;
+ return nullptr;
}
bool UI_block_is_empty_ex(const uiBlock *block, const bool skip_title)
{
- const uiBut *but = block->buttons.first;
+ const uiBut *but = static_cast<const uiBut *>(block->buttons.first);
if (skip_title) {
/* Skip the first label, since popups often have a title,
* we may want to consider the block empty in this case. */
@@ -636,7 +633,7 @@ bool UI_block_is_empty_ex(const uiBlock *block, const bool skip_title)
but = but->next;
}
}
- return (ui_but_next_non_separator(but) == NULL);
+ return (ui_but_next_non_separator(but) == nullptr);
}
bool UI_block_is_empty(const uiBlock *block)
@@ -647,7 +644,7 @@ bool UI_block_is_empty(const uiBlock *block)
bool UI_block_can_add_separator(const uiBlock *block)
{
if (ui_block_is_menu(block) && !ui_block_is_pie_menu(block)) {
- const uiBut *but = block->buttons.last;
+ const uiBut *but = static_cast<const uiBut *>(block->buttons.last);
return (but && !ELEM(but->type, UI_BTYPE_SEPR_LINE, UI_BTYPE_SEPR));
}
return true;
@@ -662,7 +659,7 @@ bool UI_block_can_add_separator(const uiBlock *block)
uiBlock *ui_block_find_mouse_over_ex(const ARegion *region, const int xy[2], bool only_clip)
{
if (!ui_region_contains_point_px(region, xy)) {
- return NULL;
+ return nullptr;
}
LISTBASE_FOREACH (uiBlock *, block, &region->uiblocks) {
if (only_clip) {
@@ -676,7 +673,7 @@ uiBlock *ui_block_find_mouse_over_ex(const ARegion *region, const int xy[2], boo
return block;
}
}
- return NULL;
+ return nullptr;
}
uiBlock *ui_block_find_mouse_over(const ARegion *region, const wmEvent *event, bool only_clip)
@@ -699,7 +696,7 @@ uiBut *ui_region_find_active_but(ARegion *region)
}
}
- return NULL;
+ return nullptr;
}
uiBut *ui_region_find_first_but_test_flag(ARegion *region, int flag_include, int flag_exclude)
@@ -712,7 +709,7 @@ uiBut *ui_region_find_first_but_test_flag(ARegion *region, int flag_include, int
}
}
- return NULL;
+ return nullptr;
}
/** \} */
@@ -752,7 +749,7 @@ bool ui_region_contains_rect_px(const ARegion *region, const rcti *rect_px)
{
rcti winrct;
ui_region_winrct_get_no_margin(region, &winrct);
- if (!BLI_rcti_isect(&winrct, rect_px, NULL)) {
+ if (!BLI_rcti_isect(&winrct, rect_px, nullptr)) {
return false;
}
@@ -761,7 +758,7 @@ bool ui_region_contains_rect_px(const ARegion *region, const rcti *rect_px)
const View2D *v2d = &region->v2d;
rcti rect_region;
ui_window_to_region_rcti(region, &rect_region, rect_px);
- if (!BLI_rcti_isect(&v2d->mask, &rect_region, NULL) ||
+ if (!BLI_rcti_isect(&v2d->mask, &rect_region, nullptr) ||
UI_view2d_rect_in_scrollers(region, &region->v2d, rect_px)) {
return false;
}
@@ -787,7 +784,7 @@ ARegion *ui_screen_region_find_mouse_over_ex(bScreen *screen, const int xy[2])
return region;
}
}
- return NULL;
+ return nullptr;
}
ARegion *ui_screen_region_find_mouse_over(bScreen *screen, const wmEvent *event)
@@ -803,7 +800,7 @@ ARegion *ui_screen_region_find_mouse_over(bScreen *screen, const wmEvent *event)
void ui_interface_tag_script_reload_queries(void)
{
- g_ot_tool_set_by_id = NULL;
+ g_ot_tool_set_by_id = nullptr;
}
/** \} */
diff --git a/source/blender/editors/interface/interface_region_color_picker.c b/source/blender/editors/interface/interface_region_color_picker.cc
index 9fb6f538191..ab0a6039cdc 100644
--- a/source/blender/editors/interface/interface_region_color_picker.c
+++ b/source/blender/editors/interface/interface_region_color_picker.cc
@@ -7,9 +7,9 @@
* Color Picker Region & Color Utils
*/
-#include <stdarg.h>
-#include <stdlib.h>
-#include <string.h>
+#include <cstdarg>
+#include <cstdlib>
+#include <cstring>
#include "MEM_guardedalloc.h"
@@ -168,7 +168,7 @@ static void ui_color_picker_update_hsv(ColorPicker *cpicker,
void ui_but_hsv_set(uiBut *but)
{
float rgb_perceptual[3];
- ColorPicker *cpicker = but->custom_data;
+ ColorPicker *cpicker = static_cast<ColorPicker *>(but->custom_data);
float *hsv_perceptual = cpicker->hsv_perceptual;
ui_color_picker_hsv_to_rgb(hsv_perceptual, rgb_perceptual);
@@ -255,7 +255,8 @@ static void ui_colorpicker_rgba_update_cb(bContext *UNUSED(C), void *bt1, void *
if (prop) {
RNA_property_float_get_array(&ptr, prop, rgb_scene_linear);
- ui_update_color_picker_buts_rgb(but, but->block, but->custom_data, rgb_scene_linear);
+ ui_update_color_picker_buts_rgb(
+ but, but->block, static_cast<ColorPicker *>(but->custom_data), rgb_scene_linear);
}
if (popup) {
@@ -268,7 +269,7 @@ static void ui_colorpicker_hsv_update_cb(bContext *UNUSED(C), void *bt1, void *U
uiBut *but = (uiBut *)bt1;
uiPopupBlockHandle *popup = but->block->handle;
float rgb_scene_linear[3];
- ColorPicker *cpicker = but->custom_data;
+ ColorPicker *cpicker = static_cast<ColorPicker *>(but->custom_data);
ui_color_picker_hsv_to_rgb(cpicker->hsv_scene_linear, rgb_scene_linear);
ui_update_color_picker_buts_rgb(but, but->block, cpicker, rgb_scene_linear);
@@ -282,7 +283,7 @@ static void ui_colorpicker_hex_rna_cb(bContext *UNUSED(C), void *bt1, void *hexc
{
uiBut *but = (uiBut *)bt1;
uiPopupBlockHandle *popup = but->block->handle;
- ColorPicker *cpicker = but->custom_data;
+ ColorPicker *cpicker = static_cast<ColorPicker *>(but->custom_data);
char *hexcol = (char *)hexcl;
float rgb[3];
@@ -307,7 +308,7 @@ static void ui_popup_close_cb(bContext *UNUSED(C), void *bt1, void *UNUSED(arg))
uiPopupBlockHandle *popup = but->block->handle;
if (popup) {
- ColorPicker *cpicker = but->custom_data;
+ ColorPicker *cpicker = static_cast<ColorPicker *>(but->custom_data);
BLI_assert(cpicker->is_init);
popup->menuretval = (equals_v3v3(cpicker->hsv_perceptual, cpicker->hsv_perceptual_init) ?
UI_RETURN_CANCEL :
@@ -315,7 +316,7 @@ static void ui_popup_close_cb(bContext *UNUSED(C), void *bt1, void *UNUSED(arg))
}
}
-static void ui_colorpicker_hide_reveal(uiBlock *block, enum ePickerType colormode)
+static void ui_colorpicker_hide_reveal(uiBlock *block, ePickerType colormode)
{
/* tag buttons */
LISTBASE_FOREACH (uiBut *, bt, &block->buttons) {
@@ -337,9 +338,9 @@ static void ui_colorpicker_hide_reveal(uiBlock *block, enum ePickerType colormod
static void ui_colorpicker_create_mode_cb(bContext *UNUSED(C), void *bt1, void *UNUSED(arg))
{
- uiBut *bt = bt1;
+ uiBut *bt = static_cast<uiBut *>(bt1);
const short colormode = ui_but_value_get(bt);
- ui_colorpicker_hide_reveal(bt->block, colormode);
+ ui_colorpicker_hide_reveal(bt->block, (ePickerType)colormode);
}
#define PICKER_H (7.5f * U.widget_unit)
@@ -374,7 +375,7 @@ static void ui_colorpicker_circle(uiBlock *block,
0.0,
0,
TIP_("Color"));
- UI_but_func_set(bt, ui_colorpicker_rgba_update_cb, bt, NULL);
+ UI_but_func_set(bt, ui_colorpicker_rgba_update_cb, bt, nullptr);
bt->custom_data = cpicker;
/* value */
@@ -396,7 +397,7 @@ static void ui_colorpicker_circle(uiBlock *block,
0,
"Lightness");
hsv_but->gradient_type = UI_GRAD_L_ALT;
- UI_but_func_set(&hsv_but->but, ui_colorpicker_rgba_update_cb, &hsv_but->but, NULL);
+ UI_but_func_set(&hsv_but->but, ui_colorpicker_rgba_update_cb, &hsv_but->but, nullptr);
}
else {
hsv_but = (uiButHSVCube *)uiDefButR_prop(block,
@@ -416,7 +417,7 @@ static void ui_colorpicker_circle(uiBlock *block,
0,
TIP_("Value"));
hsv_but->gradient_type = UI_GRAD_V_ALT;
- UI_but_func_set(&hsv_but->but, ui_colorpicker_rgba_update_cb, &hsv_but->but, NULL);
+ UI_but_func_set(&hsv_but->but, ui_colorpicker_rgba_update_cb, &hsv_but->but, nullptr);
}
hsv_but->but.custom_data = cpicker;
}
@@ -449,7 +450,7 @@ static void ui_colorpicker_square(uiBlock *block,
0,
TIP_("Color"));
hsv_but->gradient_type = type;
- UI_but_func_set(&hsv_but->but, ui_colorpicker_rgba_update_cb, &hsv_but->but, NULL);
+ UI_but_func_set(&hsv_but->but, ui_colorpicker_rgba_update_cb, &hsv_but->but, nullptr);
hsv_but->but.custom_data = cpicker;
/* value */
@@ -469,8 +470,8 @@ static void ui_colorpicker_square(uiBlock *block,
0,
0,
TIP_("Value"));
- hsv_but->gradient_type = type + 3;
- UI_but_func_set(&hsv_but->but, ui_colorpicker_rgba_update_cb, &hsv_but->but, NULL);
+ hsv_but->gradient_type = (eButGradientType)(type + 3);
+ UI_but_func_set(&hsv_but->but, ui_colorpicker_rgba_update_cb, &hsv_but->but, nullptr);
hsv_but->but.custom_data = cpicker;
}
@@ -547,7 +548,7 @@ static void ui_block_colorpicker(uiBlock *block,
"");
UI_but_flag_disable(bt, UI_BUT_UNDO);
UI_but_drawflag_disable(bt, UI_BUT_TEXT_LEFT);
- UI_but_func_set(bt, ui_colorpicker_create_mode_cb, bt, NULL);
+ UI_but_func_set(bt, ui_colorpicker_create_mode_cb, bt, nullptr);
bt->custom_data = cpicker;
bt = uiDefButC(block,
UI_BTYPE_ROW,
@@ -565,7 +566,7 @@ static void ui_block_colorpicker(uiBlock *block,
"");
UI_but_flag_disable(bt, UI_BUT_UNDO);
UI_but_drawflag_disable(bt, UI_BUT_TEXT_LEFT);
- UI_but_func_set(bt, ui_colorpicker_create_mode_cb, bt, NULL);
+ UI_but_func_set(bt, ui_colorpicker_create_mode_cb, bt, nullptr);
bt->custom_data = cpicker;
bt = uiDefButC(block,
UI_BTYPE_ROW,
@@ -583,7 +584,7 @@ static void ui_block_colorpicker(uiBlock *block,
"");
UI_but_flag_disable(bt, UI_BUT_UNDO);
UI_but_drawflag_disable(bt, UI_BUT_TEXT_LEFT);
- UI_but_func_set(bt, ui_colorpicker_create_mode_cb, bt, NULL);
+ UI_but_func_set(bt, ui_colorpicker_create_mode_cb, bt, nullptr);
bt->custom_data = cpicker;
UI_block_align_end(block);
@@ -598,10 +599,10 @@ static void ui_block_colorpicker(uiBlock *block,
yco,
UI_UNIT_X,
UI_UNIT_Y,
- NULL);
+ nullptr);
UI_but_flag_disable(bt, UI_BUT_UNDO);
UI_but_drawflag_disable(bt, UI_BUT_ICON_LEFT);
- UI_but_func_set(bt, ui_popup_close_cb, bt, NULL);
+ UI_but_func_set(bt, ui_popup_close_cb, bt, nullptr);
bt->custom_data = cpicker;
}
@@ -625,7 +626,7 @@ static void ui_block_colorpicker(uiBlock *block,
0,
3,
TIP_("Red"));
- UI_but_func_set(bt, ui_colorpicker_rgba_update_cb, bt, NULL);
+ UI_but_func_set(bt, ui_colorpicker_rgba_update_cb, bt, nullptr);
bt->custom_data = cpicker;
bt = uiDefButR_prop(block,
UI_BTYPE_NUM_SLIDER,
@@ -643,7 +644,7 @@ static void ui_block_colorpicker(uiBlock *block,
0,
3,
TIP_("Green"));
- UI_but_func_set(bt, ui_colorpicker_rgba_update_cb, bt, NULL);
+ UI_but_func_set(bt, ui_colorpicker_rgba_update_cb, bt, nullptr);
bt->custom_data = cpicker;
bt = uiDefButR_prop(block,
UI_BTYPE_NUM_SLIDER,
@@ -661,7 +662,7 @@ static void ui_block_colorpicker(uiBlock *block,
0,
3,
TIP_("Blue"));
- UI_but_func_set(bt, ui_colorpicker_rgba_update_cb, bt, NULL);
+ UI_but_func_set(bt, ui_colorpicker_rgba_update_cb, bt, nullptr);
bt->custom_data = cpicker;
/* Could use:
@@ -686,7 +687,7 @@ static void ui_block_colorpicker(uiBlock *block,
3,
TIP_("Hue"));
UI_but_flag_disable(bt, UI_BUT_UNDO);
- UI_but_func_set(bt, ui_colorpicker_hsv_update_cb, bt, NULL);
+ UI_but_func_set(bt, ui_colorpicker_hsv_update_cb, bt, nullptr);
bt->custom_data = cpicker;
bt = uiDefButF(block,
UI_BTYPE_NUM_SLIDER,
@@ -703,7 +704,7 @@ static void ui_block_colorpicker(uiBlock *block,
3,
TIP_("Saturation"));
UI_but_flag_disable(bt, UI_BUT_UNDO);
- UI_but_func_set(bt, ui_colorpicker_hsv_update_cb, bt, NULL);
+ UI_but_func_set(bt, ui_colorpicker_hsv_update_cb, bt, nullptr);
bt->custom_data = cpicker;
if (U.color_picker_type == USER_CP_CIRCLE_HSL) {
bt = uiDefButF(block,
@@ -740,7 +741,7 @@ static void ui_block_colorpicker(uiBlock *block,
UI_but_flag_disable(bt, UI_BUT_UNDO);
bt->hardmax = hardmax; /* not common but rgb may be over 1.0 */
- UI_but_func_set(bt, ui_colorpicker_hsv_update_cb, bt, NULL);
+ UI_but_func_set(bt, ui_colorpicker_hsv_update_cb, bt, nullptr);
bt->custom_data = cpicker;
UI_block_align_end(block);
@@ -762,7 +763,7 @@ static void ui_block_colorpicker(uiBlock *block,
0,
3,
TIP_("Alpha"));
- UI_but_func_set(bt, ui_colorpicker_rgba_update_cb, bt, NULL);
+ UI_but_func_set(bt, ui_colorpicker_rgba_update_cb, bt, nullptr);
bt->custom_data = cpicker;
}
else {
@@ -809,14 +810,14 @@ static void ui_block_colorpicker(uiBlock *block,
yco - UI_UNIT_Y,
butwidth,
UI_UNIT_Y,
- NULL,
+ nullptr,
0.0,
0.0,
0,
0,
"");
- ui_colorpicker_hide_reveal(block, colormode);
+ ui_colorpicker_hide_reveal(block, (ePickerType)colormode);
}
static int ui_colorpicker_small_wheel_cb(const bContext *UNUSED(C),
@@ -834,9 +835,9 @@ static int ui_colorpicker_small_wheel_cb(const bContext *UNUSED(C),
if (add != 0.0f) {
LISTBASE_FOREACH (uiBut *, but, &block->buttons) {
- if (but->type == UI_BTYPE_HSVCUBE && but->active == NULL) {
+ if (but->type == UI_BTYPE_HSVCUBE && but->active == nullptr) {
uiPopupBlockHandle *popup = block->handle;
- ColorPicker *cpicker = but->custom_data;
+ ColorPicker *cpicker = static_cast<ColorPicker *>(but->custom_data);
float *hsv_perceptual = cpicker->hsv_perceptual;
float rgb_perceptual[3];
@@ -865,7 +866,7 @@ static int ui_colorpicker_small_wheel_cb(const bContext *UNUSED(C),
uiBlock *ui_block_func_COLOR(bContext *C, uiPopupBlockHandle *handle, void *arg_but)
{
- uiBut *but = arg_but;
+ uiBut *but = static_cast<uiBut *>(arg_but);
uiBlock *block;
bool show_picker = true;
@@ -901,7 +902,7 @@ uiBlock *ui_block_func_COLOR(bContext *C, uiPopupBlockHandle *handle, void *arg_
ColorPicker *ui_block_colorpicker_create(struct uiBlock *block)
{
- ColorPicker *cpicker = MEM_callocN(sizeof(ColorPicker), "color_picker");
+ ColorPicker *cpicker = MEM_cnew<ColorPicker>(__func__);
BLI_addhead(&block->color_pickers.list, cpicker);
return cpicker;
diff --git a/source/blender/editors/interface/interface_region_hud.c b/source/blender/editors/interface/interface_region_hud.cc
index 4d72cd5382c..d6166694a4a 100644
--- a/source/blender/editors/interface/interface_region_hud.c
+++ b/source/blender/editors/interface/interface_region_hud.cc
@@ -7,7 +7,7 @@
* Floating Persistent Region
*/
-#include <string.h>
+#include <cstring>
#include "MEM_guardedalloc.h"
@@ -49,7 +49,7 @@ struct HudRegionData {
static bool last_redo_poll(const bContext *C, short region_type)
{
wmOperator *op = WM_operator_last_redo(C);
- if (op == NULL) {
+ if (op == nullptr) {
return false;
}
@@ -60,7 +60,8 @@ static bool last_redo_poll(const bContext *C, short region_type)
* wrong context.
*/
ScrArea *area = CTX_wm_area(C);
- ARegion *region_op = (region_type != -1) ? BKE_area_find_region_type(area, region_type) : NULL;
+ ARegion *region_op = (region_type != -1) ? BKE_area_find_region_type(area, region_type) :
+ nullptr;
ARegion *region_prev = CTX_wm_region(C);
CTX_wm_region_set((bContext *)C, region_op);
@@ -90,9 +91,9 @@ static bool hud_panel_operator_redo_poll(const bContext *C, PanelType *UNUSED(pt
{
ScrArea *area = CTX_wm_area(C);
ARegion *region = BKE_area_find_region_type(area, RGN_TYPE_HUD);
- if (region != NULL) {
- struct HudRegionData *hrd = region->regiondata;
- if (hrd != NULL) {
+ if (region != nullptr) {
+ HudRegionData *hrd = static_cast<HudRegionData *>(region->regiondata);
+ if (hrd != nullptr) {
return last_redo_poll(C, hrd->regionid);
}
}
@@ -108,7 +109,7 @@ static void hud_panel_operator_redo_draw_header(const bContext *C, Panel *panel)
static void hud_panel_operator_redo_draw(const bContext *C, Panel *panel)
{
wmOperator *op = WM_operator_last_redo(C);
- if (op == NULL) {
+ if (op == nullptr) {
return;
}
if (!WM_operator_check_ui_enabled(C, op->type->name)) {
@@ -120,9 +121,7 @@ static void hud_panel_operator_redo_draw(const bContext *C, Panel *panel)
static void hud_panels_register(ARegionType *art, int space_type, int region_type)
{
- PanelType *pt;
-
- pt = MEM_callocN(sizeof(PanelType), __func__);
+ PanelType *pt = MEM_cnew<PanelType>(__func__);
strcpy(pt->idname, "OPERATOR_PT_redo");
strcpy(pt->label, N_("Redo"));
strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
@@ -155,8 +154,8 @@ static void hud_region_free(ARegion *region)
static void hud_region_layout(const bContext *C, ARegion *region)
{
- struct HudRegionData *hrd = region->regiondata;
- if (hrd == NULL || !last_redo_poll(C, hrd->regionid)) {
+ HudRegionData *hrd = static_cast<HudRegionData *>(region->regiondata);
+ if (hrd == nullptr || !last_redo_poll(C, hrd->regionid)) {
ED_region_tag_redraw(region);
hud_region_hide(region);
return;
@@ -205,19 +204,17 @@ static void hud_region_draw(const bContext *C, ARegion *region)
GPU_clear_color(0.0f, 0.0f, 0.0f, 0.0f);
if ((region->flag & RGN_FLAG_HIDDEN) == 0) {
- ui_draw_menu_back(NULL,
- NULL,
- &(rcti){
- .xmax = region->winx,
- .ymax = region->winy,
- });
+ rcti reset_rect = {};
+ reset_rect.xmax = region->winx;
+ reset_rect.ymax = region->winy;
+ ui_draw_menu_back(nullptr, nullptr, &reset_rect);
ED_region_panels_draw(C, region);
}
}
ARegionType *ED_area_type_hud(int space_type)
{
- ARegionType *art = MEM_callocN(sizeof(ARegionType), __func__);
+ ARegionType *art = MEM_cnew<ARegionType>(__func__);
art->regionid = RGN_TYPE_HUD;
art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D;
art->layout = hud_region_layout;
@@ -238,7 +235,7 @@ ARegionType *ED_area_type_hud(int space_type)
static ARegion *hud_region_add(ScrArea *area)
{
- ARegion *region = MEM_callocN(sizeof(ARegion), "area region");
+ ARegion *region = MEM_cnew<ARegion>(__func__);
ARegion *region_win = BKE_area_find_region_type(area, RGN_TYPE_WINDOW);
if (region_win) {
BLI_insertlinkbefore(&area->regionbase, region_win, region);
@@ -288,7 +285,7 @@ void ED_area_type_hud_ensure(bContext *C, ScrArea *area)
ED_area_type_hud_clear(wm, area);
ARegionType *art = BKE_regiontype_from_id(area->type, RGN_TYPE_HUD);
- if (art == NULL) {
+ if (art == nullptr) {
return;
}
@@ -301,9 +298,9 @@ void ED_area_type_hud_ensure(bContext *C, ScrArea *area)
}
bool init = false;
- const bool was_hidden = region == NULL || region->visible == false;
+ const bool was_hidden = region == nullptr || region->visible == false;
ARegion *region_op = CTX_wm_region(C);
- BLI_assert((region_op == NULL) || (region_op->regiontype != RGN_TYPE_HUD));
+ BLI_assert((region_op == nullptr) || (region_op->regiontype != RGN_TYPE_HUD));
if (!last_redo_poll(C, region_op ? region_op->regiontype : -1)) {
if (region) {
ED_region_tag_redraw(region);
@@ -312,7 +309,7 @@ void ED_area_type_hud_ensure(bContext *C, ScrArea *area)
return;
}
- if (region == NULL) {
+ if (region == nullptr) {
init = true;
region = hud_region_add(area);
region->type = art;
@@ -332,9 +329,9 @@ void ED_area_type_hud_ensure(bContext *C, ScrArea *area)
}
{
- struct HudRegionData *hrd = region->regiondata;
- if (hrd == NULL) {
- hrd = MEM_callocN(sizeof(*hrd), __func__);
+ HudRegionData *hrd = static_cast<HudRegionData *>(region->regiondata);
+ if (hrd == nullptr) {
+ hrd = MEM_cnew<HudRegionData>(__func__);
region->regiondata = hrd;
}
if (region_op) {
@@ -355,10 +352,10 @@ void ED_area_type_hud_ensure(bContext *C, ScrArea *area)
ED_region_tag_redraw(region);
/* Reset zoom level (not well supported). */
- region->v2d.cur = region->v2d.tot = (rctf){
- .xmax = region->winx,
- .ymax = region->winy,
- };
+ rctf reset_rect = {};
+ reset_rect.xmax = region->winx;
+ reset_rect.ymax = region->winy;
+ region->v2d.cur = region->v2d.tot = reset_rect;
region->v2d.minzoom = 1.0f;
region->v2d.maxzoom = 1.0f;
@@ -373,10 +370,7 @@ void ED_area_type_hud_ensure(bContext *C, ScrArea *area)
if (was_hidden) {
region->winx = region->v2d.winx;
region->winy = region->v2d.winy;
- region->v2d.cur = region->v2d.tot = (rctf){
- .xmax = region->winx,
- .ymax = region->winy,
- };
+ region->v2d.cur = region->v2d.tot = reset_rect;
}
CTX_wm_region_set((bContext *)C, region_prev);
}
diff --git a/source/blender/editors/interface/interface_region_menu_pie.c b/source/blender/editors/interface/interface_region_menu_pie.cc
index 74e128f3098..586aeef44fd 100644
--- a/source/blender/editors/interface/interface_region_menu_pie.c
+++ b/source/blender/editors/interface/interface_region_menu_pie.cc
@@ -7,9 +7,9 @@
* Pie Menu Region
*/
-#include <stdarg.h>
-#include <stdlib.h>
-#include <string.h>
+#include <cstdarg>
+#include <cstdlib>
+#include <cstring>
#include "MEM_guardedalloc.h"
@@ -51,7 +51,7 @@ struct uiPieMenu {
static uiBlock *ui_block_func_PIE(bContext *UNUSED(C), uiPopupBlockHandle *handle, void *arg_pie)
{
uiBlock *block;
- uiPieMenu *pie = arg_pie;
+ uiPieMenu *pie = static_cast<uiPieMenu *>(arg_pie);
int minwidth, width, height;
minwidth = UI_MENU_WIDTH_MIN;
@@ -89,14 +89,13 @@ static float ui_pie_menu_title_width(const char *name, int icon)
uiPieMenu *UI_pie_menu_begin(struct bContext *C, const char *title, int icon, const wmEvent *event)
{
const uiStyle *style = UI_style_get_dpi();
- uiPieMenu *pie;
short event_type;
wmWindow *win = CTX_wm_window(C);
- pie = MEM_callocN(sizeof(*pie), "pie menu");
+ uiPieMenu *pie = MEM_cnew<uiPieMenu>(__func__);
- pie->block_radial = UI_block_begin(C, NULL, __func__, UI_EMBOSS);
+ pie->block_radial = UI_block_begin(C, nullptr, __func__, UI_EMBOSS);
/* may be useful later to allow spawning pies
* from old positions */
/* pie->block_radial->flag |= UI_BLOCK_POPUP_MEMORY; */
@@ -153,7 +152,7 @@ uiPieMenu *UI_pie_menu_begin(struct bContext *C, const char *title, int icon, co
0,
w,
UI_UNIT_Y,
- NULL,
+ nullptr,
0.0,
0.0,
0,
@@ -170,7 +169,7 @@ uiPieMenu *UI_pie_menu_begin(struct bContext *C, const char *title, int icon, co
0,
w,
UI_UNIT_Y,
- NULL,
+ nullptr,
0.0,
0.0,
0,
@@ -191,7 +190,7 @@ void UI_pie_menu_end(bContext *C, uiPieMenu *pie)
wmWindow *window = CTX_wm_window(C);
uiPopupBlockHandle *menu;
- menu = ui_popup_block_create(C, NULL, NULL, NULL, ui_block_func_PIE, pie, NULL);
+ menu = ui_popup_block_create(C, nullptr, nullptr, nullptr, ui_block_func_PIE, pie, nullptr);
menu->popup = true;
menu->towardstime = PIL_check_seconds_timer();
@@ -212,7 +211,7 @@ int UI_pie_menu_invoke(struct bContext *C, const char *idname, const wmEvent *ev
uiLayout *layout;
MenuType *mt = WM_menutype_find(idname, true);
- if (mt == NULL) {
+ if (mt == nullptr) {
printf("%s: named menu \"%s\" not found\n", __func__, idname);
return OPERATOR_CANCELLED;
}
@@ -263,7 +262,7 @@ int UI_pie_menu_invoke_from_rna_enum(struct bContext *C,
uiPieMenu *pie;
uiLayout *layout;
- RNA_pointer_create(NULL, &RNA_Context, C, &ctx_ptr);
+ RNA_pointer_create(nullptr, &RNA_Context, C, &ctx_ptr);
if (!RNA_path_resolve(&ctx_ptr, path, &r_ptr, &r_prop)) {
return OPERATOR_CANCELLED;
@@ -280,7 +279,7 @@ int UI_pie_menu_invoke_from_rna_enum(struct bContext *C,
layout = UI_pie_menu_layout(pie);
layout = uiLayoutRadial(layout);
- uiItemFullR(layout, &r_ptr, r_prop, RNA_NO_INDEX, 0, UI_ITEM_R_EXPAND, NULL, 0);
+ uiItemFullR(layout, &r_ptr, r_prop, RNA_NO_INDEX, 0, UI_ITEM_R_EXPAND, nullptr, 0);
UI_pie_menu_end(C, pie);
@@ -304,7 +303,7 @@ int UI_pie_menu_invoke_from_rna_enum(struct bContext *C,
* - Julian (Feb 2016)
* \{ */
-typedef struct PieMenuLevelData {
+ struct PieMenuLevelData {
char title[UI_MAX_NAME_STR]; /* parent pie title, copied for level */
int icon; /* parent pie icon, copied for level */
int totitem; /* total count of *remaining* items */
@@ -314,7 +313,7 @@ typedef struct PieMenuLevelData {
const char *propname;
IDProperty *properties;
wmOperatorCallContext context, flag;
-} PieMenuLevelData;
+} ;
/**
* Invokes a new pie menu for a new level.
@@ -362,17 +361,17 @@ void ui_pie_menu_level_create(uiBlock *block,
const EnumPropertyItem *items,
int totitem,
wmOperatorCallContext context,
- int flag)
+ wmOperatorCallContext flag)
{
const int totitem_parent = PIE_MAX_ITEMS - 1;
const int totitem_remain = totitem - totitem_parent;
const size_t array_size = sizeof(EnumPropertyItem) * totitem_remain;
/* used as but->func_argN so freeing is handled elsewhere */
- EnumPropertyItem *remaining = MEM_mallocN(array_size + sizeof(EnumPropertyItem),
- "pie_level_item_array");
+ EnumPropertyItem *remaining = static_cast<EnumPropertyItem *>(
+ MEM_mallocN(array_size + sizeof(EnumPropertyItem), "pie_level_item_array"));
memcpy(remaining, items + totitem_parent, array_size);
- /* A NULL terminating sentinel element is required. */
+ /* A nullptr terminating sentinel element is required. */
memset(&remaining[totitem_remain], 0, sizeof(EnumPropertyItem));
/* yuk, static... issue is we can't reliably free this without doing dangerous changes */
@@ -395,7 +394,7 @@ void ui_pie_menu_level_create(uiBlock *block,
0,
UI_UNIT_X * 3,
UI_UNIT_Y,
- NULL,
+ nullptr,
0.0f,
0.0f,
0.0f,
diff --git a/source/blender/editors/interface/interface_region_menu_popup.c b/source/blender/editors/interface/interface_region_menu_popup.cc
index 7d8f4315710..e843a275d08 100644
--- a/source/blender/editors/interface/interface_region_menu_popup.c
+++ b/source/blender/editors/interface/interface_region_menu_popup.cc
@@ -7,9 +7,9 @@
* PopUp Menu Region
*/
-#include <stdarg.h>
-#include <stdlib.h>
-#include <string.h>
+#include <cstdarg>
+#include <cstdlib>
+#include <cstring>
#include "MEM_guardedalloc.h"
@@ -50,7 +50,7 @@ bool ui_but_menu_step_poll(const uiBut *but)
BLI_assert(but->type == UI_BTYPE_MENU);
/* currently only RNA buttons */
- return ((but->menu_step_func != NULL) ||
+ return ((but->menu_step_func != nullptr) ||
(but->rnaprop && RNA_property_type(but->rnaprop) == PROP_ENUM));
}
@@ -58,12 +58,16 @@ int ui_but_menu_step(uiBut *but, int direction)
{
if (ui_but_menu_step_poll(but)) {
if (but->menu_step_func) {
- return but->menu_step_func(but->block->evil_C, direction, but->poin);
+ return but->menu_step_func(
+ static_cast<bContext *>(but->block->evil_C), direction, but->poin);
}
const int curval = RNA_property_enum_get(&but->rnapoin, but->rnaprop);
- return RNA_property_enum_step(
- but->block->evil_C, &but->rnapoin, but->rnaprop, curval, direction);
+ return RNA_property_enum_step(static_cast<bContext *>(but->block->evil_C),
+ &but->rnapoin,
+ but->rnaprop,
+ curval,
+ direction);
}
printf("%s: cannot cycle button '%s'\n", __func__, but->str);
@@ -85,7 +89,7 @@ static uint ui_popup_string_hash(const char *str, const bool use_sep)
{
/* sometimes button contains hotkey, sometimes not, strip for proper compare */
int hash;
- const char *delimit = use_sep ? strrchr(str, UI_SEP_CHAR) : NULL;
+ const char *delimit = use_sep ? strrchr(str, UI_SEP_CHAR) : nullptr;
if (delimit) {
hash = BLI_ghashutil_strhash_n(str, delimit - str);
@@ -102,7 +106,7 @@ uint ui_popup_menu_hash(const char *str)
return BLI_ghashutil_strhash(str);
}
-/* but == NULL read, otherwise set */
+/* but == nullptr read, otherwise set */
static uiBut *ui_popup_menu_memory__internal(uiBlock *block, uiBut *but)
{
static uint mem[256];
@@ -114,13 +118,13 @@ static uiBut *ui_popup_menu_memory__internal(uiBlock *block, uiBut *but)
if (first) {
/* init */
memset(mem, -1, sizeof(mem));
- first = 0;
+ first = false;
}
if (but) {
/* set */
mem[hash_mod] = ui_popup_string_hash(but->str, but->flag & UI_BUT_HAS_SEP_CHAR);
- return NULL;
+ return nullptr;
}
/* get */
@@ -131,12 +135,12 @@ static uiBut *ui_popup_menu_memory__internal(uiBlock *block, uiBut *but)
}
}
- return NULL;
+ return nullptr;
}
uiBut *ui_popup_menu_memory_get(uiBlock *block)
{
- return ui_popup_menu_memory__internal(block, NULL);
+ return ui_popup_menu_memory__internal(block, nullptr);
}
void ui_popup_menu_memory_set(uiBlock *block, uiBut *but)
@@ -166,7 +170,7 @@ struct uiPopupMenu {
static uiBlock *ui_block_func_POPUP(bContext *C, uiPopupBlockHandle *handle, void *arg_pup)
{
uiBlock *block;
- uiPopupMenu *pup = arg_pup;
+ uiPopupMenu *pup = static_cast<uiPopupMenu *>(arg_pup);
int minwidth, width, height;
char direction;
bool flip;
@@ -174,7 +178,7 @@ static uiBlock *ui_block_func_POPUP(bContext *C, uiPopupBlockHandle *handle, voi
if (pup->menu_func) {
pup->block->handle = handle;
pup->menu_func(C, pup->layout, pup->menu_arg);
- pup->block->handle = NULL;
+ pup->block->handle = nullptr;
}
/* Find block minimum width. */
@@ -229,7 +233,7 @@ static uiBlock *ui_block_func_POPUP(bContext *C, uiPopupBlockHandle *handle, voi
if (pup->popup) {
int offset[2];
- uiBut *but_activate = NULL;
+ uiBut *but_activate = nullptr;
UI_block_flag_enable(block, UI_BLOCK_LOOP | UI_BLOCK_NUMSELECT);
UI_block_theme_style_set(block, UI_BLOCK_THEME_STYLE_POPUP);
UI_block_direction_set(block, direction);
@@ -309,10 +313,9 @@ uiPopupBlockHandle *ui_popup_menu_create(
wmWindow *window = CTX_wm_window(C);
const uiStyle *style = UI_style_get_dpi();
uiPopupBlockHandle *handle;
- uiPopupMenu *pup;
- pup = MEM_callocN(sizeof(uiPopupMenu), __func__);
- pup->block = UI_block_begin(C, NULL, __func__, UI_EMBOSS_PULLDOWN);
+ uiPopupMenu *pup = MEM_cnew<uiPopupMenu>(__func__);
+ pup->block = UI_block_begin(C, nullptr, __func__, UI_EMBOSS_PULLDOWN);
pup->block->flag |= UI_BLOCK_NUMSELECT; /* default menus to numselect */
pup->layout = UI_block_layout(
pup->block, UI_LAYOUT_VERTICAL, UI_LAYOUT_MENU, 0, 0, 200, 0, UI_MENU_PADDING, style);
@@ -348,7 +351,7 @@ uiPopupBlockHandle *ui_popup_menu_create(
pup->menu_func = menu_func;
pup->menu_arg = arg;
- handle = ui_popup_block_create(C, butregion, but, NULL, ui_block_func_POPUP, pup, NULL);
+ handle = ui_popup_block_create(C, butregion, but, nullptr, ui_block_func_POPUP, pup, nullptr);
if (!but) {
handle->popup = true;
@@ -374,10 +377,10 @@ uiPopupMenu *UI_popup_menu_begin_ex(bContext *C,
int icon)
{
const uiStyle *style = UI_style_get_dpi();
- uiPopupMenu *pup = MEM_callocN(sizeof(uiPopupMenu), "popup menu");
+ uiPopupMenu *pup = MEM_cnew<uiPopupMenu>(__func__);
uiBut *but;
- pup->block = UI_block_begin(C, NULL, block_name, UI_EMBOSS_PULLDOWN);
+ pup->block = UI_block_begin(C, nullptr, block_name, UI_EMBOSS_PULLDOWN);
pup->block->flag |= UI_BLOCK_POPUP_MEMORY | UI_BLOCK_IS_FLIP;
pup->block->puphash = ui_popup_menu_hash(title);
pup->layout = UI_block_layout(
@@ -389,7 +392,7 @@ uiPopupMenu *UI_popup_menu_begin_ex(bContext *C,
uiLayoutSetOperatorContext(pup->layout, WM_OP_EXEC_REGION_WIN);
/* create in advance so we can let buttons point to retval already */
- pup->block->handle = MEM_callocN(sizeof(uiPopupBlockHandle), "uiPopupBlockHandle");
+ pup->block->handle = MEM_cnew<uiPopupBlockHandle>(__func__);
/* create title button */
if (title[0]) {
@@ -406,7 +409,7 @@ uiPopupMenu *UI_popup_menu_begin_ex(bContext *C,
0,
200,
UI_UNIT_Y,
- NULL,
+ nullptr,
0.0,
0.0,
0,
@@ -415,7 +418,7 @@ uiPopupMenu *UI_popup_menu_begin_ex(bContext *C,
}
else {
but = uiDefBut(
- pup->block, UI_BTYPE_LABEL, 0, title, 0, 0, 200, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
+ pup->block, UI_BTYPE_LABEL, 0, title, 0, 0, 200, UI_UNIT_Y, nullptr, 0.0, 0.0, 0, 0, "");
but->drawflag = UI_BUT_TEXT_LEFT;
}
@@ -440,8 +443,8 @@ void UI_popup_menu_end(bContext *C, uiPopupMenu *pup)
{
wmWindow *window = CTX_wm_window(C);
uiPopupBlockHandle *menu;
- uiBut *but = NULL;
- ARegion *butregion = NULL;
+ uiBut *but = nullptr;
+ ARegion *butregion = nullptr;
pup->popup = true;
pup->mx = window->eventstate->xy[0];
@@ -452,7 +455,7 @@ void UI_popup_menu_end(bContext *C, uiPopupMenu *pup)
butregion = pup->butregion;
}
- menu = ui_popup_block_create(C, butregion, but, NULL, ui_block_func_POPUP, pup, NULL);
+ menu = ui_popup_block_create(C, butregion, but, nullptr, ui_block_func_POPUP, pup, nullptr);
menu->popup = true;
UI_popup_handlers_add(C, &window->modalhandlers, menu, 0);
@@ -467,7 +470,7 @@ bool UI_popup_menu_end_or_cancel(bContext *C, uiPopupMenu *pup)
UI_popup_menu_end(C, pup);
return true;
}
- UI_block_layout_resolve(pup->block, NULL, NULL);
+ UI_block_layout_resolve(pup->block, nullptr, nullptr);
MEM_freeN(pup->block->handle);
UI_block_free(C, pup->block);
MEM_freeN(pup);
@@ -487,7 +490,7 @@ uiLayout *UI_popup_menu_layout(uiPopupMenu *pup)
void UI_popup_menu_reports(bContext *C, ReportList *reports)
{
- uiPopupMenu *pup = NULL;
+ uiPopupMenu *pup = nullptr;
uiLayout *layout;
if (!CTX_wm_window(C)) {
@@ -502,7 +505,7 @@ void UI_popup_menu_reports(bContext *C, ReportList *reports)
continue;
}
- if (pup == NULL) {
+ if (pup == nullptr) {
char title[UI_MAX_DRAW_STR];
BLI_snprintf(title, sizeof(title), "%s: %s", IFACE_("Report"), report->typestr);
/* popup_menu stuff does just what we need (but pass meaningful block name) */
@@ -540,7 +543,7 @@ int UI_popup_menu_invoke(bContext *C, const char *idname, ReportList *reports)
uiLayout *layout;
MenuType *mt = WM_menutype_find(idname, true);
- if (mt == NULL) {
+ if (mt == nullptr) {
BKE_reportf(reports, RPT_ERROR, "Menu \"%s\" not found", idname);
return OPERATOR_CANCELLED;
}
@@ -572,7 +575,7 @@ void UI_popup_block_invoke_ex(
wmWindow *window = CTX_wm_window(C);
uiPopupBlockHandle *handle;
- handle = ui_popup_block_create(C, NULL, NULL, func, NULL, arg, arg_free);
+ handle = ui_popup_block_create(C, nullptr, nullptr, func, nullptr, arg, arg_free);
handle->popup = true;
/* It can be useful to disable refresh (even though it will work)
@@ -580,7 +583,8 @@ void UI_popup_block_invoke_ex(
handle->can_refresh = can_refresh;
UI_popup_handlers_add(C, &window->modalhandlers, handle, 0);
- UI_block_active_only_flagged_buttons(C, handle->region, handle->region->uiblocks.first);
+ UI_block_active_only_flagged_buttons(
+ C, handle->region, static_cast<uiBlock *>(handle->region->uiblocks.first));
WM_event_add_mousemove(window);
}
@@ -599,7 +603,7 @@ void UI_popup_block_ex(bContext *C,
wmWindow *window = CTX_wm_window(C);
uiPopupBlockHandle *handle;
- handle = ui_popup_block_create(C, NULL, NULL, func, NULL, arg, NULL);
+ handle = ui_popup_block_create(C, nullptr, nullptr, func, nullptr, arg, nullptr);
handle->popup = true;
handle->retvalue = 1;
handle->can_refresh = true;
@@ -611,7 +615,8 @@ void UI_popup_block_ex(bContext *C,
// handle->opcontext = opcontext;
UI_popup_handlers_add(C, &window->modalhandlers, handle, 0);
- UI_block_active_only_flagged_buttons(C, handle->region, handle->region->uiblocks.first);
+ UI_block_active_only_flagged_buttons(
+ C, handle->region, static_cast<uiBlock *>(handle->region->uiblocks.first));
WM_event_add_mousemove(window);
}
@@ -621,7 +626,7 @@ void uiPupBlockOperator(bContext *C, uiBlockCreateFunc func, wmOperator *op, wmO
wmWindow *window = CTX_wm_window(C);
uiPopupBlockHandle *handle;
- handle = ui_popup_block_create(C, NULL, NULL, func, NULL, op, NULL);
+ handle = ui_popup_block_create(C, nullptr, nullptr, func, nullptr, op, nullptr);
handle->popup = 1;
handle->retvalue = 1;
handle->can_refresh = true;
@@ -638,7 +643,7 @@ void uiPupBlockOperator(bContext *C, uiBlockCreateFunc func, wmOperator *op, wmO
void UI_popup_block_close(bContext *C, wmWindow *win, uiBlock *block)
{
- /* if loading new .blend while popup is open, window will be NULL */
+ /* if loading new .blend while popup is open, window will be nullptr */
if (block->handle) {
if (win) {
const bScreen *screen = WM_window_get_active_screen(win);
diff --git a/source/blender/editors/interface/interface_region_popover.c b/source/blender/editors/interface/interface_region_popover.cc
index 7c7c9e887dd..2e10261a4f7 100644
--- a/source/blender/editors/interface/interface_region_popover.c
+++ b/source/blender/editors/interface/interface_region_popover.cc
@@ -80,7 +80,7 @@ static void ui_popover_create_block(bContext *C, uiPopover *pup, wmOperatorCallC
const uiStyle *style = UI_style_get_dpi();
- pup->block = UI_block_begin(C, NULL, __func__, UI_EMBOSS);
+ pup->block = UI_block_begin(C, nullptr, __func__, UI_EMBOSS);
UI_block_flag_enable(pup->block, UI_BLOCK_KEEP_OPEN | UI_BLOCK_POPOVER);
#ifdef USE_UI_POPOVER_ONCE
if (pup->is_once) {
@@ -104,7 +104,7 @@ static void ui_popover_create_block(bContext *C, uiPopover *pup, wmOperatorCallC
static uiBlock *ui_block_func_POPOVER(bContext *C, uiPopupBlockHandle *handle, void *arg_pup)
{
- uiPopover *pup = arg_pup;
+ uiPopover *pup = static_cast<uiPopover *>(arg_pup);
/* Create UI block and layout now if it wasn't done between begin/end. */
if (!pup->layout) {
@@ -113,10 +113,10 @@ static uiBlock *ui_block_func_POPOVER(bContext *C, uiPopupBlockHandle *handle, v
if (pup->menu_func) {
pup->block->handle = handle;
pup->menu_func(C, pup->layout, pup->menu_arg);
- pup->block->handle = NULL;
+ pup->block->handle = nullptr;
}
- pup->layout = NULL;
+ pup->layout = nullptr;
}
/* Setup and resolve UI layout for block. */
@@ -185,10 +185,10 @@ static uiBlock *ui_block_func_POPOVER(bContext *C, uiPopupBlockHandle *handle, v
block->minbounds = UI_MENU_WIDTH_MIN;
if (!handle->refresh) {
- uiBut *but = NULL;
- uiBut *but_first = NULL;
+ uiBut *but = nullptr;
+ uiBut *but_first = nullptr;
LISTBASE_FOREACH (uiBut *, but_iter, &block->buttons) {
- if ((but_first == NULL) && ui_but_is_editable(but_iter)) {
+ if ((but_first == nullptr) && ui_but_is_editable(but_iter)) {
but_first = but_iter;
}
if (but_iter->flag & (UI_SELECT | UI_SELECT_DRAW)) {
@@ -219,8 +219,8 @@ static uiBlock *ui_block_func_POPOVER(bContext *C, uiPopupBlockHandle *handle, v
static void ui_block_free_func_POPOVER(void *arg_pup)
{
- uiPopover *pup = arg_pup;
- if (pup->keymap != NULL) {
+ uiPopover *pup = static_cast<uiPopover *>(arg_pup);
+ if (pup->keymap != nullptr) {
wmWindow *window = pup->window;
WM_event_remove_keymap_handler(&window->modalhandlers, pup->keymap);
}
@@ -235,7 +235,7 @@ uiPopupBlockHandle *ui_popover_panel_create(
const PanelType *panel_type = (PanelType *)arg;
/* Create popover, buttons are created from callback. */
- uiPopover *pup = MEM_callocN(sizeof(uiPopover), __func__);
+ uiPopover *pup = MEM_cnew<uiPopover>(__func__);
pup->but = but;
/* FIXME: maybe one day we want non panel popovers? */
@@ -262,7 +262,7 @@ uiPopupBlockHandle *ui_popover_panel_create(
/* Create popup block. */
uiPopupBlockHandle *handle;
handle = ui_popup_block_create(
- C, butregion, but, NULL, ui_block_func_POPOVER, pup, ui_block_free_func_POPOVER);
+ C, butregion, but, nullptr, ui_block_func_POPOVER, pup, ui_block_free_func_POPOVER);
handle->can_refresh = true;
/* Add handlers. If attached to a button, the button will already
@@ -286,7 +286,7 @@ int UI_popover_panel_invoke(bContext *C, const char *idname, bool keep_open, Rep
{
uiLayout *layout;
PanelType *pt = WM_paneltype_find(idname, true);
- if (pt == NULL) {
+ if (pt == nullptr) {
BKE_reportf(reports, RPT_ERROR, "Panel \"%s\" not found", idname);
return OPERATOR_CANCELLED;
}
@@ -296,23 +296,23 @@ int UI_popover_panel_invoke(bContext *C, const char *idname, bool keep_open, Rep
return (OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH);
}
- uiBlock *block = NULL;
+ uiBlock *block = nullptr;
if (keep_open) {
uiPopupBlockHandle *handle = ui_popover_panel_create(
- C, NULL, NULL, ui_item_paneltype_func, pt);
- uiPopover *pup = handle->popup_create_vars.arg;
+ C, nullptr, nullptr, ui_item_paneltype_func, pt);
+ uiPopover *pup = static_cast<uiPopover *>(handle->popup_create_vars.arg);
block = pup->block;
}
else {
uiPopover *pup = UI_popover_begin(C, U.widget_unit * pt->ui_units_x, false);
layout = UI_popover_layout(pup);
UI_paneltype_draw(C, pt, layout);
- UI_popover_end(C, pup, NULL);
+ UI_popover_end(C, pup, nullptr);
block = pup->block;
}
if (block) {
- uiPopupBlockHandle *handle = block->handle;
+ uiPopupBlockHandle *handle = static_cast<uiPopupBlockHandle *>(block->handle);
UI_block_active_only_flagged_buttons(C, handle->region, block);
}
return OPERATOR_INTERFACE;
@@ -326,20 +326,20 @@ int UI_popover_panel_invoke(bContext *C, const char *idname, bool keep_open, Rep
uiPopover *UI_popover_begin(bContext *C, int ui_menu_width, bool from_active_button)
{
- uiPopover *pup = MEM_callocN(sizeof(uiPopover), "popover menu");
+ uiPopover *pup = MEM_cnew<uiPopover>(__func__);
if (ui_menu_width == 0) {
ui_menu_width = U.widget_unit * UI_POPOVER_WIDTH_UNITS;
}
pup->ui_size_x = ui_menu_width;
- ARegion *butregion = NULL;
- uiBut *but = NULL;
+ ARegion *butregion = nullptr;
+ uiBut *but = nullptr;
if (from_active_button) {
butregion = CTX_wm_region(C);
but = UI_region_active_but_get(butregion);
- if (but == NULL) {
- butregion = NULL;
+ if (but == nullptr) {
+ butregion = nullptr;
}
}
@@ -350,14 +350,14 @@ uiPopover *UI_popover_begin(bContext *C, int ui_menu_width, bool from_active_but
ui_popover_create_block(C, pup, WM_OP_EXEC_REGION_WIN);
/* create in advance so we can let buttons point to retval already */
- pup->block->handle = MEM_callocN(sizeof(uiPopupBlockHandle), "uiPopupBlockHandle");
+ pup->block->handle = MEM_cnew<uiPopupBlockHandle>(__func__);
return pup;
}
static void popover_keymap_fn(wmKeyMap *UNUSED(keymap), wmKeyMapItem *UNUSED(kmi), void *user_data)
{
- uiPopover *pup = user_data;
+ uiPopover *pup = static_cast<uiPopover *>(user_data);
pup->block->handle->menuretval = UI_RETURN_OK;
}
@@ -376,8 +376,13 @@ void UI_popover_end(bContext *C, uiPopover *pup, wmKeyMap *keymap)
WM_event_set_keymap_handler_post_callback(pup->keymap_handler, popover_keymap_fn, pup);
}
- handle = ui_popup_block_create(
- C, pup->butregion, pup->but, NULL, ui_block_func_POPOVER, pup, ui_block_free_func_POPOVER);
+ handle = ui_popup_block_create(C,
+ pup->butregion,
+ pup->but,
+ nullptr,
+ ui_block_func_POPOVER,
+ pup,
+ ui_block_free_func_POPOVER);
/* Add handlers. */
UI_popup_handlers_add(C, &window->modalhandlers, handle, 0);
diff --git a/source/blender/editors/interface/interface_region_popup.c b/source/blender/editors/interface/interface_region_popup.cc
index 2f2556225b5..74c228e3338 100644
--- a/source/blender/editors/interface/interface_region_popup.c
+++ b/source/blender/editors/interface/interface_region_popup.cc
@@ -7,9 +7,9 @@
* PopUp Region (Generic)
*/
-#include <stdarg.h>
-#include <stdlib.h>
-#include <string.h>
+#include <cstdarg>
+#include <cstdlib>
+#include <cstring>
#include "MEM_guardedalloc.h"
@@ -120,7 +120,7 @@ static void ui_popup_block_position(wmWindow *window,
short dir1 = 0, dir2 = 0;
if (!handle->refresh) {
- bool left = 0, right = 0, top = 0, down = 0;
+ bool left = false, right = false, top = false, down = false;
const int win_x = WM_window_pixels_x(window);
const int win_y = WM_window_pixels_y(window);
@@ -131,24 +131,24 @@ static void ui_popup_block_position(wmWindow *window,
/* check if there's space at all */
if (butrct.xmin - max_size_x + center_x > 0.0f) {
- left = 1;
+ left = true;
}
if (butrct.xmax + max_size_x - center_x < win_x) {
- right = 1;
+ right = true;
}
if (butrct.ymin - max_size_y + center_y > 0.0f) {
- down = 1;
+ down = true;
}
if (butrct.ymax + max_size_y - center_y < win_y) {
- top = 1;
+ top = true;
}
if (top == 0 && down == 0) {
if (butrct.ymin - max_size_y < win_y - butrct.ymax - max_size_y) {
- top = 1;
+ top = true;
}
else {
- down = 1;
+ down = true;
}
}
@@ -335,7 +335,7 @@ static void ui_popup_block_position(wmWindow *window,
}
/* Keep a list of these, needed for pull-down menus. */
- uiSafetyRct *saferct = MEM_callocN(sizeof(uiSafetyRct), "uiSafetyRct");
+ uiSafetyRct *saferct = MEM_cnew<uiSafetyRct>(__func__);
saferct->parent = butrct;
saferct->safety = block->safety;
BLI_freelistN(&block->saferct);
@@ -520,7 +520,7 @@ static void ui_popup_block_remove(bContext *C, uiPopupBlockHandle *handle)
CTX_wm_window_set(C, win);
ui_region_temp_remove(C, screen, handle->region);
- /* Reset context (area and region were NULL'ed when changing context window). */
+ /* Reset context (area and region were nullptr'ed when changing context window). */
CTX_wm_window_set(C, ctx_win);
CTX_wm_area_set(C, ctx_area);
CTX_wm_region_set(C, ctx_region);
@@ -548,10 +548,10 @@ uiBlock *ui_popup_block_refresh(bContext *C,
const uiBlockHandleCreateFunc handle_create_func = handle->popup_create_vars.handle_create_func;
void *arg = handle->popup_create_vars.arg;
- uiBlock *block_old = region->uiblocks.first;
+ uiBlock *block_old = static_cast<uiBlock *>(region->uiblocks.first);
uiBlock *block;
- handle->refresh = (block_old != NULL);
+ handle->refresh = (block_old != nullptr);
BLI_assert(!handle->refresh || handle->can_refresh);
@@ -573,7 +573,7 @@ uiBlock *ui_popup_block_refresh(bContext *C,
/* ensure we don't use mouse coords here! */
#ifdef DEBUG
- window->eventstate = NULL;
+ window->eventstate = nullptr;
#endif
if (block->handle) {
@@ -588,7 +588,7 @@ uiBlock *ui_popup_block_refresh(bContext *C,
region->regiondata = handle;
/* set UI_BLOCK_NUMSELECT before UI_block_end() so we get alphanumeric keys assigned */
- if (but == NULL) {
+ if (but == nullptr) {
block->flag |= UI_BLOCK_POPUP;
}
@@ -596,7 +596,7 @@ uiBlock *ui_popup_block_refresh(bContext *C,
UI_block_theme_style_set(block, UI_BLOCK_THEME_STYLE_POPUP);
/* defer this until blocks are translated (below) */
- block->oldblock = NULL;
+ block->oldblock = nullptr;
if (!block->endblock) {
UI_block_end_ex(
@@ -610,9 +610,8 @@ uiBlock *ui_popup_block_refresh(bContext *C,
handle->direction = block->direction;
}
else {
- uiSafetyRct *saferct;
/* Keep a list of these, needed for pull-down menus. */
- saferct = MEM_callocN(sizeof(uiSafetyRct), "uiSafetyRct");
+ uiSafetyRct *saferct = MEM_cnew<uiSafetyRct>(__func__);
saferct->safety = block->safety;
BLI_addhead(&block->saferct, saferct);
}
@@ -760,7 +759,6 @@ uiPopupBlockHandle *ui_popup_block_create(bContext *C,
static ARegionType type;
ARegion *region;
uiBlock *block;
- uiPopupBlockHandle *handle;
/* disable tooltips from buttons below */
if (activebut) {
@@ -770,7 +768,7 @@ uiPopupBlockHandle *ui_popup_block_create(bContext *C,
WM_cursor_set(window, WM_CURSOR_DEFAULT);
/* create handle */
- handle = MEM_callocN(sizeof(uiPopupBlockHandle), "uiPopupBlockHandle");
+ uiPopupBlockHandle *handle = MEM_cnew<uiPopupBlockHandle>(__func__);
/* store context for operator */
handle->ctx_area = CTX_wm_area(C);
@@ -782,7 +780,7 @@ uiPopupBlockHandle *ui_popup_block_create(bContext *C,
handle->popup_create_vars.arg = arg;
handle->popup_create_vars.arg_free = arg_free;
handle->popup_create_vars.but = but;
- handle->popup_create_vars.butregion = but ? butregion : NULL;
+ handle->popup_create_vars.butregion = but ? butregion : nullptr;
copy_v2_v2_int(handle->popup_create_vars.event_xy, window->eventstate->xy);
/* don't allow by default, only if popup type explicitly supports it */
@@ -816,7 +814,7 @@ void ui_popup_block_free(bContext *C, uiPopupBlockHandle *handle)
/* If this popup is created from a popover which does NOT have keep-open flag set,
* then close the popover too. We could extend this to other popup types too. */
ARegion *region = handle->popup_create_vars.butregion;
- if (region != NULL) {
+ if (region != nullptr) {
LISTBASE_FOREACH (uiBlock *, block, &region->uiblocks) {
if (block->handle && (block->flag & UI_BLOCK_POPOVER) &&
(block->flag & UI_BLOCK_KEEP_OPEN) == 0) {
diff --git a/source/blender/editors/interface/interface_regions.c b/source/blender/editors/interface/interface_regions.cc
index ea6d293e52f..1a2c1f7919c 100644
--- a/source/blender/editors/interface/interface_regions.c
+++ b/source/blender/editors/interface/interface_regions.cc
@@ -25,7 +25,7 @@
ARegion *ui_region_temp_add(bScreen *screen)
{
- ARegion *region = MEM_callocN(sizeof(ARegion), __func__);
+ ARegion *region = MEM_cnew<ARegion>(__func__);
BLI_addtail(&screen->regionbase, region);
region->regiontype = RGN_TYPE_TEMPORARY;
@@ -45,6 +45,6 @@ void ui_region_temp_remove(bContext *C, bScreen *screen, ARegion *region)
}
ED_region_exit(C, region);
- BKE_area_region_free(NULL, region); /* NULL: no spacetype */
+ BKE_area_region_free(nullptr, region); /* nullptr: no spacetype */
BLI_freelinkN(&screen->regionbase, region);
}
diff --git a/source/blender/editors/interface/interface_style.c b/source/blender/editors/interface/interface_style.cc
index 76023f3033f..b4e97f8a396 100644
--- a/source/blender/editors/interface/interface_style.c
+++ b/source/blender/editors/interface/interface_style.cc
@@ -5,11 +5,11 @@
* \ingroup edinterface
*/
-#include <limits.h>
-#include <math.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
+#include <climits>
+#include <cmath>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
#include "MEM_guardedalloc.h"
@@ -57,7 +57,7 @@
static uiStyle *ui_style_new(ListBase *styles, const char *name, short uifont_id)
{
- uiStyle *style = MEM_callocN(sizeof(uiStyle), "new style");
+ uiStyle *style = MEM_cnew<uiStyle>(__func__);
BLI_addtail(styles, style);
BLI_strncpy(style->name, name, MAX_STYLE_NAME);
@@ -108,14 +108,14 @@ static uiStyle *ui_style_new(ListBase *styles, const char *name, short uifont_id
static uiFont *uifont_to_blfont(int id)
{
- uiFont *font = U.uifonts.first;
+ uiFont *font = static_cast<uiFont *>(U.uifonts.first);
for (; font; font = font->next) {
if (font->uifont_id == id) {
return font;
}
}
- return U.uifonts.first;
+ return static_cast<uiFont *>(U.uifonts.first);
}
/* *************** draw ************************ */
@@ -198,7 +198,7 @@ void UI_fontstyle_draw(const uiFontStyle *fs,
const uchar col[4],
const struct uiFontStyleDraw_Params *fs_params)
{
- UI_fontstyle_draw_ex(fs, rect, str, str_len, col, fs_params, NULL, NULL, NULL);
+ UI_fontstyle_draw_ex(fs, rect, str, str_len, col, fs_params, nullptr, nullptr, nullptr);
}
void UI_fontstyle_draw_rotated(const uiFontStyle *fs,
@@ -284,17 +284,13 @@ void UI_fontstyle_draw_simple_backdrop(const uiFontStyle *fs,
const float decent = BLF_descender(fs->uifont_id);
const float margin = height / 4.0f;
+ rctf rect;
+ rect.xmin = x - margin;
+ rect.xmax = x + width + margin;
+ rect.ymin = (y + decent) - margin;
+ rect.ymax = (y + decent) + height + margin;
UI_draw_roundbox_corner_set(UI_CNR_ALL);
- UI_draw_roundbox_4fv(
- &(const rctf){
- .xmin = x - margin,
- .xmax = x + width + margin,
- .ymin = (y + decent) - margin,
- .ymax = (y + decent) + height + margin,
- },
- true,
- margin,
- col_bg);
+ UI_draw_roundbox_4fv(&rect, true, margin, col_bg);
}
BLF_position(fs->uifont_id, x, y, 0.0f);
@@ -307,12 +303,12 @@ void UI_fontstyle_draw_simple_backdrop(const uiFontStyle *fs,
const uiStyle *UI_style_get(void)
{
#if 0
- uiStyle *style = NULL;
+ uiStyle *style = nullptr;
/* offset is two struct uiStyle pointers */
style = BLI_findstring(&U.uistyles, "Unifont Style", sizeof(style) * 2);
- return (style != NULL) ? style : U.uistyles.first;
+ return (style != nullptr) ? style : U.uistyles.first;
#else
- return U.uistyles.first;
+ return static_cast<const uiStyle *>(U.uistyles.first);
#endif
}
@@ -378,7 +374,7 @@ int UI_fontstyle_height_max(const uiFontStyle *fs)
void uiStyleInit(void)
{
- const uiStyle *style = U.uistyles.first;
+ const uiStyle *style = static_cast<uiStyle *>(U.uistyles.first);
/* recover from uninitialized dpi */
if (U.dpi == 0) {
@@ -400,11 +396,11 @@ void uiStyleInit(void)
blf_mono_font_render = -1;
}
- uiFont *font_first = U.uifonts.first;
+ uiFont *font_first = static_cast<uiFont *>(U.uifonts.first);
/* default builtin */
- if (font_first == NULL) {
- font_first = MEM_callocN(sizeof(uiFont), "ui font");
+ if (font_first == nullptr) {
+ font_first = MEM_cnew<uiFont>(__func__);
BLI_addtail(&U.uifonts, font_first);
}
@@ -439,7 +435,7 @@ void uiStyleInit(void)
}
}
- if (style == NULL) {
+ if (style == nullptr) {
style = ui_style_new(&U.uistyles, "Default Style", UIFONT_DEFAULT);
}
diff --git a/source/blender/editors/interface/interface_utils.c b/source/blender/editors/interface/interface_utils.cc
index 728d42a9353..b796f07c24b 100644
--- a/source/blender/editors/interface/interface_utils.c
+++ b/source/blender/editors/interface/interface_utils.cc
@@ -5,17 +5,16 @@
* \ingroup edinterface
*/
-#include <ctype.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
+#include <cctype>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
#include "DNA_object_types.h"
#include "DNA_screen_types.h"
#include "ED_screen.h"
-#include "BLI_alloca.h"
#include "BLI_listbase.h"
#include "BLI_math.h"
#include "BLI_string.h"
@@ -55,12 +54,12 @@ uiBut *uiDefAutoButR(uiBlock *block,
int width,
int height)
{
- uiBut *but = NULL;
+ uiBut *but = nullptr;
switch (RNA_property_type(prop)) {
case PROP_BOOLEAN: {
if (RNA_property_array_check(prop) && index == -1) {
- return NULL;
+ return nullptr;
}
if (icon && name && name[0] == '\0') {
@@ -79,7 +78,7 @@ uiBut *uiDefAutoButR(uiBlock *block,
0,
-1,
-1,
- NULL);
+ nullptr);
}
else if (icon) {
but = uiDefIconTextButR_prop(block,
@@ -98,7 +97,7 @@ uiBut *uiDefAutoButR(uiBlock *block,
0,
-1,
-1,
- NULL);
+ nullptr);
}
else {
but = uiDefButR_prop(block,
@@ -116,7 +115,7 @@ uiBut *uiDefAutoButR(uiBlock *block,
0,
-1,
-1,
- NULL);
+ nullptr);
}
break;
}
@@ -139,10 +138,10 @@ uiBut *uiDefAutoButR(uiBlock *block,
0,
0,
0,
- NULL);
+ nullptr);
}
else {
- return NULL;
+ return nullptr;
}
}
else if (RNA_property_subtype(prop) == PROP_PERCENTAGE ||
@@ -162,11 +161,25 @@ uiBut *uiDefAutoButR(uiBlock *block,
0,
-1,
-1,
- NULL);
+ nullptr);
}
else {
- but = uiDefButR_prop(
- block, UI_BTYPE_NUM, 0, name, x, y, width, height, ptr, prop, index, 0, 0, 0, 0, NULL);
+ but = uiDefButR_prop(block,
+ UI_BTYPE_NUM,
+ 0,
+ name,
+ x,
+ y,
+ width,
+ height,
+ ptr,
+ prop,
+ index,
+ 0,
+ 0,
+ 0,
+ 0,
+ nullptr);
}
if (RNA_property_flag(prop) & PROP_TEXTEDIT_UPDATE) {
@@ -191,14 +204,14 @@ uiBut *uiDefAutoButR(uiBlock *block,
0,
-1,
-1,
- NULL);
+ nullptr);
}
else if (icon) {
but = uiDefIconTextButR_prop(block,
UI_BTYPE_MENU,
0,
icon,
- NULL,
+ nullptr,
x,
y,
width,
@@ -210,7 +223,7 @@ uiBut *uiDefAutoButR(uiBlock *block,
0,
-1,
-1,
- NULL);
+ nullptr);
}
else {
but = uiDefButR_prop(block,
@@ -228,7 +241,7 @@ uiBut *uiDefAutoButR(uiBlock *block,
0,
-1,
-1,
- NULL);
+ nullptr);
}
break;
case PROP_STRING:
@@ -248,7 +261,7 @@ uiBut *uiDefAutoButR(uiBlock *block,
0,
-1,
-1,
- NULL);
+ nullptr);
}
else if (icon) {
but = uiDefIconTextButR_prop(block,
@@ -267,7 +280,7 @@ uiBut *uiDefAutoButR(uiBlock *block,
0,
-1,
-1,
- NULL);
+ nullptr);
}
else {
but = uiDefButR_prop(block,
@@ -285,7 +298,7 @@ uiBut *uiDefAutoButR(uiBlock *block,
0,
-1,
-1,
- NULL);
+ nullptr);
}
if (RNA_property_flag(prop) & PROP_TEXTEDIT_UPDATE) {
@@ -319,20 +332,21 @@ uiBut *uiDefAutoButR(uiBlock *block,
0,
-1,
-1,
- NULL);
- ui_but_add_search(but, ptr, prop, NULL, NULL);
+ nullptr);
+ ui_but_add_search(but, ptr, prop, nullptr, nullptr);
break;
}
case PROP_COLLECTION: {
char text[256];
BLI_snprintf(
text, sizeof(text), IFACE_("%d items"), RNA_property_collection_length(ptr, prop));
- but = uiDefBut(block, UI_BTYPE_LABEL, 0, text, x, y, width, height, NULL, 0, 0, 0, 0, NULL);
+ but = uiDefBut(
+ block, UI_BTYPE_LABEL, 0, text, x, y, width, height, nullptr, 0, 0, 0, 0, nullptr);
UI_but_flag_enable(but, UI_BUT_DISABLED);
break;
}
default:
- but = NULL;
+ but = nullptr;
break;
}
@@ -414,7 +428,7 @@ eAutoPropButsReturn uiDefAutoButsRNA(uiLayout *layout,
case UI_BUT_LABEL_ALIGN_NONE:
default:
col = layout;
- name = NULL; /* no smart label alignment, show default name with button */
+ name = nullptr; /* no smart label alignment, show default name with button */
break;
}
@@ -440,7 +454,7 @@ eAutoPropButsReturn uiDefAutoButsRNA(uiLayout *layout,
/* *** RNA collection search menu *** */
-typedef struct CollItemSearch {
+struct CollItemSearch {
struct CollItemSearch *next, *prev;
void *data;
char *name;
@@ -449,7 +463,7 @@ typedef struct CollItemSearch {
bool is_id;
int name_prefix_offset;
uint has_sep_char : 1;
-} CollItemSearch;
+};
static bool add_collection_search_item(CollItemSearch *cis,
const bool requires_exact_data_name,
@@ -462,10 +476,11 @@ static bool add_collection_search_item(CollItemSearch *cis,
* name prefix for showing the library status. */
int name_prefix_offset = cis->name_prefix_offset;
if (!has_id_icon && cis->is_id && !requires_exact_data_name) {
- cis->iconid = UI_icon_from_library(cis->data);
+ cis->iconid = UI_icon_from_library(static_cast<const ID *>(cis->data));
/* No need to re-allocate, string should be shorter than before (lib status prefix is
* removed). */
- BKE_id_full_name_ui_prefix_get(name_buf, cis->data, false, UI_SEP_CHAR, &name_prefix_offset);
+ BKE_id_full_name_ui_prefix_get(
+ name_buf, static_cast<const ID *>(cis->data), false, UI_SEP_CHAR, &name_prefix_offset);
BLI_assert(strlen(name_buf) <= MEM_allocN_len(cis->name));
strcpy(cis->name, name_buf);
}
@@ -478,15 +493,12 @@ static bool add_collection_search_item(CollItemSearch *cis,
name_prefix_offset);
}
-void ui_rna_collection_search_update_fn(const struct bContext *C,
- void *arg,
- const char *str,
- uiSearchItems *items,
- const bool is_first)
+void ui_rna_collection_search_update_fn(
+ const bContext *C, void *arg, const char *str, uiSearchItems *items, const bool is_first)
{
- uiRNACollectionSearch *data = arg;
+ uiRNACollectionSearch *data = static_cast<uiRNACollectionSearch *>(arg);
const int flag = RNA_property_flag(data->target_prop);
- ListBase *items_list = MEM_callocN(sizeof(ListBase), "items_list");
+ ListBase *items_list = MEM_cnew<ListBase>("items_list");
const bool is_ptr_target = (RNA_property_type(data->target_prop) == PROP_POINTER);
/* For non-pointer properties, UI code acts entirely based on the item's name. So the name has to
* match the RNA name exactly. So only for pointer properties, the name can be modified to add
@@ -497,7 +509,7 @@ void ui_rna_collection_search_update_fn(const struct bContext *C,
char *name;
bool has_id_icon = false;
- StringSearch *search = skip_filter ? NULL : BLI_string_search_new();
+ StringSearch *search = skip_filter ? nullptr : BLI_string_search_new();
/* build a temporary list of relevant items first */
int item_index = 0;
@@ -522,18 +534,17 @@ void ui_rna_collection_search_update_fn(const struct bContext *C,
const bool is_id = itemptr.type && RNA_struct_is_ID(itemptr.type);
if (is_id) {
- iconid = ui_id_icon_get(C, itemptr.data, false);
+ iconid = ui_id_icon_get(C, static_cast<ID *>(itemptr.data), false);
if (!ELEM(iconid, 0, ICON_BLANK1)) {
has_id_icon = true;
}
if (requires_exact_data_name) {
- name = RNA_struct_name_get_alloc(&itemptr, name_buf, sizeof(name_buf), NULL);
+ name = RNA_struct_name_get_alloc(&itemptr, name_buf, sizeof(name_buf), nullptr);
}
else {
- const ID *id = itemptr.data;
- BKE_id_full_name_ui_prefix_get(
- name_buf, itemptr.data, true, UI_SEP_CHAR, &name_prefix_offset);
+ const ID *id = static_cast<ID *>(itemptr.data);
+ BKE_id_full_name_ui_prefix_get(name_buf, id, true, UI_SEP_CHAR, &name_prefix_offset);
BLI_STATIC_ASSERT(sizeof(name_buf) >= MAX_ID_FULL_NAME_UI,
"Name string buffer should be big enough to hold full UI ID name");
name = name_buf;
@@ -541,11 +552,11 @@ void ui_rna_collection_search_update_fn(const struct bContext *C,
}
}
else {
- name = RNA_struct_name_get_alloc(&itemptr, name_buf, sizeof(name_buf), NULL);
+ name = RNA_struct_name_get_alloc(&itemptr, name_buf, sizeof(name_buf), nullptr);
}
if (name) {
- CollItemSearch *cis = MEM_callocN(sizeof(CollItemSearch), "CollectionItemSearch");
+ CollItemSearch *cis = MEM_cnew<CollItemSearch>(__func__);
cis->data = itemptr.data;
cis->name = BLI_strdup(name);
cis->index = item_index;
@@ -597,7 +608,7 @@ void ui_rna_collection_search_update_fn(const struct bContext *C,
int UI_icon_from_id(const ID *id)
{
- if (id == NULL) {
+ if (id == nullptr) {
return ICON_NONE;
}
@@ -608,7 +619,7 @@ int UI_icon_from_id(const ID *id)
if (ob->type == OB_EMPTY) {
return ICON_EMPTY_DATA;
}
- return UI_icon_from_id(ob->data);
+ return UI_icon_from_id(static_cast<const ID *>(ob->data));
}
/* otherwise get it through RNA, creating the pointer
@@ -761,7 +772,7 @@ bool UI_but_online_manual_id(const uiBut *but, char *r_str, size_t maxlength)
return false;
}
-bool UI_but_online_manual_id_from_active(const struct bContext *C, char *r_str, size_t maxlength)
+bool UI_but_online_manual_id_from_active(const bContext *C, char *r_str, size_t maxlength)
{
uiBut *but = UI_context_active_but_get(C);
@@ -861,7 +872,7 @@ void UI_but_ensure_in_view(const bContext *C, ARegion *region, const uiBut *but)
* Modal Button Store API.
*
* Store for modal operators & handlers to register button pointers
- * which are maintained while drawing or NULL when removed.
+ * which are maintained while drawing or nullptr when removed.
*
* This is needed since button pointers are continuously freed and re-allocated.
*
@@ -880,7 +891,7 @@ struct uiButStoreElem {
uiButStore *UI_butstore_create(uiBlock *block)
{
- uiButStore *bs_handle = MEM_callocN(sizeof(uiButStore), __func__);
+ uiButStore *bs_handle = MEM_cnew<uiButStore>(__func__);
bs_handle->block = block;
BLI_addtail(&block->butstore, bs_handle);
@@ -899,7 +910,7 @@ void UI_butstore_free(uiBlock *block, uiButStore *bs_handle)
* Ideally we would manage moving the 'uiButStore', keeping a correct state.
* All things considered this is the most straightforward fix - Campbell.
*/
- if (block != bs_handle->block && bs_handle->block != NULL) {
+ if (block != bs_handle->block && bs_handle->block != nullptr) {
block = bs_handle->block;
}
@@ -912,7 +923,7 @@ void UI_butstore_free(uiBlock *block, uiButStore *bs_handle)
bool UI_butstore_is_valid(uiButStore *bs)
{
- return (bs->block != NULL);
+ return (bs->block != nullptr);
}
bool UI_butstore_is_registered(uiBlock *block, uiBut *but)
@@ -930,7 +941,7 @@ bool UI_butstore_is_registered(uiBlock *block, uiBut *but)
void UI_butstore_register(uiButStore *bs_handle, uiBut **but_p)
{
- uiButStoreElem *bs_elem = MEM_callocN(sizeof(uiButStoreElem), __func__);
+ uiButStoreElem *bs_elem = MEM_cnew<uiButStoreElem>(__func__);
BLI_assert(*but_p);
bs_elem->but_p = but_p;
@@ -968,9 +979,9 @@ bool UI_butstore_register_update(uiBlock *block, uiBut *but_dst, const uiBut *bu
void UI_butstore_clear(uiBlock *block)
{
LISTBASE_FOREACH (uiButStore *, bs_handle, &block->butstore) {
- bs_handle->block = NULL;
+ bs_handle->block = nullptr;
LISTBASE_FOREACH (uiButStoreElem *, bs_elem, &bs_handle->items) {
- *bs_elem->but_p = NULL;
+ *bs_elem->but_p = nullptr;
}
}
}
@@ -984,14 +995,14 @@ void UI_butstore_update(uiBlock *block)
}
}
- if (LIKELY(block->butstore.first == NULL)) {
+ if (LIKELY(block->butstore.first == nullptr)) {
return;
}
/* warning, loop-in-loop, in practice we only store <10 buttons at a time,
* so this isn't going to be a problem, if that changes old-new mapping can be cached first */
LISTBASE_FOREACH (uiButStore *, bs_handle, &block->butstore) {
- BLI_assert(ELEM(bs_handle->block, NULL, block) ||
+ BLI_assert(ELEM(bs_handle->block, nullptr, block) ||
(block->oldblock && block->oldblock == bs_handle->block));
if (bs_handle->block == block->oldblock) {
@@ -1001,7 +1012,7 @@ void UI_butstore_update(uiBlock *block)
if (*bs_elem->but_p) {
uiBut *but_new = ui_but_find_new(block, *bs_elem->but_p);
- /* can be NULL if the buttons removed,
+ /* can be nullptr if the buttons removed,
* NOTE: we could allow passing in a callback when buttons are removed
* so the caller can cleanup */
*bs_elem->but_p = but_new;
diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c
index b33cab3cbc6..a16c24f63cd 100644
--- a/source/blender/editors/interface/interface_widgets.c
+++ b/source/blender/editors/interface/interface_widgets.c
@@ -1178,7 +1178,7 @@ static bool draw_widgetbase_batch_skip_draw_cache(void)
{
/* MacOS is known to have issues on Mac Mini and MacBook Pro with Intel Iris GPU.
* For example, T78307. */
- if (GPU_type_matches(GPU_DEVICE_INTEL, GPU_OS_MAC, GPU_DRIVER_ANY)) {
+ if (GPU_type_matches_ex(GPU_DEVICE_INTEL, GPU_OS_MAC, GPU_DRIVER_ANY, GPU_BACKEND_OPENGL)) {
return true;
}
@@ -3745,8 +3745,8 @@ static void widget_numslider(
widget_init(&wtb1);
/* Backdrop first. */
- const float ofs = widget_radius_from_zoom(zoom, wcol);
- round_box_edges(&wtb, roundboxalign, rect, ofs);
+ const float rad = widget_radius_from_zoom(zoom, wcol);
+ round_box_edges(&wtb, roundboxalign, rect, rad);
wtb.draw_outline = false;
widgetbase_draw(&wtb, wcol);
@@ -3801,24 +3801,27 @@ static void widget_numslider(
const float width = (float)BLI_rcti_size_x(rect);
factor_ui = factor * width;
+ /* The rectangle width needs to be at least twice the corner radius for the round corners
+ * to be drawn properly. */
+ const float min_width = 2.0f * rad;
- if (factor_ui <= ofs) {
- /* Left part only. */
- roundboxalign_slider &= ~(UI_CNR_TOP_RIGHT | UI_CNR_BOTTOM_RIGHT);
- rect1.xmax = rect1.xmin + ofs;
- factor_discard = factor_ui / ofs;
+ if (factor_ui > width - rad) {
+ /* Left part + middle part + right part. */
+ factor_discard = factor;
}
- else if (factor_ui <= width - ofs) {
+ else if (factor_ui > min_width) {
/* Left part + middle part. */
roundboxalign_slider &= ~(UI_CNR_TOP_RIGHT | UI_CNR_BOTTOM_RIGHT);
rect1.xmax = rect1.xmin + factor_ui;
}
else {
- /* Left part + middle part + right part. */
- factor_discard = factor;
+ /* Left part */
+ roundboxalign_slider &= ~(UI_CNR_TOP_RIGHT | UI_CNR_BOTTOM_RIGHT);
+ rect1.xmax = rect1.xmin + min_width;
+ factor_discard = factor_ui / min_width;
}
- round_box_edges(&wtb1, roundboxalign_slider, &rect1, ofs);
+ round_box_edges(&wtb1, roundboxalign_slider, &rect1, rad);
wtb1.draw_outline = false;
widgetbase_set_uniform_discard_factor(&wtb1, factor_discard);
widgetbase_draw(&wtb1, wcol);
diff --git a/source/blender/editors/interface/view2d.c b/source/blender/editors/interface/view2d.c
index 8962e1462b6..bf3c8362ce6 100644
--- a/source/blender/editors/interface/view2d.c
+++ b/source/blender/editors/interface/view2d.c
@@ -1268,59 +1268,67 @@ static void grid_axis_start_and_count(
}
}
-typedef struct DotGridLevelInfo {
- /* The factor applied to the #min_step argument. This could be easily computed in runtime,
- * but seeing it together with the other values is helpful. */
- float step_factor;
- /* The normalized zoom level at which the grid level starts to fade in.
- * At lower zoom levels, the points will not be visible and the level will be skipped. */
- float fade_in_start_zoom;
- /* The normalized zoom level at which the grid finishes fading in.
- * At higher zoom levels, the points will be opaque. */
- float fade_in_end_zoom;
-} DotGridLevelInfo;
-
-static const DotGridLevelInfo level_info[9] = {
- {6.4f, -0.1f, 0.01f},
- {3.2f, 0.0f, 0.025f},
- {1.6f, 0.025f, 0.15f},
- {0.8f, 0.05f, 0.2f},
- {0.4f, 0.1f, 0.25f},
- {0.2f, 0.125f, 0.3f},
- {0.1f, 0.25f, 0.5f},
- {0.05f, 0.7f, 0.9f},
- {0.025f, 0.6f, 0.9f},
-};
-
void UI_view2d_dot_grid_draw(const View2D *v2d,
const int grid_color_id,
const float min_step,
- const int grid_levels)
+ const int grid_subdivisions)
{
- BLI_assert(grid_levels >= 0 && grid_levels < 10);
+ BLI_assert(grid_subdivisions >= 0 && grid_subdivisions < 4);
+ if (grid_subdivisions == 0) {
+ return;
+ }
+
const float zoom_x = (float)(BLI_rcti_size_x(&v2d->mask) + 1) / BLI_rctf_size_x(&v2d->cur);
- const float zoom_normalized = (zoom_x - v2d->minzoom) / (v2d->maxzoom - v2d->minzoom);
GPUVertFormat *format = immVertexFormat();
const uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
const uint color_id = GPU_vertformat_attr_add(format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR);
- GPU_point_size(3.0f * UI_DPI_FAC);
- float color[4];
- UI_GetThemeColor3fv(grid_color_id, color);
+ /* Scaling the dots fully with the zoom looks too busy, but a bit of size variation is nice. */
+ const float min_point_size = 2.0f * UI_DPI_FAC;
+ const float point_size_factor = 1.5f;
+ const float max_point_size = point_size_factor * min_point_size;
+
+ /* Each consecutive grid level is five times larger than the previous. */
+ const int subdivision_scale = 5;
+
+ const float view_level = logf(min_step / zoom_x) / logf(subdivision_scale);
+ const int largest_visible_level = (int)view_level;
- for (int level = 0; level < grid_levels; level++) {
- const DotGridLevelInfo *info = &level_info[level];
- const float step = min_step * info->step_factor * U.widget_unit;
+ for (int level_offset = 0; level_offset <= grid_subdivisions; level_offset++) {
+ const int level = largest_visible_level - level_offset;
- const float alpha_factor = (zoom_normalized - info->fade_in_start_zoom) /
- (info->fade_in_end_zoom - info->fade_in_start_zoom);
- color[3] = clamp_f(BLI_easing_cubic_ease_in_out(alpha_factor, 0.0f, 1.0f, 1.0f), 0.0f, 1.0f);
- if (color[3] == 0.0f) {
+ if (level < 0) {
break;
}
+ const float level_scale = powf(subdivision_scale, level);
+ const float point_size_precise = min_point_size * level_scale * zoom_x;
+ const float point_size_draw = ceilf(
+ clamp_f(point_size_precise, min_point_size, max_point_size));
+
+ /* To compensate the for the clamped point_size we adjust the alpha to make the overall
+ * brightness of the grid background more consistent. */
+ const float alpha = pow2f(point_size_precise / point_size_draw);
+
+ /* Make sure we don't draw points once the alpha gets too low. */
+ const float alpha_cutoff = 0.01f;
+ if (alpha < alpha_cutoff) {
+ break;
+ }
+ const float alpha_clamped = clamp_f((1.0f + alpha_cutoff) * alpha - alpha_cutoff, 0.0f, 1.0f);
+
+ /* If we have don't draw enough subdivision levels so they fade out naturally, we apply an
+ * additional fade to the last level to avoid pop in. */
+ const bool last_level = level_offset == grid_subdivisions;
+ const float subdivision_fade = last_level ? (1.0f - fractf(view_level)) : 1.0f;
+
+ float color[4];
+ UI_GetThemeColor3fv(grid_color_id, color);
+ color[3] = alpha_clamped * subdivision_fade;
+
+ const float step = min_step * level_scale;
int count_x;
float start_x;
grid_axis_start_and_count(step, v2d->cur.xmin, v2d->cur.xmax, &start_x, &count_x);
@@ -1331,6 +1339,7 @@ void UI_view2d_dot_grid_draw(const View2D *v2d,
continue;
}
+ GPU_point_size(point_size_draw);
immBegin(GPU_PRIM_POINTS, count_x * count_y);
/* Theoretically drawing on top of lower grid levels could be avoided, but it would also
diff --git a/source/blender/editors/lattice/editlattice_select.c b/source/blender/editors/lattice/editlattice_select.c
index ea99c6e23ff..54a72c7ea5d 100644
--- a/source/blender/editors/lattice/editlattice_select.c
+++ b/source/blender/editors/lattice/editlattice_select.c
@@ -664,7 +664,6 @@ bool ED_lattice_select_pick(bContext *C, const int mval[2], const struct SelectP
break;
}
case SEL_OP_SET: {
- ED_lattice_flags_set(vc.obedit, 0);
bp->f1 |= SELECT;
break;
}
diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c
index 2181b652d16..1499742af54 100644
--- a/source/blender/editors/mesh/editmesh_tools.c
+++ b/source/blender/editors/mesh/editmesh_tools.c
@@ -4712,7 +4712,7 @@ static int edbm_separate_exec(bContext *C, wmOperator *op)
Object *ob = base_iter->object;
if (ob->type == OB_MESH) {
Mesh *me = ob->data;
- if (!ID_IS_LINKED(me)) {
+ if (BKE_id_is_editable(bmain, &me->id)) {
BMesh *bm_old = NULL;
bool changed = false;
diff --git a/source/blender/editors/mesh/mesh_data.c b/source/blender/editors/mesh/mesh_data.c
index b99ff8296f3..630ef66504f 100644
--- a/source/blender/editors/mesh/mesh_data.c
+++ b/source/blender/editors/mesh/mesh_data.c
@@ -481,7 +481,8 @@ static bool layers_poll(bContext *C)
{
Object *ob = ED_object_context(C);
ID *data = (ob) ? ob->data : NULL;
- return (ob && !ID_IS_LINKED(ob) && ob->type == OB_MESH && data && !ID_IS_LINKED(data));
+ return (ob && !ID_IS_LINKED(ob) && !ID_IS_OVERRIDE_LIBRARY(ob) && ob->type == OB_MESH && data &&
+ !ID_IS_LINKED(data) && !ID_IS_OVERRIDE_LIBRARY(data));
}
/*********************** Sculpt Vertex colors operators ************************/
@@ -867,7 +868,7 @@ static bool mesh_customdata_mask_clear_poll(bContext *C)
return false;
}
- if (!ID_IS_LINKED(me)) {
+ if (!ID_IS_LINKED(me) && !ID_IS_OVERRIDE_LIBRARY(me)) {
CustomData *data = GET_CD_DATA(me, vdata);
if (CustomData_has_layer(data, CD_PAINT_MASK)) {
return true;
@@ -918,7 +919,7 @@ static int mesh_customdata_skin_state(bContext *C)
if (ob && ob->type == OB_MESH) {
Mesh *me = ob->data;
- if (!ID_IS_LINKED(me)) {
+ if (!ID_IS_LINKED(me) && !ID_IS_OVERRIDE_LIBRARY(me)) {
CustomData *data = GET_CD_DATA(me, vdata);
return CustomData_has_layer(data, CD_MVERT_SKIN);
}
diff --git a/source/blender/editors/mesh/mesh_mirror.c b/source/blender/editors/mesh/mesh_mirror.c
index b3d4757184e..82e77a88a57 100644
--- a/source/blender/editors/mesh/mesh_mirror.c
+++ b/source/blender/editors/mesh/mesh_mirror.c
@@ -166,7 +166,7 @@ void ED_mesh_mirrtopo_init(BMEditMesh *em,
const bool is_editmode = (em != NULL);
MEdge *medge = NULL, *med;
- /* editmode*/
+ /* Edit-mode variables. */
BMEdge *eed;
BMIter iter;
diff --git a/source/blender/editors/object/object_add.cc b/source/blender/editors/object/object_add.cc
index b8ffaf87118..6a7920d4d75 100644
--- a/source/blender/editors/object/object_add.cc
+++ b/source/blender/editors/object/object_add.cc
@@ -8,6 +8,7 @@
#include <cctype>
#include <cstdlib>
#include <cstring>
+#include <optional>
#include "MEM_guardedalloc.h"
@@ -1280,7 +1281,7 @@ static bool object_gpencil_add_poll(bContext *C)
Scene *scene = CTX_data_scene(C);
Object *obact = CTX_data_active_object(C);
- if ((scene == nullptr) || (ID_IS_LINKED(scene))) {
+ if ((scene == nullptr) || ID_IS_LINKED(scene) || ID_IS_OVERRIDE_LIBRARY(scene)) {
return false;
}
@@ -1629,66 +1630,100 @@ void OBJECT_OT_light_add(wmOperatorType *ot)
/** \name Add Collection Instance Operator
* \{ */
-static int collection_instance_add_exec(bContext *C, wmOperator *op)
-{
- Main *bmain = CTX_data_main(C);
+struct CollectionAddInfo {
+ /* The collection that is supposed to be added, determined through operator properties. */
Collection *collection;
+ /* The local-view bits (if any) the object should have set to become visible in current context.
+ */
ushort local_view_bits;
+ /* The transform that should be applied to the collection, determined through operator properties
+ * if set (e.g. to place the collection under the cursor), otherwise through context (e.g. 3D
+ * cursor location). */
float loc[3], rot[3];
+};
+
+static std::optional<CollectionAddInfo> collection_add_info_get_from_op(bContext *C,
+ wmOperator *op)
+{
+ CollectionAddInfo add_info{};
+
+ Main *bmain = CTX_data_main(C);
- PropertyRNA *prop_name = RNA_struct_find_property(op->ptr, "name");
PropertyRNA *prop_location = RNA_struct_find_property(op->ptr, "location");
PropertyRNA *prop_session_uuid = RNA_struct_find_property(op->ptr, "session_uuid");
+ PropertyRNA *prop_name = RNA_struct_find_property(op->ptr, "name");
bool update_location_if_necessary = false;
- if (RNA_property_is_set(op->ptr, prop_name)) {
+ if (prop_name && RNA_property_is_set(op->ptr, prop_name)) {
char name[MAX_ID_NAME - 2];
RNA_property_string_get(op->ptr, prop_name, name);
- collection = (Collection *)BKE_libblock_find_name(bmain, ID_GR, name);
+ add_info.collection = (Collection *)BKE_libblock_find_name(bmain, ID_GR, name);
update_location_if_necessary = true;
}
else if (RNA_property_is_set(op->ptr, prop_session_uuid)) {
const uint32_t session_uuid = (uint32_t)RNA_property_int_get(op->ptr, prop_session_uuid);
- collection = (Collection *)BKE_libblock_find_session_uuid(bmain, ID_GR, session_uuid);
+ add_info.collection = (Collection *)BKE_libblock_find_session_uuid(bmain, ID_GR, session_uuid);
update_location_if_necessary = true;
}
else {
- collection = static_cast<Collection *>(
+ add_info.collection = static_cast<Collection *>(
BLI_findlink(&bmain->collections, RNA_enum_get(op->ptr, "collection")));
}
if (update_location_if_necessary) {
int mval[2];
if (!RNA_property_is_set(op->ptr, prop_location) && object_add_drop_xy_get(C, op, &mval)) {
- ED_object_location_from_view(C, loc);
- ED_view3d_cursor3d_position(C, mval, false, loc);
- RNA_property_float_set_array(op->ptr, prop_location, loc);
+ ED_object_location_from_view(C, add_info.loc);
+ ED_view3d_cursor3d_position(C, mval, false, add_info.loc);
+ RNA_property_float_set_array(op->ptr, prop_location, add_info.loc);
}
}
- if (collection == nullptr) {
- return OPERATOR_CANCELLED;
+ if (add_info.collection == nullptr) {
+ return std::nullopt;
}
- if (!ED_object_add_generic_get_opts(
- C, op, 'Z', loc, rot, nullptr, nullptr, &local_view_bits, nullptr)) {
- return OPERATOR_CANCELLED;
+ if (!ED_object_add_generic_get_opts(C,
+ op,
+ 'Z',
+ add_info.loc,
+ add_info.rot,
+ nullptr,
+ nullptr,
+ &add_info.local_view_bits,
+ nullptr)) {
+ return std::nullopt;
}
ViewLayer *view_layer = CTX_data_view_layer(C);
/* Avoid dependency cycles. */
LayerCollection *active_lc = BKE_layer_collection_get_active(view_layer);
- while (BKE_collection_cycle_find(active_lc->collection, collection)) {
+ while (BKE_collection_cycle_find(active_lc->collection, add_info.collection)) {
active_lc = BKE_layer_collection_activate_parent(view_layer, active_lc);
}
- Object *ob = ED_object_add_type(
- C, OB_EMPTY, collection->id.name + 2, loc, rot, false, local_view_bits);
- ob->instance_collection = collection;
+ return add_info;
+}
+
+static int collection_instance_add_exec(bContext *C, wmOperator *op)
+{
+ std::optional<CollectionAddInfo> add_info = collection_add_info_get_from_op(C, op);
+ if (!add_info) {
+ return OPERATOR_CANCELLED;
+ }
+
+ Object *ob = ED_object_add_type(C,
+ OB_EMPTY,
+ add_info->collection->id.name + 2,
+ add_info->loc,
+ add_info->rot,
+ false,
+ add_info->local_view_bits);
+ ob->instance_collection = add_info->collection;
ob->empty_drawsize = U.collection_instance_empty_size;
ob->transflag |= OB_DUPLICOLLECTION;
- id_us_plus(&collection->id);
+ id_us_plus(&add_info->collection->id);
return OPERATOR_FINISHED;
}
@@ -1750,6 +1785,128 @@ void OBJECT_OT_collection_instance_add(wmOperatorType *ot)
/** \} */
/* -------------------------------------------------------------------- */
+/** \name Collection Drop Operator
+ *
+ * Internal operator for collection dropping.
+ *
+ * \warning This is tied closely together to the drop-box callbacks, so it shouldn't be used on its
+ * own.
+ *
+ * The drop-box callback imports the collection, links it into the view-layer, selects all imported
+ * objects (which may include peripheral objects like parents or boolean-objects of an object in
+ * the collection) and activates one. Only the callback has enough info to do this reliably. Based
+ * on the instancing operator option, this operator then does one of two things:
+ * - Instancing enabled: Unlink the collection again, and instead add a collection instance empty
+ * at the drop position.
+ * - Instancing disabled: Transform the objects to the drop position, keeping all relative
+ * transforms of the objects to each other as is.
+ *
+ * \{ */
+
+static int collection_drop_exec(bContext *C, wmOperator *op)
+{
+ Main *bmain = CTX_data_main(C);
+ LayerCollection *active_collection = CTX_data_layer_collection(C);
+ std::optional<CollectionAddInfo> add_info = collection_add_info_get_from_op(C, op);
+ if (!add_info) {
+ return OPERATOR_CANCELLED;
+ }
+
+ if (RNA_boolean_get(op->ptr, "use_instance")) {
+ BKE_collection_child_remove(bmain, active_collection->collection, add_info->collection);
+ DEG_id_tag_update(&active_collection->collection->id, ID_RECALC_COPY_ON_WRITE);
+ DEG_relations_tag_update(bmain);
+
+ Object *ob = ED_object_add_type(C,
+ OB_EMPTY,
+ add_info->collection->id.name + 2,
+ add_info->loc,
+ add_info->rot,
+ false,
+ add_info->local_view_bits);
+ ob->instance_collection = add_info->collection;
+ ob->empty_drawsize = U.collection_instance_empty_size;
+ ob->transflag |= OB_DUPLICOLLECTION;
+ id_us_plus(&add_info->collection->id);
+ }
+ else {
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ float delta_mat[4][4];
+ unit_m4(delta_mat);
+
+ const float scale[3] = {1.0f, 1.0f, 1.0f};
+ loc_eul_size_to_mat4(delta_mat, add_info->loc, add_info->rot, scale);
+
+ float offset[3];
+ /* Reverse apply the instance offset, so toggling the Instance option doesn't cause the
+ * collection to jump. */
+ negate_v3_v3(offset, add_info->collection->instance_offset);
+ translate_m4(delta_mat, UNPACK3(offset));
+
+ ObjectsInViewLayerParams params = {0};
+ uint objects_len;
+ Object **objects = BKE_view_layer_array_selected_objects_params(
+ view_layer, nullptr, &objects_len, &params);
+ ED_object_xform_array_m4(objects, objects_len, delta_mat);
+
+ MEM_freeN(objects);
+ }
+
+ return OPERATOR_FINISHED;
+}
+
+void OBJECT_OT_collection_external_asset_drop(wmOperatorType *ot)
+{
+ PropertyRNA *prop;
+
+ /* identifiers */
+ /* Name should only be displayed in the drag tooltip. */
+ ot->name = "Add Collection";
+ ot->description = "Add the dragged collection to the scene";
+ ot->idname = "OBJECT_OT_collection_external_asset_drop";
+
+ /* api callbacks */
+ ot->invoke = object_instance_add_invoke;
+ ot->exec = collection_drop_exec;
+ ot->poll = ED_operator_objectmode;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
+
+ /* properties */
+ prop = RNA_def_int(ot->srna,
+ "session_uuid",
+ 0,
+ INT32_MIN,
+ INT32_MAX,
+ "Session UUID",
+ "Session UUID of the collection to add",
+ INT32_MIN,
+ INT32_MAX);
+ RNA_def_property_flag(prop, (PropertyFlag)(PROP_SKIP_SAVE | PROP_HIDDEN));
+
+ ED_object_add_generic_props(ot, false);
+
+ /* Important: Instancing option. Intentionally remembered across executions (no #PROP_SKIP_SAVE).
+ */
+ RNA_def_boolean(ot->srna,
+ "use_instance",
+ true,
+ "Instance",
+ "Add the dropped collection as collection instance");
+
+ object_add_drop_xy_props(ot);
+
+ prop = RNA_def_enum(ot->srna, "collection", DummyRNA_NULL_items, 0, "Collection", "");
+ RNA_def_enum_funcs(prop, RNA_collection_itemf);
+ RNA_def_property_flag(prop,
+ (PropertyFlag)(PROP_SKIP_SAVE | PROP_HIDDEN | PROP_ENUM_NO_TRANSLATE));
+ ot->prop = prop;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
/** \name Add Data Instance Operator
*
* Use for dropping ID's from the outliner.
@@ -2752,12 +2909,14 @@ static int object_convert_exec(bContext *C, wmOperator *op)
* However, changing this is more design than bug-fix, not to mention convoluted code below,
* so that will be for later.
* But at the very least, do not do that with linked IDs! */
- if ((ID_IS_LINKED(ob) || (ob->data && ID_IS_LINKED(ob->data))) && !keep_original) {
+ if ((!BKE_id_is_editable(bmain, &ob->id) ||
+ (ob->data && !BKE_id_is_editable(bmain, static_cast<ID *>(ob->data)))) &&
+ !keep_original) {
keep_original = true;
- BKE_report(
- op->reports,
- RPT_INFO,
- "Converting some linked object/object data, enforcing 'Keep Original' option to True");
+ BKE_report(op->reports,
+ RPT_INFO,
+ "Converting some non-editable object/object data, enforcing 'Keep Original' "
+ "option to True");
}
DEG_id_tag_update(&base->object->id, ID_RECALC_GEOMETRY);
@@ -3631,7 +3790,7 @@ static int object_transform_to_mouse_exec(bContext *C, wmOperator *op)
/* Don't transform a linked object. There's just nothing to do here in this case, so return
* #OPERATOR_FINISHED. */
- if (ID_IS_LINKED(ob)) {
+ if (!BKE_id_is_editable(bmain, &ob->id)) {
return OPERATOR_FINISHED;
}
diff --git a/source/blender/editors/object/object_bake.c b/source/blender/editors/object/object_bake.c
index dbb6916dfce..d93edd2776b 100644
--- a/source/blender/editors/object/object_bake.c
+++ b/source/blender/editors/object/object_bake.c
@@ -515,7 +515,7 @@ static void multiresbake_freejob(void *bkv)
/* delete here, since this delete will be called from main thread */
for (link = data->images.first; link; link = link->next) {
Image *ima = (Image *)link->data;
- BKE_image_free_gputextures(ima);
+ BKE_image_partial_update_mark_full_update(ima);
}
MEM_freeN(data->ob_image.array);
diff --git a/source/blender/editors/object/object_bake_api.c b/source/blender/editors/object/object_bake_api.c
index efcb47f76ab..44f05600d7d 100644
--- a/source/blender/editors/object/object_bake_api.c
+++ b/source/blender/editors/object/object_bake_api.c
@@ -180,7 +180,7 @@ static bool write_internal_bake_pixels(Image *image,
void *lock;
bool is_float;
char *mask_buffer = NULL;
- const size_t num_pixels = (size_t)width * (size_t)height;
+ const size_t pixels_num = (size_t)width * (size_t)height;
ibuf = BKE_image_acquire_ibuf(image, NULL, &lock);
@@ -189,8 +189,8 @@ static bool write_internal_bake_pixels(Image *image,
}
if (margin > 0 || !is_clear) {
- mask_buffer = MEM_callocN(sizeof(char) * num_pixels, "Bake Mask");
- RE_bake_mask_fill(pixel_array, num_pixels, mask_buffer);
+ mask_buffer = MEM_callocN(sizeof(char) * pixels_num, "Bake Mask");
+ RE_bake_mask_fill(pixel_array, pixels_num, mask_buffer);
}
is_float = (ibuf->rect_float != NULL);
@@ -298,7 +298,7 @@ static bool write_internal_bake_pixels(Image *image,
/* force OpenGL reload */
static void bake_targets_refresh(BakeTargets *targets)
{
- for (int i = 0; i < targets->num_images; i++) {
+ for (int i = 0; i < targets->images_num; i++) {
Image *ima = targets->images[i].image;
if (ima) {
@@ -374,10 +374,10 @@ static bool write_external_bake_pixels(const char *filepath,
/* margins */
if (margin > 0) {
char *mask_buffer = NULL;
- const size_t num_pixels = (size_t)width * (size_t)height;
+ const size_t pixels_num = (size_t)width * (size_t)height;
- mask_buffer = MEM_callocN(sizeof(char) * num_pixels, "Bake Mask");
- RE_bake_mask_fill(pixel_array, num_pixels, mask_buffer);
+ mask_buffer = MEM_callocN(sizeof(char) * pixels_num, "Bake Mask");
+ RE_bake_mask_fill(pixel_array, pixels_num, mask_buffer);
RE_bake_margin(ibuf, mask_buffer, margin, margin_type, mesh_eval, uv_layer);
if (mask_buffer) {
@@ -670,9 +670,9 @@ static bool bake_targets_init_image_textures(const BakeAPIRender *bkr,
Object *ob,
ReportList *reports)
{
- int num_materials = ob->totcol;
+ int materials_num = ob->totcol;
- if (num_materials == 0) {
+ if (materials_num == 0) {
if (bkr->save_mode == R_BAKE_SAVE_INTERNAL) {
BKE_report(
reports, RPT_ERROR, "No active image found, add a material or bake to an external file");
@@ -688,15 +688,15 @@ static bool bake_targets_init_image_textures(const BakeAPIRender *bkr,
}
/* Over-allocate in case there is more materials than images. */
- targets->num_materials = num_materials;
- targets->images = MEM_callocN(sizeof(BakeImage) * targets->num_materials, "BakeTargets.images");
- targets->material_to_image = MEM_callocN(sizeof(int) * targets->num_materials,
+ targets->materials_num = materials_num;
+ targets->images = MEM_callocN(sizeof(BakeImage) * targets->materials_num, "BakeTargets.images");
+ targets->material_to_image = MEM_callocN(sizeof(int) * targets->materials_num,
"BakeTargets.material_to_image");
/* Error handling and tag (in case multiple materials share the same image). */
BKE_main_id_tag_idcode(bkr->main, ID_IM, LIB_TAG_DOIT, false);
- for (int i = 0; i < num_materials; i++) {
+ for (int i = 0; i < materials_num; i++) {
Image *image;
ED_object_get_active_image(ob, i + 1, &image, NULL, NULL, NULL);
@@ -713,10 +713,10 @@ static bool bake_targets_init_image_textures(const BakeAPIRender *bkr,
}
}
else {
- targets->material_to_image[i] = targets->num_images;
- targets->images[targets->num_images].image = image;
+ targets->material_to_image[i] = targets->images_num;
+ targets->images[targets->images_num].image = image;
image->id.tag |= LIB_TAG_DOIT;
- targets->num_images++;
+ targets->images_num++;
}
}
@@ -733,7 +733,7 @@ static bool bake_targets_init_internal(const BakeAPIRender *bkr,
}
/* Saving to image datablocks. */
- for (int i = 0; i < targets->num_images; i++) {
+ for (int i = 0; i < targets->images_num; i++) {
BakeImage *bk_image = &targets->images[i];
void *lock;
ImBuf *ibuf = BKE_image_acquire_ibuf(bk_image->image, NULL, &lock);
@@ -741,9 +741,9 @@ static bool bake_targets_init_internal(const BakeAPIRender *bkr,
if (ibuf) {
bk_image->width = ibuf->x;
bk_image->height = ibuf->y;
- bk_image->offset = targets->num_pixels;
+ bk_image->offset = targets->pixels_num;
- targets->num_pixels += (size_t)ibuf->x * (size_t)ibuf->y;
+ targets->pixels_num += (size_t)ibuf->x * (size_t)ibuf->y;
}
else {
BKE_image_release_ibuf(bk_image->image, ibuf, lock);
@@ -765,12 +765,12 @@ static bool bake_targets_output_internal(const BakeAPIRender *bkr,
{
bool all_ok = true;
- for (int i = 0; i < targets->num_images; i++) {
+ for (int i = 0; i < targets->images_num; i++) {
BakeImage *bk_image = &targets->images[i];
const bool ok = write_internal_bake_pixels(bk_image->image,
pixel_array + bk_image->offset,
targets->result +
- bk_image->offset * targets->num_channels,
+ bk_image->offset * targets->channels_num,
bk_image->width,
bk_image->height,
bkr->margin,
@@ -809,15 +809,15 @@ static bool bake_targets_init_external(const BakeAPIRender *bkr,
}
/* Saving to disk. */
- for (int i = 0; i < targets->num_images; i++) {
+ for (int i = 0; i < targets->images_num; i++) {
BakeImage *bk_image = &targets->images[i];
bk_image->width = bkr->width;
bk_image->height = bkr->height;
- bk_image->offset = targets->num_pixels;
+ bk_image->offset = targets->pixels_num;
bk_image->image = NULL;
- targets->num_pixels += (size_t)bkr->width * (size_t)bkr->height;
+ targets->pixels_num += (size_t)bkr->width * (size_t)bkr->height;
if (!bkr->is_split_materials) {
break;
@@ -826,7 +826,7 @@ static bool bake_targets_init_external(const BakeAPIRender *bkr,
if (!bkr->is_split_materials) {
/* saving a single image */
- for (int i = 0; i < targets->num_materials; i++) {
+ for (int i = 0; i < targets->materials_num; i++) {
targets->material_to_image[i] = 0;
}
}
@@ -844,7 +844,7 @@ static bool bake_targets_output_external(const BakeAPIRender *bkr,
{
bool all_ok = true;
- for (int i = 0; i < targets->num_images; i++) {
+ for (int i = 0; i < targets->images_num; i++) {
BakeImage *bk_image = &targets->images[i];
BakeData *bake = &bkr->scene->r.bake;
@@ -888,7 +888,7 @@ static bool bake_targets_output_external(const BakeAPIRender *bkr,
const bool ok = write_external_bake_pixels(name,
pixel_array + bk_image->offset,
targets->result +
- bk_image->offset * targets->num_channels,
+ bk_image->offset * targets->channels_num,
bk_image->width,
bk_image->height,
bkr->margin,
@@ -934,11 +934,11 @@ static bool bake_targets_init_vertex_colors(BakeTargets *targets, Object *ob, Re
}
targets->images = MEM_callocN(sizeof(BakeImage), "BakeTargets.images");
- targets->num_images = 1;
+ targets->images_num = 1;
targets->material_to_image = MEM_callocN(sizeof(int) * ob->totcol,
"BakeTargets.material_to_image");
- targets->num_materials = ob->totcol;
+ targets->materials_num = ob->totcol;
BakeImage *bk_image = &targets->images[0];
bk_image->width = me->totloop;
@@ -946,7 +946,7 @@ static bool bake_targets_init_vertex_colors(BakeTargets *targets, Object *ob, Re
bk_image->offset = 0;
bk_image->image = NULL;
- targets->num_pixels = bk_image->width * bk_image->height;
+ targets->pixels_num = bk_image->width * bk_image->height;
return true;
}
@@ -984,10 +984,10 @@ static void bake_targets_populate_pixels_vertex_colors(BakeTargets *targets,
BakePixel *pixel_array)
{
Mesh *me = ob->data;
- const int num_pixels = targets->num_pixels;
+ const int pixels_num = targets->pixels_num;
/* Initialize blank pixels. */
- for (int i = 0; i < num_pixels; i++) {
+ for (int i = 0; i < pixels_num; i++) {
BakePixel *pixel = &pixel_array[i];
pixel->primitive_id = -1;
@@ -1059,12 +1059,12 @@ static void bake_targets_populate_pixels_vertex_colors(BakeTargets *targets,
MEM_freeN(looptri);
}
-static void bake_result_add_to_rgba(float rgba[4], const float *result, const int num_channels)
+static void bake_result_add_to_rgba(float rgba[4], const float *result, const int channels_num)
{
- if (num_channels == 4) {
+ if (channels_num == 4) {
add_v4_v4(rgba, result);
}
- else if (num_channels == 3) {
+ else if (channels_num == 3) {
add_v3_v3(rgba, result);
rgba[3] += 1.0f;
}
@@ -1082,7 +1082,7 @@ static bool bake_targets_output_vertex_colors(BakeTargets *targets, Object *ob)
MPropCol *mcol = CustomData_get_layer(&me->vdata, CD_PROP_COLOR);
const bool mcol_valid = (mcol != NULL && U.experimental.use_sculpt_vertex_colors);
MLoopCol *mloopcol = CustomData_get_layer(&me->ldata, CD_MLOOPCOL);
- const int num_channels = targets->num_channels;
+ const int channels_num = targets->channels_num;
const float *result = targets->result;
if (mcol_valid) {
@@ -1096,7 +1096,7 @@ static bool bake_targets_output_vertex_colors(BakeTargets *targets, Object *ob)
MLoop *mloop = me->mloop;
for (int i = 0; i < totloop; i++, mloop++) {
const int v = mloop->v;
- bake_result_add_to_rgba(mcol[v].color, &result[i * num_channels], num_channels);
+ bake_result_add_to_rgba(mcol[v].color, &result[i * channels_num], channels_num);
num_loops_for_vertex[v]++;
}
@@ -1118,7 +1118,7 @@ static bool bake_targets_output_vertex_colors(BakeTargets *targets, Object *ob)
for (int i = 0; i < totloop; i++, mloop++, mloopcol++) {
float rgba[4];
zero_v4(rgba);
- bake_result_add_to_rgba(rgba, &result[i * num_channels], num_channels);
+ bake_result_add_to_rgba(rgba, &result[i * channels_num], channels_num);
if (is_noncolor) {
unit_float_to_uchar_clamp_v4(&mloopcol->r, rgba);
@@ -1160,13 +1160,13 @@ static bool bake_targets_init(const BakeAPIRender *bkr,
}
}
- if (targets->num_pixels == 0) {
+ if (targets->pixels_num == 0) {
return false;
}
targets->is_noncolor = is_noncolor_pass(bkr->pass_type);
- targets->num_channels = RE_pass_depth(bkr->pass_type);
- targets->result = MEM_callocN(sizeof(float) * targets->num_channels * targets->num_pixels,
+ targets->channels_num = RE_pass_depth(bkr->pass_type);
+ targets->result = MEM_callocN(sizeof(float) * targets->channels_num * targets->pixels_num,
"bake return pixels");
return true;
@@ -1182,7 +1182,7 @@ static void bake_targets_populate_pixels(const BakeAPIRender *bkr,
bake_targets_populate_pixels_vertex_colors(targets, ob, me_eval, pixel_array);
}
else {
- RE_bake_pixels_populate(me_eval, pixel_array, targets->num_pixels, targets, bkr->uv_layer);
+ RE_bake_pixels_populate(me_eval, pixel_array, targets->pixels_num, targets, bkr->uv_layer);
}
}
@@ -1329,7 +1329,7 @@ static int bake(const BakeAPIRender *bkr,
/* Populate the pixel array with the face data. Except if we use a cage, then
* it is populated later with the cage mesh (smoothed version of the mesh). */
- pixel_array_low = MEM_mallocN(sizeof(BakePixel) * targets.num_pixels, "bake pixels low poly");
+ pixel_array_low = MEM_mallocN(sizeof(BakePixel) * targets.pixels_num, "bake pixels low poly");
if ((bkr->is_selected_to_active && (ob_cage == NULL) && bkr->is_cage) == false) {
bake_targets_populate_pixels(bkr, &targets, ob_low, me_low_eval, pixel_array_low);
}
@@ -1422,7 +1422,7 @@ static int bake(const BakeAPIRender *bkr,
ob_low_eval->base_flag &= ~(BASE_VISIBLE_DEPSGRAPH | BASE_ENABLED_RENDER);
/* populate the pixel arrays with the corresponding face data for each high poly object */
- pixel_array_high = MEM_mallocN(sizeof(BakePixel) * targets.num_pixels,
+ pixel_array_high = MEM_mallocN(sizeof(BakePixel) * targets.pixels_num,
"bake pixels high poly");
if (!RE_bake_pixels_populate_from_objects(me_low_eval,
@@ -1430,7 +1430,7 @@ static int bake(const BakeAPIRender *bkr,
pixel_array_high,
highpoly,
tot_highpoly,
- targets.num_pixels,
+ targets.pixels_num,
ob_cage != NULL,
bkr->cage_extrusion,
bkr->max_ray_distance,
@@ -1491,16 +1491,16 @@ static int bake(const BakeAPIRender *bkr,
break;
}
RE_bake_normal_world_to_world(pixel_array_low,
- targets.num_pixels,
- targets.num_channels,
+ targets.pixels_num,
+ targets.channels_num,
targets.result,
bkr->normal_swizzle);
break;
}
case R_BAKE_SPACE_OBJECT: {
RE_bake_normal_world_to_object(pixel_array_low,
- targets.num_pixels,
- targets.num_channels,
+ targets.pixels_num,
+ targets.channels_num,
targets.result,
ob_low_eval,
bkr->normal_swizzle);
@@ -1509,8 +1509,8 @@ static int bake(const BakeAPIRender *bkr,
case R_BAKE_SPACE_TANGENT: {
if (bkr->is_selected_to_active) {
RE_bake_normal_world_to_tangent(pixel_array_low,
- targets.num_pixels,
- targets.num_channels,
+ targets.pixels_num,
+ targets.channels_num,
targets.result,
me_low_eval,
bkr->normal_swizzle,
@@ -1535,8 +1535,8 @@ static int bake(const BakeAPIRender *bkr,
}
RE_bake_normal_world_to_tangent(pixel_array_low,
- targets.num_pixels,
- targets.num_channels,
+ targets.pixels_num,
+ targets.channels_num,
targets.result,
(me_nores) ? me_nores : me_low_eval,
bkr->normal_swizzle,
diff --git a/source/blender/editors/object/object_data_transfer.c b/source/blender/editors/object/object_data_transfer.c
index 3abf0d68eb3..6805c9144d6 100644
--- a/source/blender/editors/object/object_data_transfer.c
+++ b/source/blender/editors/object/object_data_transfer.c
@@ -319,11 +319,11 @@ static void data_transfer_exec_preprocess_objects(bContext *C,
}
me = ob->data;
- if (ID_IS_LINKED(me)) {
- /* Do not transfer to linked data, not supported. */
+ if (ID_IS_LINKED(me) || ID_IS_OVERRIDE_LIBRARY(me)) {
+ /* Do not transfer to linked/override data, not supported. */
BKE_reportf(op->reports,
RPT_WARNING,
- "Skipping object '%s', linked data '%s' cannot be modified",
+ "Skipping object '%s', linked or override data '%s' cannot be modified",
ob->id.name + 2,
me->id.name + 2);
me->id.tag &= ~LIB_TAG_DOIT;
diff --git a/source/blender/editors/object/object_edit.c b/source/blender/editors/object/object_edit.c
index 7cef3e1725b..cc8644285c0 100644
--- a/source/blender/editors/object/object_edit.c
+++ b/source/blender/editors/object/object_edit.c
@@ -51,6 +51,7 @@
#include "BKE_image.h"
#include "BKE_lattice.h"
#include "BKE_layer.h"
+#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_material.h"
#include "BKE_mball.h"
@@ -973,7 +974,7 @@ static int posemode_exec(bContext *C, wmOperator *op)
const View3D *v3d = CTX_wm_view3d(C);
FOREACH_SELECTED_OBJECT_BEGIN (view_layer, v3d, ob) {
if ((ob != obact) && (ob->type == OB_ARMATURE) && (ob->mode == OB_MODE_OBJECT) &&
- (!ID_IS_LINKED(ob))) {
+ BKE_id_is_editable(bmain, &ob->id)) {
ED_object_posemode_enter_ex(bmain, ob);
}
}
@@ -1528,6 +1529,7 @@ static int shade_smooth_exec(bContext *C, wmOperator *op)
}
}
+ Main *bmain = CTX_data_main(C);
LISTBASE_FOREACH (CollectionPointerLink *, ctx_ob, &ctx_objects) {
/* Always un-tag all object data-blocks irrespective of our ability to operate on them. */
Object *ob = ctx_ob->ptr.data;
@@ -1538,7 +1540,7 @@ static int shade_smooth_exec(bContext *C, wmOperator *op)
data->tag &= ~LIB_TAG_DOIT;
/* Finished un-tagging, continue with regular logic. */
- if (data && ID_IS_LINKED(data)) {
+ if (data && !BKE_id_is_editable(bmain, data)) {
has_linked_data = true;
continue;
}
diff --git a/source/blender/editors/object/object_gpencil_modifier.c b/source/blender/editors/object/object_gpencil_modifier.c
index d0a6a5d44c0..573f048e6b6 100644
--- a/source/blender/editors/object/object_gpencil_modifier.c
+++ b/source/blender/editors/object/object_gpencil_modifier.c
@@ -26,6 +26,7 @@
#include "BKE_context.h"
#include "BKE_gpencil.h"
#include "BKE_gpencil_modifier.h"
+#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_object.h"
#include "BKE_report.h"
@@ -418,17 +419,18 @@ static bool gpencil_edit_modifier_poll_generic(bContext *C,
int obtype_flag,
const bool is_liboverride_allowed)
{
+ Main *bmain = CTX_data_main(C);
PointerRNA ptr = CTX_data_pointer_get_type(C, "modifier", rna_type);
Object *ob = (ptr.owner_id) ? (Object *)ptr.owner_id : ED_object_active_context(C);
GpencilModifierData *mod = ptr.data; /* May be NULL. */
- if (!ob || ID_IS_LINKED(ob)) {
+ if (!ob || !BKE_id_is_editable(bmain, &ob->id)) {
return false;
}
if (obtype_flag && ((1 << ob->type) & obtype_flag) == 0) {
return false;
}
- if (ptr.owner_id && ID_IS_LINKED(ptr.owner_id)) {
+ if (ptr.owner_id && !BKE_id_is_editable(bmain, ptr.owner_id)) {
return false;
}
diff --git a/source/blender/editors/object/object_hook.c b/source/blender/editors/object/object_hook.c
index e8637b57724..b3f62f3fc0f 100644
--- a/source/blender/editors/object/object_hook.c
+++ b/source/blender/editors/object/object_hook.c
@@ -54,23 +54,26 @@
#include "object_intern.h"
-static int return_editmesh_indexar(BMEditMesh *em, int *r_tot, int **r_indexar, float r_cent[3])
+static int return_editmesh_indexar(BMEditMesh *em,
+ int *r_indexar_num,
+ int **r_indexar,
+ float r_cent[3])
{
BMVert *eve;
BMIter iter;
- int *index, nr, totvert = 0;
+ int *index, nr, indexar_num = 0;
BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
if (BM_elem_flag_test(eve, BM_ELEM_SELECT)) {
- totvert++;
+ indexar_num++;
}
}
- if (totvert == 0) {
+ if (indexar_num == 0) {
return 0;
}
- *r_indexar = index = MEM_mallocN(4 * totvert, "hook indexar");
- *r_tot = totvert;
+ *r_indexar = index = MEM_mallocN(4 * indexar_num, "hook indexar");
+ *r_indexar_num = indexar_num;
nr = 0;
zero_v3(r_cent);
@@ -83,9 +86,9 @@ static int return_editmesh_indexar(BMEditMesh *em, int *r_tot, int **r_indexar,
nr++;
}
- mul_v3_fl(r_cent, 1.0f / (float)totvert);
+ mul_v3_fl(r_cent, 1.0f / (float)indexar_num);
- return totvert;
+ return indexar_num;
}
static bool return_editmesh_vgroup(Object *obedit, BMEditMesh *em, char *r_name, float r_cent[3])
@@ -97,7 +100,7 @@ static bool return_editmesh_vgroup(Object *obedit, BMEditMesh *em, char *r_name,
if (cd_dvert_offset != -1) {
const int defgrp_index = active_index - 1;
- int totvert = 0;
+ int indexar_num = 0;
MDeformVert *dvert;
BMVert *eve;
@@ -109,14 +112,14 @@ static bool return_editmesh_vgroup(Object *obedit, BMEditMesh *em, char *r_name,
if (BKE_defvert_find_weight(dvert, defgrp_index) > 0.0f) {
add_v3_v3(r_cent, eve->co);
- totvert++;
+ indexar_num++;
}
}
- if (totvert) {
+ if (indexar_num) {
const ListBase *defbase = BKE_object_defgroup_list(obedit);
bDeformGroup *dg = BLI_findlink(defbase, defgrp_index);
BLI_strncpy(r_name, dg->name, sizeof(dg->name));
- mul_v3_fl(r_cent, 1.0f / (float)totvert);
+ mul_v3_fl(r_cent, 1.0f / (float)indexar_num);
return true;
}
}
@@ -139,7 +142,7 @@ static void select_editbmesh_hook(Object *ob, HookModifierData *hmd)
BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
if (nr == hmd->indexar[index]) {
BM_vert_select_set(em->bm, eve, true);
- if (index < hmd->totindex - 1) {
+ if (index < hmd->indexar_num - 1) {
index++;
}
}
@@ -151,12 +154,12 @@ static void select_editbmesh_hook(Object *ob, HookModifierData *hmd)
}
static int return_editlattice_indexar(Lattice *editlatt,
- int *r_tot,
int **r_indexar,
+ int *r_indexar_num,
float r_cent[3])
{
BPoint *bp;
- int *index, nr, totvert = 0, a;
+ int *index, nr, indexar_num = 0, a;
/* count */
a = editlatt->pntsu * editlatt->pntsv * editlatt->pntsw;
@@ -164,18 +167,18 @@ static int return_editlattice_indexar(Lattice *editlatt,
while (a--) {
if (bp->f1 & SELECT) {
if (bp->hide == 0) {
- totvert++;
+ indexar_num++;
}
}
bp++;
}
- if (totvert == 0) {
+ if (indexar_num == 0) {
return 0;
}
- *r_indexar = index = MEM_mallocN(4 * totvert, "hook indexar");
- *r_tot = totvert;
+ *r_indexar = index = MEM_mallocN(4 * indexar_num, "hook indexar");
+ *r_indexar_num = indexar_num;
nr = 0;
zero_v3(r_cent);
@@ -193,9 +196,9 @@ static int return_editlattice_indexar(Lattice *editlatt,
nr++;
}
- mul_v3_fl(r_cent, 1.0f / (float)totvert);
+ mul_v3_fl(r_cent, 1.0f / (float)indexar_num);
- return totvert;
+ return indexar_num;
}
static void select_editlattice_hook(Object *obedit, HookModifierData *hmd)
@@ -211,7 +214,7 @@ static void select_editlattice_hook(Object *obedit, HookModifierData *hmd)
while (a--) {
if (hmd->indexar[index] == nr) {
bp->f1 |= SELECT;
- if (index < hmd->totindex - 1) {
+ if (index < hmd->indexar_num - 1) {
index++;
}
}
@@ -220,12 +223,15 @@ static void select_editlattice_hook(Object *obedit, HookModifierData *hmd)
}
}
-static int return_editcurve_indexar(Object *obedit, int *r_tot, int **r_indexar, float r_cent[3])
+static int return_editcurve_indexar(Object *obedit,
+ int **r_indexar,
+ int *r_indexar_num,
+ float r_cent[3])
{
ListBase *editnurb = object_editcurve_get(obedit);
BPoint *bp;
BezTriple *bezt;
- int *index, a, nr, totvert = 0;
+ int *index, a, nr, indexar_num = 0;
LISTBASE_FOREACH (Nurb *, nu, editnurb) {
if (nu->type == CU_BEZIER) {
@@ -233,13 +239,13 @@ static int return_editcurve_indexar(Object *obedit, int *r_tot, int **r_indexar,
a = nu->pntsu;
while (a--) {
if (bezt->f1 & SELECT) {
- totvert++;
+ indexar_num++;
}
if (bezt->f2 & SELECT) {
- totvert++;
+ indexar_num++;
}
if (bezt->f3 & SELECT) {
- totvert++;
+ indexar_num++;
}
bezt++;
}
@@ -249,18 +255,18 @@ static int return_editcurve_indexar(Object *obedit, int *r_tot, int **r_indexar,
a = nu->pntsu * nu->pntsv;
while (a--) {
if (bp->f1 & SELECT) {
- totvert++;
+ indexar_num++;
}
bp++;
}
}
}
- if (totvert == 0) {
+ if (indexar_num == 0) {
return 0;
}
- *r_indexar = index = MEM_mallocN(sizeof(*index) * totvert, "hook indexar");
- *r_tot = totvert;
+ *r_indexar = index = MEM_mallocN(sizeof(*index) * indexar_num, "hook indexar");
+ *r_indexar_num = indexar_num;
nr = 0;
zero_v3(r_cent);
@@ -305,21 +311,21 @@ static int return_editcurve_indexar(Object *obedit, int *r_tot, int **r_indexar,
}
}
- mul_v3_fl(r_cent, 1.0f / (float)totvert);
+ mul_v3_fl(r_cent, 1.0f / (float)indexar_num);
- return totvert;
+ return indexar_num;
}
static bool object_hook_index_array(Main *bmain,
Scene *scene,
Object *obedit,
- int *r_tot,
int **r_indexar,
+ int *r_indexar_num,
char *r_name,
float r_cent[3])
{
*r_indexar = NULL;
- *r_tot = 0;
+ *r_indexar_num = 0;
r_name[0] = 0;
switch (obedit->type) {
@@ -338,7 +344,7 @@ static bool object_hook_index_array(Main *bmain,
BKE_editmesh_looptri_and_normals_calc(em);
/* check selected vertices first */
- if (return_editmesh_indexar(em, r_tot, r_indexar, r_cent) == 0) {
+ if (return_editmesh_indexar(em, r_indexar_num, r_indexar, r_cent) == 0) {
return return_editmesh_vgroup(obedit, em, r_name, r_cent);
}
return true;
@@ -347,10 +353,10 @@ static bool object_hook_index_array(Main *bmain,
case OB_SURF:
ED_curve_editnurb_load(bmain, obedit);
ED_curve_editnurb_make(obedit);
- return return_editcurve_indexar(obedit, r_tot, r_indexar, r_cent);
+ return return_editcurve_indexar(obedit, r_indexar, r_indexar_num, r_cent);
case OB_LATTICE: {
Lattice *lt = obedit->data;
- return return_editlattice_indexar(lt->editlatt->latt, r_tot, r_indexar, r_cent);
+ return return_editlattice_indexar(lt->editlatt->latt, r_indexar, r_indexar_num, r_cent);
}
default:
return false;
@@ -371,21 +377,21 @@ static void select_editcurve_hook(Object *obedit, HookModifierData *hmd)
while (a--) {
if (nr == hmd->indexar[index]) {
bezt->f1 |= SELECT;
- if (index < hmd->totindex - 1) {
+ if (index < hmd->indexar_num - 1) {
index++;
}
}
nr++;
if (nr == hmd->indexar[index]) {
bezt->f2 |= SELECT;
- if (index < hmd->totindex - 1) {
+ if (index < hmd->indexar_num - 1) {
index++;
}
}
nr++;
if (nr == hmd->indexar[index]) {
bezt->f3 |= SELECT;
- if (index < hmd->totindex - 1) {
+ if (index < hmd->indexar_num - 1) {
index++;
}
}
@@ -400,7 +406,7 @@ static void select_editcurve_hook(Object *obedit, HookModifierData *hmd)
while (a--) {
if (nr == hmd->indexar[index]) {
bp->f1 |= SELECT;
- if (index < hmd->totindex - 1) {
+ if (index < hmd->indexar_num - 1) {
index++;
}
}
@@ -514,10 +520,10 @@ static int add_hook_object(const bContext *C,
HookModifierData *hmd = NULL;
float cent[3];
float pose_mat[4][4];
- int tot, ok, *indexar;
+ int indexar_num, ok, *indexar;
char name[MAX_NAME];
- ok = object_hook_index_array(bmain, scene, obedit, &tot, &indexar, name, cent);
+ ok = object_hook_index_array(bmain, scene, obedit, &indexar, &indexar_num, name, cent);
if (!ok) {
BKE_report(reports, RPT_ERROR, "Requires selected vertices or active vertex group");
@@ -545,7 +551,7 @@ static int add_hook_object(const bContext *C,
hmd->object = ob;
hmd->indexar = indexar;
copy_v3_v3(hmd->cent, cent);
- hmd->totindex = tot;
+ hmd->indexar_num = indexar_num;
BLI_strncpy(hmd->name, name, sizeof(hmd->name));
unit_m4(pose_mat);
@@ -873,7 +879,7 @@ static int object_hook_assign_exec(bContext *C, wmOperator *op)
HookModifierData *hmd = NULL;
float cent[3];
char name[MAX_NAME];
- int *indexar, tot;
+ int *indexar, indexar_num;
object_hook_from_context(C, &ptr, num, &ob, &hmd);
if (hmd == NULL) {
@@ -883,7 +889,7 @@ static int object_hook_assign_exec(bContext *C, wmOperator *op)
/* assign functionality */
- if (!object_hook_index_array(bmain, scene, ob, &tot, &indexar, name, cent)) {
+ if (!object_hook_index_array(bmain, scene, ob, &indexar, &indexar_num, name, cent)) {
BKE_report(op->reports, RPT_WARNING, "Requires selected vertices or active vertex group");
return OPERATOR_CANCELLED;
}
@@ -893,7 +899,7 @@ static int object_hook_assign_exec(bContext *C, wmOperator *op)
copy_v3_v3(hmd->cent, cent);
hmd->indexar = indexar;
- hmd->totindex = tot;
+ hmd->indexar_num = indexar_num;
DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
diff --git a/source/blender/editors/object/object_intern.h b/source/blender/editors/object/object_intern.h
index 490c495dad5..cb703caa8d1 100644
--- a/source/blender/editors/object/object_intern.h
+++ b/source/blender/editors/object/object_intern.h
@@ -119,6 +119,7 @@ void OBJECT_OT_pointcloud_add(struct wmOperatorType *ot);
* Only used as menu.
*/
void OBJECT_OT_collection_instance_add(struct wmOperatorType *ot);
+void OBJECT_OT_collection_external_asset_drop(struct wmOperatorType *ot);
void OBJECT_OT_data_instance_add(struct wmOperatorType *ot);
void OBJECT_OT_duplicates_make_real(struct wmOperatorType *ot);
diff --git a/source/blender/editors/object/object_modifier.c b/source/blender/editors/object/object_modifier.c
index 7fedc2c6265..545265b18b1 100644
--- a/source/blender/editors/object/object_modifier.c
+++ b/source/blender/editors/object/object_modifier.c
@@ -219,9 +219,6 @@ ModifierData *ED_object_modifier_add(
/* ensure skin-node customdata exists */
BKE_mesh_ensure_skin_customdata(ob->data);
}
- else if (type == eModifierType_Nodes) {
- MOD_nodes_init(bmain, (NodesModifierData *)new_md);
- }
}
BKE_object_modifier_set_active(ob, new_md);
@@ -541,36 +538,36 @@ bool ED_object_modifier_convert(ReportList *UNUSED(reports),
return false;
}
- int totpart = psys_eval->totcached;
- int totchild = psys_eval->totchildcache;
+ int part_num = psys_eval->totcached;
+ int child_num = psys_eval->totchildcache;
- if (totchild && (part->draw & PART_DRAW_PARENT) == 0) {
- totpart = 0;
+ if (child_num && (part->draw & PART_DRAW_PARENT) == 0) {
+ part_num = 0;
}
/* count */
- int totvert = 0, totedge = 0;
+ int verts_num = 0, edges_num = 0;
ParticleCacheKey **cache = psys_eval->pathcache;
- for (int a = 0; a < totpart; a++) {
+ for (int a = 0; a < part_num; a++) {
ParticleCacheKey *key = cache[a];
if (key->segments > 0) {
- totvert += key->segments + 1;
- totedge += key->segments;
+ verts_num += key->segments + 1;
+ edges_num += key->segments;
}
}
cache = psys_eval->childcache;
- for (int a = 0; a < totchild; a++) {
+ for (int a = 0; a < child_num; a++) {
ParticleCacheKey *key = cache[a];
if (key->segments > 0) {
- totvert += key->segments + 1;
- totedge += key->segments;
+ verts_num += key->segments + 1;
+ edges_num += key->segments;
}
}
- if (totvert == 0) {
+ if (verts_num == 0) {
return false;
}
@@ -578,11 +575,11 @@ bool ED_object_modifier_convert(ReportList *UNUSED(reports),
Object *obn = BKE_object_add(bmain, view_layer, OB_MESH, NULL);
Mesh *me = obn->data;
- me->totvert = totvert;
- me->totedge = totedge;
+ me->totvert = verts_num;
+ me->totedge = edges_num;
- me->mvert = CustomData_add_layer(&me->vdata, CD_MVERT, CD_CALLOC, NULL, totvert);
- me->medge = CustomData_add_layer(&me->edata, CD_MEDGE, CD_CALLOC, NULL, totedge);
+ me->mvert = CustomData_add_layer(&me->vdata, CD_MVERT, CD_CALLOC, NULL, verts_num);
+ me->medge = CustomData_add_layer(&me->edata, CD_MEDGE, CD_CALLOC, NULL, edges_num);
me->mface = CustomData_add_layer(&me->fdata, CD_MFACE, CD_CALLOC, NULL, 0);
MVert *mvert = me->mvert;
@@ -590,7 +587,7 @@ bool ED_object_modifier_convert(ReportList *UNUSED(reports),
/* copy coordinates */
cache = psys_eval->pathcache;
- for (int a = 0; a < totpart; a++) {
+ for (int a = 0; a < part_num; a++) {
ParticleCacheKey *key = cache[a];
int kmax = key->segments;
for (int k = 0; k <= kmax; k++, key++, cvert++, mvert++) {
@@ -609,7 +606,7 @@ bool ED_object_modifier_convert(ReportList *UNUSED(reports),
}
cache = psys_eval->childcache;
- for (int a = 0; a < totchild; a++) {
+ for (int a = 0; a < child_num; a++) {
ParticleCacheKey *key = cache[a];
int kmax = key->segments;
for (int k = 0; k <= kmax; k++, key++, cvert++, mvert++) {
@@ -774,9 +771,9 @@ static bool modifier_apply_obdata(
RPT_INFO,
"Applied modifier only changed CV points, not tessellated/bevel vertices");
- int numVerts;
- float(*vertexCos)[3] = BKE_curve_nurbs_vert_coords_alloc(&curve_eval->nurb, &numVerts);
- mti->deformVerts(md_eval, &mectx, NULL, vertexCos, numVerts);
+ int verts_num;
+ float(*vertexCos)[3] = BKE_curve_nurbs_vert_coords_alloc(&curve_eval->nurb, &verts_num);
+ mti->deformVerts(md_eval, &mectx, NULL, vertexCos, verts_num);
BKE_curve_nurbs_vert_coords_apply(&curve->nurb, vertexCos, false);
MEM_freeN(vertexCos);
@@ -793,9 +790,9 @@ static bool modifier_apply_obdata(
return false;
}
- int numVerts;
- float(*vertexCos)[3] = BKE_lattice_vert_coords_alloc(lattice, &numVerts);
- mti->deformVerts(md_eval, &mectx, NULL, vertexCos, numVerts);
+ int verts_num;
+ float(*vertexCos)[3] = BKE_lattice_vert_coords_alloc(lattice, &verts_num);
+ mti->deformVerts(md_eval, &mectx, NULL, vertexCos, verts_num);
BKE_lattice_vert_coords_apply(lattice, vertexCos);
MEM_freeN(vertexCos);
@@ -1016,6 +1013,7 @@ bool edit_modifier_poll_generic(bContext *C,
const bool is_editmode_allowed,
const bool is_liboverride_allowed)
{
+ Main *bmain = CTX_data_main(C);
PointerRNA ptr = CTX_data_pointer_get_type(C, "modifier", rna_type);
Object *ob = (ptr.owner_id) ? (Object *)ptr.owner_id : ED_object_active_context(C);
ModifierData *mod = ptr.data; /* May be NULL. */
@@ -1024,13 +1022,13 @@ bool edit_modifier_poll_generic(bContext *C,
mod = BKE_object_active_modifier(ob);
}
- if (!ob || ID_IS_LINKED(ob)) {
+ if (!ob || !BKE_id_is_editable(bmain, &ob->id)) {
return false;
}
if (obtype_flag && ((1 << ob->type) & obtype_flag) == 0) {
return false;
}
- if (ptr.owner_id && ID_IS_LINKED(ptr.owner_id)) {
+ if (ptr.owner_id && !BKE_id_is_editable(bmain, ptr.owner_id)) {
return false;
}
@@ -1365,7 +1363,7 @@ void OBJECT_OT_modifier_move_to_index(wmOperatorType *ot)
/** \name Apply Modifier Operator
* \{ */
-static bool modifier_apply_poll_ex(bContext *C, bool allow_shared)
+static bool modifier_apply_poll(bContext *C)
{
if (!edit_modifier_poll_generic(C, &RNA_Modifier, 0, false, false)) {
return false;
@@ -1380,10 +1378,6 @@ static bool modifier_apply_poll_ex(bContext *C, bool allow_shared)
CTX_wm_operator_poll_msg_set(C, "Modifiers cannot be applied on override data");
return false;
}
- if (!allow_shared && (ob->data != NULL) && ID_REAL_USERS(ob->data) > 1) {
- CTX_wm_operator_poll_msg_set(C, "Modifiers cannot be applied to multi-user data");
- return false;
- }
if (md != NULL) {
if ((ob->mode & OB_MODE_SCULPT) && (find_multires_modifier_before(scene, md)) &&
(BKE_modifier_is_same_topology(md) == false)) {
@@ -1395,11 +1389,6 @@ static bool modifier_apply_poll_ex(bContext *C, bool allow_shared)
return true;
}
-static bool modifier_apply_poll(bContext *C)
-{
- return modifier_apply_poll_ex(C, false);
-}
-
static int modifier_apply_exec_ex(bContext *C, wmOperator *op, int apply_as, bool keep_modifier)
{
Main *bmain = CTX_data_main(C);
@@ -1408,11 +1397,19 @@ static int modifier_apply_exec_ex(bContext *C, wmOperator *op, int apply_as, boo
Object *ob = ED_object_active_context(C);
ModifierData *md = edit_modifier_property_get(op, ob, 0);
const bool do_report = RNA_boolean_get(op->ptr, "report");
+ const bool do_single_user = RNA_boolean_get(op->ptr, "single_user");
if (md == NULL) {
return OPERATOR_CANCELLED;
}
+ if (do_single_user && ID_REAL_USERS(ob->data) > 1) {
+ ED_object_single_obdata_user(bmain, scene, ob);
+ BKE_main_id_newptr_and_tag_clear(bmain);
+ WM_event_add_notifier(C, NC_WINDOW, NULL);
+ DEG_relations_tag_update(bmain);
+ }
+
int reports_len;
char name[MAX_NAME];
if (do_report) {
@@ -1449,6 +1446,19 @@ static int modifier_apply_invoke(bContext *C, wmOperator *op, const wmEvent *eve
{
int retval;
if (edit_modifier_invoke_properties_with_hover(C, op, event, &retval)) {
+ PointerRNA ptr = CTX_data_pointer_get_type(C, "modifier", &RNA_Modifier);
+ Object *ob = (ptr.owner_id != NULL) ? (Object *)ptr.owner_id : ED_object_active_context(C);
+
+ if ((ob->data != NULL) && ID_REAL_USERS(ob->data) > 1) {
+ PropertyRNA *prop = RNA_struct_find_property(op->ptr, "single_user");
+ if (!RNA_property_is_set(op->ptr, prop)) {
+ RNA_property_boolean_set(op->ptr, prop, true);
+ }
+ if (RNA_property_boolean_get(op->ptr, prop)) {
+ return WM_operator_confirm_message(
+ C, op, "Make object data single-user and apply modifier");
+ }
+ }
return modifier_apply_exec(C, op);
}
return retval;
@@ -1469,6 +1479,13 @@ void OBJECT_OT_modifier_apply(wmOperatorType *ot)
edit_modifier_properties(ot);
edit_modifier_report_property(ot);
+
+ PropertyRNA *prop = RNA_def_boolean(ot->srna,
+ "single_user",
+ false,
+ "Make Data Single User",
+ "Make the object's data single user if needed");
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
}
/** \} */
@@ -1479,7 +1496,7 @@ void OBJECT_OT_modifier_apply(wmOperatorType *ot)
static bool modifier_apply_as_shapekey_poll(bContext *C)
{
- return modifier_apply_poll_ex(C, true);
+ return modifier_apply_poll(C);
}
static int modifier_apply_as_shapekey_exec(bContext *C, wmOperator *op)
@@ -2781,9 +2798,9 @@ static int meshdeform_bind_exec(bContext *C, wmOperator *op)
MEM_SAFE_FREE(mmd->dynverts);
MEM_SAFE_FREE(mmd->bindweights); /* Deprecated */
MEM_SAFE_FREE(mmd->bindcos); /* Deprecated */
- mmd->totvert = 0;
- mmd->totcagevert = 0;
- mmd->totinfluence = 0;
+ mmd->verts_num = 0;
+ mmd->cage_verts_num = 0;
+ mmd->influences_num = 0;
}
else {
/* Force modifier to run, it will call binding routine
@@ -3119,7 +3136,7 @@ static int laplaciandeform_bind_exec(bContext *C, wmOperator *op)
/* This is hard to know from the modifier itself whether the evaluation is
* happening for binding or not. So we copy all the required data here. */
- lmd->total_verts = lmd_eval->total_verts;
+ lmd->verts_num = lmd_eval->verts_num;
if (lmd_eval->vertexco == NULL) {
MEM_SAFE_FREE(lmd->vertexco);
}
diff --git a/source/blender/editors/object/object_ops.c b/source/blender/editors/object/object_ops.c
index 35f5ede270d..b390cb286ee 100644
--- a/source/blender/editors/object/object_ops.c
+++ b/source/blender/editors/object/object_ops.c
@@ -98,6 +98,7 @@ void ED_operatortypes_object(void)
WM_operatortype_append(OBJECT_OT_transform_to_mouse);
WM_operatortype_append(OBJECT_OT_effector_add);
WM_operatortype_append(OBJECT_OT_collection_instance_add);
+ WM_operatortype_append(OBJECT_OT_collection_external_asset_drop);
WM_operatortype_append(OBJECT_OT_data_instance_add);
WM_operatortype_append(OBJECT_OT_metaball_add);
WM_operatortype_append(OBJECT_OT_duplicates_make_real);
diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c
index 3ecf86d14ed..7be46bdb24b 100644
--- a/source/blender/editors/object/object_relations.c
+++ b/source/blender/editors/object/object_relations.c
@@ -1350,7 +1350,7 @@ static int make_links_scene_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
- if (ID_IS_LINKED(scene_to)) {
+ if (!BKE_id_is_editable(bmain, &scene_to->id)) {
BKE_report(op->reports, RPT_ERROR, "Cannot link objects into a linked scene");
return OPERATOR_CANCELLED;
}
@@ -1481,7 +1481,7 @@ static int make_links_data_exec(bContext *C, wmOperator *op)
case MAKE_LINKS_ANIMDATA:
BKE_animdata_copy_id(bmain, (ID *)ob_dst, (ID *)ob_src, 0);
if (ob_dst->data && ob_src->data) {
- if (ID_IS_LINKED(obdata_id)) {
+ if (!BKE_id_is_editable(bmain, obdata_id)) {
is_lib = true;
break;
}
@@ -1525,7 +1525,7 @@ static int make_links_data_exec(bContext *C, wmOperator *op)
Curve *cu_src = ob_src->data;
Curve *cu_dst = ob_dst->data;
- if (ID_IS_LINKED(obdata_id)) {
+ if (!BKE_id_is_editable(bmain, obdata_id)) {
is_lib = true;
break;
}
@@ -1792,7 +1792,7 @@ static void single_obdata_users(
ID *id;
FOREACH_OBJECT_FLAG_BEGIN (scene, view_layer, v3d, flag, ob) {
- if (!ID_IS_LINKED(ob)) {
+ if (BKE_id_is_editable(bmain, &ob->id)) {
id = ob->data;
if (single_data_needs_duplication(id)) {
DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
@@ -1893,11 +1893,24 @@ static void single_obdata_users(
}
}
+void ED_object_single_obdata_user(Main *bmain, Scene *scene, Object *ob)
+{
+ FOREACH_SCENE_OBJECT_BEGIN (scene, ob_iter) {
+ ob_iter->flag &= ~OB_DONE;
+ }
+ FOREACH_SCENE_OBJECT_END;
+
+ /* Tag only the one object. */
+ ob->flag |= OB_DONE;
+
+ single_obdata_users(bmain, scene, NULL, NULL, OB_DONE);
+}
+
static void single_object_action_users(
Main *bmain, Scene *scene, ViewLayer *view_layer, View3D *v3d, const int flag)
{
FOREACH_OBJECT_FLAG_BEGIN (scene, view_layer, v3d, flag, ob) {
- if (!ID_IS_LINKED(ob)) {
+ if (BKE_id_is_editable(bmain, &ob->id)) {
AnimData *adt = BKE_animdata_from_id(&ob->id);
if (adt == NULL) {
continue;
@@ -1917,7 +1930,7 @@ static void single_objectdata_action_users(
Main *bmain, Scene *scene, ViewLayer *view_layer, View3D *v3d, const int flag)
{
FOREACH_OBJECT_FLAG_BEGIN (scene, view_layer, v3d, flag, ob) {
- if (!ID_IS_LINKED(ob) && ob->data != NULL) {
+ if (BKE_id_is_editable(bmain, &ob->id) && ob->data != NULL) {
ID *id_obdata = (ID *)ob->data;
AnimData *adt = BKE_animdata_from_id(id_obdata);
if (adt == NULL) {
@@ -1941,7 +1954,7 @@ static void single_mat_users(
int a;
FOREACH_OBJECT_FLAG_BEGIN (scene, view_layer, v3d, flag, ob) {
- if (!ID_IS_LINKED(ob)) {
+ if (BKE_id_is_editable(bmain, &ob->id)) {
for (a = 1; a <= ob->totcol; a++) {
ma = BKE_object_material_get(ob, (short)a);
if (single_data_needs_duplication(&ma->id)) {
@@ -2273,6 +2286,10 @@ static int make_override_library_exec(bContext *C, wmOperator *op)
ID *id_root = NULL;
bool is_override_instancing_object = false;
+ GSet *user_overrides_objects_uids = BLI_gset_new(
+ BLI_ghashutil_inthash_p, BLI_ghashutil_intcmp, __func__);
+ bool user_overrides_from_selected_objects = false;
+
if (!ID_IS_LINKED(obact) && obact->instance_collection != NULL &&
ID_IS_LINKED(obact->instance_collection)) {
if (!ID_IS_OVERRIDABLE_LIBRARY(obact->instance_collection)) {
@@ -2285,6 +2302,7 @@ static int make_override_library_exec(bContext *C, wmOperator *op)
id_root = &obact->instance_collection->id;
is_override_instancing_object = true;
+ user_overrides_from_selected_objects = false;
}
else if (!make_override_library_object_overridable_check(bmain, obact)) {
const int i = RNA_property_enum_get(op->ptr, op->type->prop);
@@ -2309,16 +2327,53 @@ static int make_override_library_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
id_root = &collection->id;
+ user_overrides_from_selected_objects = true;
}
/* Else, poll func ensures us that ID_IS_LINKED(obact) is true. */
else {
id_root = &obact->id;
+ user_overrides_from_selected_objects = true;
+ }
+
+ if (user_overrides_from_selected_objects) {
+ /* Only selected objects can be 'user overrides'. */
+ FOREACH_SELECTED_OBJECT_BEGIN (view_layer, CTX_wm_view3d(C), ob_iter) {
+ BLI_gset_add(user_overrides_objects_uids, POINTER_FROM_UINT(ob_iter->id.session_uuid));
+ }
+ FOREACH_SELECTED_OBJECT_END;
+ }
+ else {
+ /* Only armatures inside the root collection (and their children) can be 'user overrides'. */
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN ((Collection *)id_root, ob_iter) {
+ if (ob_iter->type == OB_ARMATURE) {
+ BLI_gset_add(user_overrides_objects_uids, POINTER_FROM_UINT(ob_iter->id.session_uuid));
+ }
+ }
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
}
BKE_main_id_tag_all(bmain, LIB_TAG_DOIT, false);
+ ID *id_root_override;
const bool success = BKE_lib_override_library_create(
- bmain, scene, view_layer, NULL, id_root, id_root, &obact->id, NULL);
+ bmain, scene, view_layer, NULL, id_root, id_root, &obact->id, &id_root_override);
+
+ /* Define liboverrides from selected/validated objects as user defined. */
+ ID *id_hierarchy_root_override = id_root_override->override_library->hierarchy_root;
+ ID *id_iter;
+ FOREACH_MAIN_ID_BEGIN (bmain, id_iter) {
+ if (ID_IS_LINKED(id_iter) || !ID_IS_OVERRIDE_LIBRARY_REAL(id_iter) ||
+ id_iter->override_library->hierarchy_root != id_hierarchy_root_override) {
+ continue;
+ }
+ if (BLI_gset_haskey(user_overrides_objects_uids,
+ POINTER_FROM_UINT(id_iter->override_library->reference->session_uuid))) {
+ id_iter->override_library->flag &= ~IDOVERRIDE_LIBRARY_FLAG_SYSTEM_DEFINED;
+ }
+ }
+ FOREACH_MAIN_ID_END;
+
+ BLI_gset_free(user_overrides_objects_uids, NULL);
/* Remove the instance empty from this scene, the items now have an overridden collection
* instead. */
diff --git a/source/blender/editors/object/object_remesh.cc b/source/blender/editors/object/object_remesh.cc
index 2e495ac6147..966df0668ca 100644
--- a/source/blender/editors/object/object_remesh.cc
+++ b/source/blender/editors/object/object_remesh.cc
@@ -459,7 +459,7 @@ static int voxel_size_edit_invoke(bContext *C, wmOperator *op, const wmEvent *ev
op->customdata = cd;
/* Select the front facing face of the mesh bounding box. */
- BoundBox *bb = BKE_mesh_boundbox_get(cd->active_object);
+ const BoundBox *bb = BKE_mesh_boundbox_get(cd->active_object);
/* Indices of the Bounding Box faces. */
const int BB_faces[6][4] = {
diff --git a/source/blender/editors/object/object_shader_fx.c b/source/blender/editors/object/object_shader_fx.c
index 973f4d4561d..dd7fc192dc1 100644
--- a/source/blender/editors/object/object_shader_fx.c
+++ b/source/blender/editors/object/object_shader_fx.c
@@ -25,6 +25,7 @@
#include "BLT_translation.h"
#include "BKE_context.h"
+#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_object.h"
#include "BKE_report.h"
@@ -278,8 +279,8 @@ static bool edit_shaderfx_poll_generic(bContext *C,
CTX_wm_operator_poll_msg_set(C, "Object type is not supported");
return false;
}
- if (ptr.owner_id != NULL && ID_IS_LINKED(ptr.owner_id)) {
- CTX_wm_operator_poll_msg_set(C, "Cannot edit library data");
+ if (ptr.owner_id != NULL && !BKE_id_is_editable(CTX_data_main(C), ptr.owner_id)) {
+ CTX_wm_operator_poll_msg_set(C, "Cannot edit library or override data");
return false;
}
if (!is_liboverride_allowed && BKE_shaderfx_is_nonlocal_in_liboverride(ob, fx)) {
diff --git a/source/blender/editors/object/object_transform.cc b/source/blender/editors/object/object_transform.cc
index afd2c048379..235ffb61738 100644
--- a/source/blender/editors/object/object_transform.cc
+++ b/source/blender/editors/object/object_transform.cc
@@ -587,18 +587,99 @@ static Array<Object *> sorted_selected_editable_objects(bContext *C)
return sorted_objects;
}
+/**
+ * Check if we need and can handle the special multiuser case.
+ */
+static bool apply_objects_internal_can_multiuser(bContext *C)
+{
+ Object *obact = CTX_data_active_object(C);
+
+ if (ELEM(NULL, obact, obact->data)) {
+ return false;
+ }
+
+ if (ID_REAL_USERS(obact->data) == 1) {
+ return false;
+ }
+
+ bool all_objects_same_data = true;
+ bool obact_selected = false;
+
+ CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) {
+ if (ob->data != obact->data) {
+ all_objects_same_data = false;
+ break;
+ }
+
+ if (ob == obact) {
+ obact_selected = true;
+ }
+ }
+ CTX_DATA_END;
+
+ return all_objects_same_data && obact_selected;
+}
+
+/**
+ * Check if the current selection need to be made into single user.
+ *
+ * It assumes that all selected objects share the same object data.
+ */
+static bool apply_objects_internal_need_single_user(bContext *C)
+{
+ Object *ob = CTX_data_active_object(C);
+ BLI_assert(apply_objects_internal_can_multiuser(C));
+
+ /* Counting the number of objects is valid since it's known the
+ * selection is only made up of users of the active objects data. */
+ return (ID_REAL_USERS(ob->data) > CTX_DATA_COUNT(C, selected_editable_objects));
+}
+
static int apply_objects_internal(bContext *C,
ReportList *reports,
bool apply_loc,
bool apply_rot,
bool apply_scale,
- bool do_props)
+ bool do_props,
+ bool do_single_user)
{
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
float rsmat[3][3], obmat[3][3], iobmat[3][3], mat[4][4], scale;
bool changed = true;
+ bool const do_multi_user = apply_objects_internal_can_multiuser(C);
+ float obact_invmat[4][4], obact_parent[4][4], obact_parentinv[4][4];
+
+ /* Only used when do_multi_user is set. */
+ Object *obact = NULL;
+ bool make_single_user = false;
+
+ if (do_multi_user) {
+ obact = CTX_data_active_object(C);
+ invert_m4_m4(obact_invmat, obact->obmat);
+
+ Object workob;
+ BKE_object_workob_calc_parent(depsgraph, scene, obact, &workob);
+ copy_m4_m4(obact_parent, workob.obmat);
+ copy_m4_m4(obact_parentinv, obact->parentinv);
+
+ if (apply_objects_internal_need_single_user(C)) {
+ if (do_single_user) {
+ make_single_user = true;
+ }
+ else {
+ ID *obact_data = static_cast<ID *>(obact->data);
+ BKE_reportf(reports,
+ RPT_ERROR,
+ "Cannot apply to a multi user: Object \"%s\", %s \"%s\", aborting",
+ obact->id.name + 2,
+ BKE_idtype_idcode_to_name(GS(obact_data->name)),
+ obact_data->name + 2);
+ return OPERATOR_CANCELLED;
+ }
+ }
+ }
/* first check if we can execute */
CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) {
@@ -612,7 +693,7 @@ static int apply_objects_internal(bContext *C,
OB_FONT,
OB_GPENCIL)) {
ID *obdata = static_cast<ID *>(ob->data);
- if (ID_REAL_USERS(obdata) > 1) {
+ if (!do_multi_user && ID_REAL_USERS(obdata) > 1) {
BKE_reportf(reports,
RPT_ERROR,
R"(Cannot apply to a multi user: Object "%s", %s "%s", aborting)",
@@ -622,10 +703,10 @@ static int apply_objects_internal(bContext *C,
changed = false;
}
- if (ID_IS_LINKED(obdata)) {
+ if (ID_IS_LINKED(obdata) || ID_IS_OVERRIDE_LIBRARY(obdata)) {
BKE_reportf(reports,
RPT_ERROR,
- R"(Cannot apply to library data: Object "%s", %s "%s", aborting)",
+ R"(Cannot apply to library or override data: Object "%s", %s "%s", aborting)",
ob->id.name + 2,
BKE_idtype_idcode_to_name(GS(obdata->name)),
obdata->name + 2);
@@ -728,6 +809,15 @@ static int apply_objects_internal(bContext *C,
changed = false;
/* now execute */
+
+ if (make_single_user) {
+ /* Make single user. */
+ ED_object_single_obdata_user(bmain, scene, obact);
+ BKE_main_id_newptr_and_tag_clear(bmain);
+ WM_event_add_notifier(C, NC_WINDOW, NULL);
+ DEG_relations_tag_update(bmain);
+ }
+
Array<Object *> objects = sorted_selected_editable_objects(C);
if (objects.is_empty()) {
return OPERATOR_CANCELLED;
@@ -774,7 +864,14 @@ static int apply_objects_internal(bContext *C,
}
/* apply to object data */
- if (ob->type == OB_MESH) {
+ if (do_multi_user && ob != obact) {
+ /* Don't apply, just set the new object data, the correct
+ * transformations will happen later. */
+ id_us_min((ID *)ob->data);
+ ob->data = obact->data;
+ id_us_plus((ID *)ob->data);
+ }
+ else if (ob->type == OB_MESH) {
Mesh *me = static_cast<Mesh *>(ob->data);
if (apply_scale) {
@@ -882,16 +979,53 @@ static int apply_objects_internal(bContext *C,
continue;
}
- if (apply_loc) {
- zero_v3(ob->loc);
- }
- if (apply_scale) {
- ob->scale[0] = ob->scale[1] = ob->scale[2] = 1.0f;
+ if (do_multi_user && ob != obact) {
+ float _obmat[4][4], _iobmat[4][4];
+ float _mat[4][4];
+
+ copy_m4_m4(_obmat, ob->obmat);
+ invert_m4_m4(_iobmat, _obmat);
+
+ copy_m4_m4(_mat, _obmat);
+ mul_m4_m4_post(_mat, obact_invmat);
+ mul_m4_m4_post(_mat, obact_parent);
+ mul_m4_m4_post(_mat, obact_parentinv);
+
+ if (apply_loc && apply_scale && apply_rot) {
+ BKE_object_apply_mat4(ob, _mat, false, true);
+ }
+ else {
+ Object ob_temp = blender::dna::shallow_copy(*ob);
+ BKE_object_apply_mat4(&ob_temp, _mat, false, true);
+
+ if (apply_loc) {
+ copy_v3_v3(ob->loc, ob_temp.loc);
+ }
+
+ if (apply_scale) {
+ copy_v3_v3(ob->scale, ob_temp.scale);
+ }
+
+ if (apply_rot) {
+ copy_v4_v4(ob->quat, ob_temp.quat);
+ copy_v3_v3(ob->rot, ob_temp.rot);
+ copy_v3_v3(ob->rotAxis, ob_temp.rotAxis);
+ ob->rotAngle = ob_temp.rotAngle;
+ }
+ }
}
- if (apply_rot) {
- zero_v3(ob->rot);
- unit_qt(ob->quat);
- unit_axis_angle(ob->rotAxis, &ob->rotAngle);
+ else {
+ if (apply_loc) {
+ zero_v3(ob->loc);
+ }
+ if (apply_scale) {
+ ob->scale[0] = ob->scale[1] = ob->scale[2] = 1.0f;
+ }
+ if (apply_rot) {
+ zero_v3(ob->rot);
+ unit_qt(ob->quat);
+ unit_axis_angle(ob->rotAxis, &ob->rotAngle);
+ }
}
Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
@@ -969,14 +1103,35 @@ static int object_transform_apply_exec(bContext *C, wmOperator *op)
const bool rot = RNA_boolean_get(op->ptr, "rotation");
const bool sca = RNA_boolean_get(op->ptr, "scale");
const bool do_props = RNA_boolean_get(op->ptr, "properties");
+ const bool do_single_user = RNA_boolean_get(op->ptr, "isolate_users");
if (loc || rot || sca) {
- return apply_objects_internal(C, op->reports, loc, rot, sca, do_props);
+ return apply_objects_internal(C, op->reports, loc, rot, sca, do_props, do_single_user);
}
/* allow for redo */
return OPERATOR_FINISHED;
}
+static int object_transform_apply_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
+{
+ Object *ob = ED_object_active_context(C);
+
+ bool can_handle_multiuser = apply_objects_internal_can_multiuser(C);
+ bool need_single_user = can_handle_multiuser && apply_objects_internal_need_single_user(C);
+
+ if ((ob->data != NULL) && need_single_user) {
+ PropertyRNA *prop = RNA_struct_find_property(op->ptr, "isolate_users");
+ if (!RNA_property_is_set(op->ptr, prop)) {
+ RNA_property_boolean_set(op->ptr, prop, true);
+ }
+ if (RNA_property_boolean_get(op->ptr, prop)) {
+ return WM_operator_confirm_message(
+ C, op, "Create new object-data users and apply transformation");
+ }
+ }
+ return object_transform_apply_exec(C, op);
+}
+
void OBJECT_OT_transform_apply(wmOperatorType *ot)
{
/* identifiers */
@@ -986,6 +1141,7 @@ void OBJECT_OT_transform_apply(wmOperatorType *ot)
/* api callbacks */
ot->exec = object_transform_apply_exec;
+ ot->invoke = object_transform_apply_invoke;
ot->poll = ED_operator_objectmode;
/* flags */
@@ -999,6 +1155,13 @@ void OBJECT_OT_transform_apply(wmOperatorType *ot)
true,
"Apply Properties",
"Modify properties such as curve vertex radius, font size and bone envelope");
+ PropertyRNA *prop = RNA_def_boolean(ot->srna,
+ "isolate_users",
+ false,
+ "Isolate Multi User Data",
+ "Create new object-data users if needed");
+ RNA_def_property_flag(prop, PROP_HIDDEN);
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
/** \} */
@@ -1100,12 +1263,12 @@ static int object_origin_set_exec(bContext *C, wmOperator *op)
}
/* reset flags */
- for (int object_index = 0; object_index < objects.size(); object_index++) {
+ for (const int object_index : objects.index_range()) {
Object *ob = objects[object_index];
ob->flag &= ~OB_DONE;
/* move active first */
- if (ob == obact) {
+ if (ob == obact && objects.size() > 1) {
memmove(&objects[1], objects.data(), object_index * sizeof(Object *));
objects[0] = ob;
}
@@ -1138,7 +1301,7 @@ static int object_origin_set_exec(bContext *C, wmOperator *op)
/* Special support for instanced collections. */
if ((ob->transflag & OB_DUPLICOLLECTION) && ob->instance_collection &&
(ob->instance_collection->id.tag & LIB_TAG_DOIT) == 0) {
- if (ID_IS_LINKED(ob->instance_collection)) {
+ if (!BKE_id_is_editable(bmain, &ob->instance_collection->id)) {
tot_lib_error++;
}
else {
@@ -1163,7 +1326,7 @@ static int object_origin_set_exec(bContext *C, wmOperator *op)
}
}
}
- else if (ID_IS_LINKED(ob->data)) {
+ else if (ID_IS_LINKED(ob->data) || ID_IS_OVERRIDE_LIBRARY(ob->data)) {
tot_lib_error++;
}
else if (ob->type == OB_MESH) {
diff --git a/source/blender/editors/object/object_vgroup.c b/source/blender/editors/object/object_vgroup.c
index f0fa693bd85..a58ffa4e0a6 100644
--- a/source/blender/editors/object/object_vgroup.c
+++ b/source/blender/editors/object/object_vgroup.c
@@ -3062,7 +3062,7 @@ static int vertex_group_select_exec(bContext *C, wmOperator *UNUSED(op))
{
Object *ob = ED_object_context(C);
- if (!ob || ID_IS_LINKED(ob)) {
+ if (!ob || ID_IS_LINKED(ob) || ID_IS_OVERRIDE_LIBRARY(ob)) {
return OPERATOR_CANCELLED;
}
diff --git a/source/blender/editors/physics/particle_edit.c b/source/blender/editors/physics/particle_edit.c
index 4a639e227f7..eba647a1b17 100644
--- a/source/blender/editors/physics/particle_edit.c
+++ b/source/blender/editors/physics/particle_edit.c
@@ -5406,10 +5406,10 @@ static bool particle_edit_toggle_poll(bContext *C)
Object *ob = CTX_data_active_object(C);
if (ob == NULL || ob->type != OB_MESH) {
- return 0;
+ return false;
}
- if (!ob->data || ID_IS_LINKED(ob->data)) {
- return 0;
+ if (!ob->data || ID_IS_LINKED(ob->data) || ID_IS_OVERRIDE_LIBRARY(ob->data)) {
+ return false;
}
return ED_object_particle_edit_mode_supported(ob);
diff --git a/source/blender/editors/physics/particle_object.c b/source/blender/editors/physics/particle_object.c
index 24860b9c4d8..6bea6e2c19e 100644
--- a/source/blender/editors/physics/particle_object.c
+++ b/source/blender/editors/physics/particle_object.c
@@ -1048,7 +1048,7 @@ static void remove_particle_systems_from_object(Object *ob_to)
if (ob_to->type != OB_MESH) {
return;
}
- if (!ob_to->data || ID_IS_LINKED(ob_to->data)) {
+ if (!ob_to->data || ID_IS_LINKED(ob_to->data) || ID_IS_OVERRIDE_LIBRARY(ob_to->data)) {
return;
}
@@ -1090,7 +1090,7 @@ static bool copy_particle_systems_to_object(const bContext *C,
if (ob_to->type != OB_MESH) {
return false;
}
- if (!ob_to->data || ID_IS_LINKED(ob_to->data)) {
+ if (!ob_to->data || !BKE_id_is_editable(bmain, ob_to->data)) {
return false;
}
diff --git a/source/blender/editors/physics/rigidbody_constraint.c b/source/blender/editors/physics/rigidbody_constraint.c
index eb799f46177..66ae2d323fd 100644
--- a/source/blender/editors/physics/rigidbody_constraint.c
+++ b/source/blender/editors/physics/rigidbody_constraint.c
@@ -40,12 +40,21 @@
/* ********************************************** */
/* Helper API's for RigidBody Constraint Editing */
+static bool operator_rigidbody_constraints_editable_poll(Scene *scene)
+{
+ if (scene == NULL || ID_IS_LINKED(scene) || ID_IS_OVERRIDE_LIBRARY(scene) ||
+ (scene->rigidbody_world != NULL && scene->rigidbody_world->constraints != NULL &&
+ (ID_IS_LINKED(scene->rigidbody_world->constraints) ||
+ ID_IS_OVERRIDE_LIBRARY(scene->rigidbody_world->constraints)))) {
+ return false;
+ }
+ return true;
+}
+
static bool ED_operator_rigidbody_con_active_poll(bContext *C)
{
Scene *scene = CTX_data_scene(C);
- if (scene == NULL || ID_IS_LINKED(&scene->id) ||
- (scene->rigidbody_world != NULL && scene->rigidbody_world->constraints != NULL &&
- ID_IS_LINKED(&scene->rigidbody_world->constraints->id))) {
+ if (!operator_rigidbody_constraints_editable_poll(scene)) {
return false;
}
@@ -59,9 +68,7 @@ static bool ED_operator_rigidbody_con_active_poll(bContext *C)
static bool ED_operator_rigidbody_con_add_poll(bContext *C)
{
Scene *scene = CTX_data_scene(C);
- if (scene == NULL || ID_IS_LINKED(&scene->id) ||
- (scene->rigidbody_world != NULL && scene->rigidbody_world->constraints != NULL &&
- ID_IS_LINKED(&scene->rigidbody_world->constraints->id))) {
+ if (!operator_rigidbody_constraints_editable_poll(scene)) {
return false;
}
return ED_operator_object_active_editable(C);
diff --git a/source/blender/editors/physics/rigidbody_object.c b/source/blender/editors/physics/rigidbody_object.c
index 8f69947ceb0..5ff687bce1a 100644
--- a/source/blender/editors/physics/rigidbody_object.c
+++ b/source/blender/editors/physics/rigidbody_object.c
@@ -44,12 +44,21 @@
/* ********************************************** */
/* Helper API's for RigidBody Objects Editing */
+static bool operator_rigidbody_editable_poll(Scene *scene)
+{
+ if (scene == NULL || ID_IS_LINKED(scene) || ID_IS_OVERRIDE_LIBRARY(scene) ||
+ (scene->rigidbody_world != NULL && scene->rigidbody_world->group != NULL &&
+ (ID_IS_LINKED(scene->rigidbody_world->group) ||
+ ID_IS_OVERRIDE_LIBRARY(scene->rigidbody_world->group)))) {
+ return false;
+ }
+ return true;
+}
+
static bool ED_operator_rigidbody_active_poll(bContext *C)
{
Scene *scene = CTX_data_scene(C);
- if (scene == NULL || ID_IS_LINKED(&scene->id) ||
- (scene->rigidbody_world != NULL && scene->rigidbody_world->group != NULL &&
- ID_IS_LINKED(&scene->rigidbody_world->group->id))) {
+ if (!operator_rigidbody_editable_poll(scene)) {
return false;
}
@@ -57,15 +66,14 @@ static bool ED_operator_rigidbody_active_poll(bContext *C)
Object *ob = ED_object_active_context(C);
return (ob && ob->rigidbody_object);
}
- return 0;
+
+ return false;
}
static bool ED_operator_rigidbody_add_poll(bContext *C)
{
Scene *scene = CTX_data_scene(C);
- if (scene == NULL || ID_IS_LINKED(&scene->id) ||
- (scene->rigidbody_world != NULL && scene->rigidbody_world->group != NULL &&
- ID_IS_LINKED(&scene->rigidbody_world->group->id))) {
+ if (!operator_rigidbody_editable_poll(scene)) {
return false;
}
@@ -73,6 +81,7 @@ static bool ED_operator_rigidbody_add_poll(bContext *C)
Object *ob = ED_object_active_context(C);
return (ob && ob->type == OB_MESH);
}
+
return false;
}
diff --git a/source/blender/editors/physics/rigidbody_world.c b/source/blender/editors/physics/rigidbody_world.c
index fa90d1e64d6..a77d70d5d9b 100644
--- a/source/blender/editors/physics/rigidbody_world.c
+++ b/source/blender/editors/physics/rigidbody_world.c
@@ -192,7 +192,7 @@ void RIGIDBODY_OT_world_export(wmOperatorType *ot)
FILE_TYPE_FOLDER,
FILE_SPECIAL,
FILE_SAVE,
- FILE_RELPATH,
+ WM_FILESEL_RELPATH,
FILE_DEFAULTDISPLAY,
FILE_SORT_DEFAULT);
}
diff --git a/source/blender/editors/render/render_intern.hh b/source/blender/editors/render/render_intern.hh
index fc40fb06851..4135a0d97a9 100644
--- a/source/blender/editors/render/render_intern.hh
+++ b/source/blender/editors/render/render_intern.hh
@@ -33,6 +33,8 @@ void SCENE_OT_view_layer_add(struct wmOperatorType *ot);
void SCENE_OT_view_layer_remove(struct wmOperatorType *ot);
void SCENE_OT_view_layer_add_aov(struct wmOperatorType *ot);
void SCENE_OT_view_layer_remove_aov(struct wmOperatorType *ot);
+void SCENE_OT_view_layer_add_lightgroup(struct wmOperatorType *ot);
+void SCENE_OT_view_layer_remove_lightgroup(struct wmOperatorType *ot);
void SCENE_OT_light_cache_bake(struct wmOperatorType *ot);
void SCENE_OT_light_cache_free(struct wmOperatorType *ot);
diff --git a/source/blender/editors/render/render_ops.cc b/source/blender/editors/render/render_ops.cc
index 1583ce44ee5..f671b2f950d 100644
--- a/source/blender/editors/render/render_ops.cc
+++ b/source/blender/editors/render/render_ops.cc
@@ -39,6 +39,8 @@ void ED_operatortypes_render()
WM_operatortype_append(SCENE_OT_view_layer_remove);
WM_operatortype_append(SCENE_OT_view_layer_add_aov);
WM_operatortype_append(SCENE_OT_view_layer_remove_aov);
+ WM_operatortype_append(SCENE_OT_view_layer_add_lightgroup);
+ WM_operatortype_append(SCENE_OT_view_layer_remove_lightgroup);
WM_operatortype_append(SCENE_OT_render_view_add);
WM_operatortype_append(SCENE_OT_render_view_remove);
diff --git a/source/blender/editors/render/render_preview.cc b/source/blender/editors/render/render_preview.cc
index ef0f0b6225c..7404b3bf010 100644
--- a/source/blender/editors/render/render_preview.cc
+++ b/source/blender/editors/render/render_preview.cc
@@ -374,6 +374,14 @@ static ID *duplicate_ids(ID *id, const bool allow_failure)
LIB_ID_COPY_NO_ANIMDATA);
return id_copy;
}
+ case ID_GR: {
+ /* Doesn't really duplicate the collection. Just creates a collection instance empty. */
+ BLI_assert(BKE_previewimg_id_supports_jobs(id));
+ Object *instance_empty = BKE_object_add_only_object(nullptr, OB_EMPTY, nullptr);
+ instance_empty->instance_collection = (Collection *)id;
+ instance_empty->transflag |= OB_DUPLICOLLECTION;
+ return &instance_empty->id;
+ }
/* These support threading, but don't need duplicating. */
case ID_IM:
case ID_BR:
@@ -884,6 +892,44 @@ static void object_preview_render(IconPreview *preview, IconPreviewSize *preview
/** \} */
/* -------------------------------------------------------------------- */
+/** \name Collection Preview
+ *
+ * For the most part this reuses the object preview code by creating an instance collection empty
+ * object and rendering that.
+ *
+ * \{ */
+
+/**
+ * Check if the collection contains any geometry that can be rendered. Otherwise there's nothing to
+ * display in the preview, so don't generate one.
+ * Objects and sub-collections hidden in the render will be skipped.
+ */
+static bool collection_preview_contains_geometry_recursive(const Collection *collection)
+{
+ LISTBASE_FOREACH (CollectionObject *, col_ob, &collection->gobject) {
+ if (col_ob->ob->visibility_flag & OB_HIDE_RENDER) {
+ continue;
+ }
+ if (OB_TYPE_IS_GEOMETRY(col_ob->ob->type)) {
+ return true;
+ }
+ }
+
+ LISTBASE_FOREACH (CollectionChild *, child_col, &collection->children) {
+ if (child_col->collection->flag & COLLECTION_HIDE_RENDER) {
+ continue;
+ }
+ if (collection_preview_contains_geometry_recursive(child_col->collection)) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
/** \name Action Preview
* \{ */
@@ -1577,6 +1623,12 @@ static void icon_preview_startjob_all_sizes(void *customdata,
continue;
}
break;
+ case ID_GR:
+ BLI_assert(collection_preview_contains_geometry_recursive((Collection *)ip->id));
+ /* A collection instance empty was created, so this can just reuse the object preview
+ * rendering. */
+ object_preview_render(ip, cur_size);
+ continue;
case ID_AC:
action_preview_render(ip, cur_size);
continue;
@@ -1868,6 +1920,9 @@ bool ED_preview_id_is_supported(const ID *id)
if (GS(id->name) == ID_OB) {
return object_preview_is_type_supported((const Object *)id);
}
+ if (GS(id->name) == ID_GR) {
+ return collection_preview_contains_geometry_recursive((const Collection *)id);
+ }
return BKE_previewimg_id_get_p(id) != nullptr;
}
diff --git a/source/blender/editors/render/render_shading.cc b/source/blender/editors/render/render_shading.cc
index f48ac99fe75..07a07b462ef 100644
--- a/source/blender/editors/render/render_shading.cc
+++ b/source/blender/editors/render/render_shading.cc
@@ -1115,6 +1115,86 @@ void SCENE_OT_view_layer_remove_aov(wmOperatorType *ot)
/** \} */
/* -------------------------------------------------------------------- */
+/** \name View Layer Add Lightgroup Operator
+ * \{ */
+
+static int view_layer_add_lightgroup_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+
+ BKE_view_layer_add_lightgroup(view_layer);
+
+ if (scene->nodetree) {
+ ntreeCompositUpdateRLayers(scene->nodetree);
+ }
+
+ DEG_id_tag_update(&scene->id, 0);
+ DEG_relations_tag_update(CTX_data_main(C));
+ WM_event_add_notifier(C, NC_SCENE | ND_LAYER, scene);
+
+ return OPERATOR_FINISHED;
+}
+
+void SCENE_OT_view_layer_add_lightgroup(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Add Lightgroup";
+ ot->idname = "SCENE_OT_view_layer_add_lightgroup";
+ ot->description = "Add a Light Group";
+
+ /* api callbacks */
+ ot->exec = view_layer_add_lightgroup_exec;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name View Layer Remove Lightgroup Operator
+ * \{ */
+
+static int view_layer_remove_lightgroup_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+
+ if (view_layer->active_lightgroup == nullptr) {
+ return OPERATOR_FINISHED;
+ }
+
+ BKE_view_layer_remove_lightgroup(view_layer, view_layer->active_lightgroup);
+
+ if (scene->nodetree) {
+ ntreeCompositUpdateRLayers(scene->nodetree);
+ }
+
+ DEG_id_tag_update(&scene->id, 0);
+ DEG_relations_tag_update(CTX_data_main(C));
+ WM_event_add_notifier(C, NC_SCENE | ND_LAYER, scene);
+
+ return OPERATOR_FINISHED;
+}
+
+void SCENE_OT_view_layer_remove_lightgroup(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Remove Lightgroup";
+ ot->idname = "SCENE_OT_view_layer_remove_lightgroup";
+ ot->description = "Remove Active Lightgroup";
+
+ /* api callbacks */
+ ot->exec = view_layer_remove_lightgroup_exec;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
/** \name Light Cache Bake Operator
* \{ */
diff --git a/source/blender/editors/screen/screen_draw.c b/source/blender/editors/screen/screen_draw.c
index dbdd0957d4b..6406b0d9d52 100644
--- a/source/blender/editors/screen/screen_draw.c
+++ b/source/blender/editors/screen/screen_draw.c
@@ -173,7 +173,7 @@ void ED_screen_draw_edges(wmWindow *win)
BLI_rcti_do_minmax_v(&scissor_rect, (int[2]){area->v3->vec.x, area->v3->vec.y});
}
- if (GPU_type_matches(GPU_DEVICE_INTEL_UHD, GPU_OS_UNIX, GPU_DRIVER_ANY)) {
+ if (GPU_type_matches_ex(GPU_DEVICE_INTEL_UHD, GPU_OS_UNIX, GPU_DRIVER_ANY, GPU_BACKEND_OPENGL)) {
/* For some reason, on linux + Intel UHD Graphics 620 the driver
* hangs if we don't flush before this. (See T57455) */
GPU_flush();
diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c
index d3cb6942892..408ddfe7241 100644
--- a/source/blender/editors/screen/screen_ops.c
+++ b/source/blender/editors/screen/screen_ops.c
@@ -177,10 +177,10 @@ bool ED_operator_scene(bContext *C)
bool ED_operator_scene_editable(bContext *C)
{
Scene *scene = CTX_data_scene(C);
- if (scene && !ID_IS_LINKED(scene)) {
- return true;
+ if (scene == NULL || !BKE_id_is_editable(CTX_data_main(C), &scene->id)) {
+ return false;
}
- return false;
+ return true;
}
bool ED_operator_objectmode(bContext *C)
@@ -319,7 +319,7 @@ bool ED_operator_node_editable(bContext *C)
{
SpaceNode *snode = CTX_wm_space_node(C);
- if (snode && snode->edittree && !ID_IS_LINKED(snode->edittree)) {
+ if (snode && snode->edittree && BKE_id_is_editable(CTX_data_main(C), &snode->edittree->id)) {
return true;
}
@@ -380,8 +380,8 @@ bool ED_operator_object_active_editable_ex(bContext *C, const Object *ob)
return false;
}
- if (ID_IS_LINKED(ob)) {
- CTX_wm_operator_poll_msg_set(C, "Cannot edit library linked object");
+ if (!BKE_id_is_editable(CTX_data_main(C), (ID *)ob)) {
+ CTX_wm_operator_poll_msg_set(C, "Cannot edit library linked or non-editable override object");
return false;
}
@@ -546,9 +546,10 @@ bool ED_operator_posemode(bContext *C)
bool ED_operator_posemode_local(bContext *C)
{
if (ED_operator_posemode(C)) {
+ Main *bmain = CTX_data_main(C);
Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C));
bArmature *arm = ob->data;
- return !(ID_IS_LINKED(&ob->id) || ID_IS_LINKED(&arm->id));
+ return (BKE_id_is_editable(bmain, &ob->id) && BKE_id_is_editable(bmain, &arm->id));
}
return false;
}
diff --git a/source/blender/editors/sculpt_paint/curves_sculpt_snake_hook.cc b/source/blender/editors/sculpt_paint/curves_sculpt_snake_hook.cc
index 682cd3b47ca..1fb3931e00f 100644
--- a/source/blender/editors/sculpt_paint/curves_sculpt_snake_hook.cc
+++ b/source/blender/editors/sculpt_paint/curves_sculpt_snake_hook.cc
@@ -36,6 +36,14 @@
#include "ED_screen.h"
#include "ED_view3d.h"
+/**
+ * The code below uses a prefix naming convention to indicate the coordinate space:
+ * - `cu`: Local space of the curves object that is being edited.
+ * - `su`: Local space of the surface object.
+ * - `wo`: World space.
+ * - `re`: 2D coordinates within the region.
+ */
+
namespace blender::ed::sculpt_paint {
using blender::bke::CurvesGeometry;
@@ -45,116 +53,231 @@ using blender::bke::CurvesGeometry;
*/
class SnakeHookOperation : public CurvesSculptStrokeOperation {
private:
- float2 last_mouse_position_;
+ float2 last_mouse_position_re_;
+
+ CurvesBrush3D brush_3d_;
+
+ friend struct SnakeHookOperatorExecutor;
public:
- void on_stroke_extended(bContext *C, const StrokeExtension &stroke_extension) override
+ void on_stroke_extended(bContext *C, const StrokeExtension &stroke_extension) override;
+};
+
+/**
+ * Utility class that actually executes the update when the stroke is updated. That's useful
+ * because it avoids passing a very large number of parameters between functions.
+ */
+struct SnakeHookOperatorExecutor {
+ SnakeHookOperation *self_ = nullptr;
+ bContext *C_ = nullptr;
+ Scene *scene_ = nullptr;
+ Object *object_ = nullptr;
+ ARegion *region_ = nullptr;
+ View3D *v3d_ = nullptr;
+ RegionView3D *rv3d_ = nullptr;
+
+ CurvesSculpt *curves_sculpt_ = nullptr;
+ Brush *brush_ = nullptr;
+ float brush_radius_re_;
+ float brush_strength_;
+ eBrushFalloffShape falloff_shape_;
+
+ Curves *curves_id_ = nullptr;
+ CurvesGeometry *curves_ = nullptr;
+
+ float4x4 curves_to_world_mat_;
+ float4x4 world_to_curves_mat_;
+
+ float2 brush_pos_prev_re_;
+ float2 brush_pos_re_;
+ float2 brush_pos_diff_re_;
+
+ void execute(SnakeHookOperation &self, bContext *C, const StrokeExtension &stroke_extension)
{
- BLI_SCOPED_DEFER([&]() { last_mouse_position_ = stroke_extension.mouse_position; });
+ BLI_SCOPED_DEFER([&]() { self.last_mouse_position_re_ = stroke_extension.mouse_position; });
+
+ self_ = &self;
+ C_ = C;
+ scene_ = CTX_data_scene(C);
+ object_ = CTX_data_active_object(C);
+ region_ = CTX_wm_region(C);
+ v3d_ = CTX_wm_view3d(C);
+ rv3d_ = CTX_wm_region_view3d(C);
+
+ curves_sculpt_ = scene_->toolsettings->curves_sculpt;
+ brush_ = BKE_paint_brush(&curves_sculpt_->paint);
+ brush_radius_re_ = BKE_brush_size_get(scene_, brush_);
+ brush_strength_ = BKE_brush_alpha_get(scene_, brush_);
+ falloff_shape_ = static_cast<eBrushFalloffShape>(brush_->falloff_shape);
+
+ curves_to_world_mat_ = object_->obmat;
+ world_to_curves_mat_ = curves_to_world_mat_.inverted();
+
+ curves_id_ = static_cast<Curves *>(object_->data);
+ curves_ = &CurvesGeometry::wrap(curves_id_->geometry);
+
+ brush_pos_prev_re_ = self.last_mouse_position_re_;
+ brush_pos_re_ = stroke_extension.mouse_position;
+ brush_pos_diff_re_ = brush_pos_re_ - brush_pos_prev_re_;
if (stroke_extension.is_first) {
+ if (falloff_shape_ == PAINT_FALLOFF_SHAPE_SPHERE) {
+ std::optional<CurvesBrush3D> brush_3d = sample_curves_3d_brush(
+ *C_, *object_, brush_pos_re_, brush_radius_re_);
+ if (brush_3d.has_value()) {
+ self_->brush_3d_ = *brush_3d;
+ }
+ }
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);
+ if (falloff_shape_ == PAINT_FALLOFF_SHAPE_SPHERE) {
+ this->spherical_snake_hook();
+ }
+ else if (falloff_shape_ == PAINT_FALLOFF_SHAPE_TUBE) {
+ this->projected_snake_hook();
+ }
+ else {
+ BLI_assert_unreachable();
+ }
- 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);
+ curves_->tag_positions_changed();
+ DEG_id_tag_update(&curves_id_->id, ID_RECALC_GEOMETRY);
+ ED_region_tag_redraw(region_);
+ }
- const float4x4 ob_mat = object.obmat;
- const float4x4 ob_imat = ob_mat.inverted();
+ void projected_snake_hook()
+ {
+ MutableSpan<float3> positions_cu = curves_->positions();
float4x4 projection;
- ED_view3d_ob_project_mat_get(rv3d, &object, projection.values);
+ 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();
+ threading::parallel_for(curves_->curves_range(), 256, [&](const IndexRange curves_range) {
+ for (const int curve_i : curves_range) {
+ const IndexRange points = curves_->points_for_curve(curve_i);
+ const int last_point_i = points.last();
+ const float3 old_pos_cu = positions_cu[last_point_i];
- const float2 mouse_prev = last_mouse_position_;
- const float2 mouse_cur = stroke_extension.mouse_position;
- const float2 mouse_diff = mouse_cur - mouse_prev;
+ float2 old_pos_re;
+ ED_view3d_project_float_v2_m4(region_, old_pos_cu, old_pos_re, projection.values);
- threading::parallel_for(curves.curves_range(), 256, [&](const IndexRange curves_range) {
- for (const int curve_i : curves_range) {
- const IndexRange curve_points = curves.points_for_curve(curve_i);
- const int last_point_i = curve_points.last();
+ const float distance_to_brush_re = math::distance(old_pos_re, brush_pos_prev_re_);
+ if (distance_to_brush_re > brush_radius_re_) {
+ continue;
+ }
- const float3 old_position = positions[last_point_i];
+ const float radius_falloff = BKE_brush_curve_strength(
+ brush_, distance_to_brush_re, brush_radius_re_);
+ const float weight = brush_strength_ * radius_falloff;
- float2 old_position_screen;
- ED_view3d_project_float_v2_m4(
- region, old_position, old_position_screen, projection.values);
+ const float2 new_position_re = old_pos_re + brush_pos_diff_re_ * weight;
+ float3 new_position_wo;
+ ED_view3d_win_to_3d(
+ v3d_, region_, curves_to_world_mat_ * old_pos_cu, new_position_re, new_position_wo);
+ const float3 new_position_cu = world_to_curves_mat_ * new_position_wo;
- const float distance_screen = math::distance(old_position_screen, mouse_prev);
- if (distance_screen > brush_radius) {
+ this->move_last_point_and_resample(positions_cu.slice(points), new_position_cu);
+ }
+ });
+ }
+
+ void spherical_snake_hook()
+ {
+ MutableSpan<float3> positions_cu = curves_->positions();
+
+ float4x4 projection;
+ ED_view3d_ob_project_mat_get(rv3d_, object_, projection.values);
+
+ float3 brush_start_wo, brush_end_wo;
+ ED_view3d_win_to_3d(v3d_,
+ region_,
+ curves_to_world_mat_ * self_->brush_3d_.position_cu,
+ brush_pos_prev_re_,
+ brush_start_wo);
+ ED_view3d_win_to_3d(v3d_,
+ region_,
+ curves_to_world_mat_ * self_->brush_3d_.position_cu,
+ brush_pos_re_,
+ brush_end_wo);
+ const float3 brush_start_cu = world_to_curves_mat_ * brush_start_wo;
+ const float3 brush_end_cu = world_to_curves_mat_ * brush_end_wo;
+ const float3 brush_diff_cu = brush_end_cu - brush_start_cu;
+
+ const float brush_radius_cu = self_->brush_3d_.radius_cu;
+ const float brush_radius_sq_cu = pow2f(brush_radius_cu);
+
+ threading::parallel_for(curves_->curves_range(), 256, [&](const IndexRange curves_range) {
+ for (const int curve_i : curves_range) {
+ const IndexRange points = curves_->points_for_curve(curve_i);
+ const int last_point_i = points.last();
+ const float3 old_pos_cu = positions_cu[last_point_i];
+
+ const float distance_to_brush_sq_cu = dist_squared_to_line_segment_v3(
+ old_pos_cu, brush_start_cu, brush_end_cu);
+ if (distance_to_brush_sq_cu > brush_radius_sq_cu) {
continue;
}
- const float radius_falloff = pow2f(1.0f - distance_screen / brush_radius);
- const float weight = brush_strength * radius_falloff;
+ const float distance_to_brush_cu = std::sqrt(distance_to_brush_sq_cu);
+
+ const float radius_falloff = BKE_brush_curve_strength(
+ brush_, distance_to_brush_cu, brush_radius_cu);
+ 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;
+ const float3 new_pos_cu = old_pos_cu + weight * brush_diff_cu;
- this->move_last_point_and_resample(positions, curve_points, new_position);
+ this->move_last_point_and_resample(positions_cu.slice(points), new_pos_cu);
}
});
-
- 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
+ void move_last_point_and_resample(MutableSpan<float3> positions_cu,
+ const float3 &new_last_point_position_cu) const
{
- Vector<float> old_lengths;
- old_lengths.append(0.0f);
+ Vector<float> old_lengths_cu;
+ old_lengths_cu.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);
+ for (const int segment_i : IndexRange(positions_cu.size() - 1)) {
+ const float3 &p1_cu = positions_cu[segment_i];
+ const float3 &p2_cu = positions_cu[segment_i + 1];
+ const float length_cu = math::distance(p1_cu, p2_cu);
+ old_lengths_cu.append(old_lengths_cu.last() + length_cu + extra_length);
}
Vector<float> point_factors;
- for (float &old_length : old_lengths) {
- point_factors.append(old_length / old_lengths.last());
+ for (float &old_length_cu : old_lengths_cu) {
+ point_factors.append(old_length_cu / old_lengths_cu.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.resize(positions_cu.size());
+ MutableSpan<float3> new_spline_positions_cu = new_spline.positions();
+ for (const int i : IndexRange(positions_cu.size() - 1)) {
+ new_spline_positions_cu[i] = positions_cu[i];
}
- new_spline_positions.last() = new_last_point_position;
+ new_spline_positions_cu.last() = new_last_point_position_cu;
new_spline.mark_cache_invalid();
- for (const int i : IndexRange(curve_points.size())) {
+ for (const int i : positions_cu.index_range()) {
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;
+ float3 p_cu;
new_spline.sample_with_index_factors<float3>(
- new_spline_positions, {&index_factor, 1}, {&p, 1});
- positions[curve_points[i]] = p;
+ new_spline_positions_cu, {&index_factor, 1}, {&p_cu, 1});
+ positions_cu[i] = p_cu;
}
}
};
+void SnakeHookOperation::on_stroke_extended(bContext *C, const StrokeExtension &stroke_extension)
+{
+ SnakeHookOperatorExecutor executor;
+ executor.execute(*this, C, stroke_extension);
+}
+
std::unique_ptr<CurvesSculptStrokeOperation> new_snake_hook_operation()
{
return std::make_unique<SnakeHookOperation>();
diff --git a/source/blender/editors/sculpt_paint/paint_cursor.c b/source/blender/editors/sculpt_paint/paint_cursor.c
index 37bc8b462aa..861da185975 100644
--- a/source/blender/editors/sculpt_paint/paint_cursor.c
+++ b/source/blender/editors/sculpt_paint/paint_cursor.c
@@ -1039,7 +1039,7 @@ static void cursor_draw_tiling_preview(const uint gpuattr,
Object *ob,
const float radius)
{
- BoundBox *bb = BKE_object_boundbox_get(ob);
+ const BoundBox *bb = BKE_object_boundbox_get(ob);
float orgLoc[3], location[3];
int tile_pass = 0;
int start[3];
diff --git a/source/blender/editors/sculpt_paint/paint_image.cc b/source/blender/editors/sculpt_paint/paint_image.cc
index 0c73c2e1f43..572e5b78b74 100644
--- a/source/blender/editors/sculpt_paint/paint_image.cc
+++ b/source/blender/editors/sculpt_paint/paint_image.cc
@@ -272,7 +272,8 @@ static bool image_paint_poll_ex(bContext *C, bool check_tool)
SpaceImage *sima = CTX_wm_space_image(C);
if (sima) {
- if (sima->image != nullptr && ID_IS_LINKED(sima->image)) {
+ if (sima->image != nullptr &&
+ (ID_IS_LINKED(sima->image) || ID_IS_OVERRIDE_LIBRARY(sima->image))) {
return false;
}
ARegion *region = CTX_wm_region(C);
@@ -850,7 +851,7 @@ static bool texture_paint_toggle_poll(bContext *C)
if (ob == nullptr || ob->type != OB_MESH) {
return false;
}
- if (!ob->data || ID_IS_LINKED(ob->data)) {
+ if (ob->data == nullptr || ID_IS_LINKED(ob->data) || ID_IS_OVERRIDE_LIBRARY(ob->data)) {
return false;
}
diff --git a/source/blender/editors/sculpt_paint/paint_image_proj.c b/source/blender/editors/sculpt_paint/paint_image_proj.c
index 12215083eb6..233cfc3b33d 100644
--- a/source/blender/editors/sculpt_paint/paint_image_proj.c
+++ b/source/blender/editors/sculpt_paint/paint_image_proj.c
@@ -6332,7 +6332,7 @@ bool ED_paint_proj_mesh_data_check(
for (int i = 1; i < ob->totcol + 1; i++) {
Material *ma = BKE_object_material_get(ob, i);
- if (ma && !ID_IS_LINKED(ma)) {
+ if (ma && !ID_IS_LINKED(ma) && !ID_IS_OVERRIDE_LIBRARY(ma)) {
hasmat = true;
if (ma->texpaintslot == NULL) {
/* refresh here just in case */
@@ -6340,7 +6340,8 @@ bool ED_paint_proj_mesh_data_check(
}
if (ma->texpaintslot != NULL &&
(ma->texpaintslot[ma->paint_active_slot].ima == NULL ||
- !ID_IS_LINKED(ma->texpaintslot[ma->paint_active_slot].ima))) {
+ !ID_IS_LINKED(ma->texpaintslot[ma->paint_active_slot].ima) ||
+ !ID_IS_OVERRIDE_LIBRARY(ma->texpaintslot[ma->paint_active_slot].ima))) {
hastex = true;
break;
}
diff --git a/source/blender/editors/sculpt_paint/paint_vertex.c b/source/blender/editors/sculpt_paint/paint_vertex.c
index e2f8d81fe13..c4d80d38100 100644
--- a/source/blender/editors/sculpt_paint/paint_vertex.c
+++ b/source/blender/editors/sculpt_paint/paint_vertex.c
@@ -1404,7 +1404,7 @@ static bool paint_mode_toggle_poll_test(bContext *C)
if (ob == NULL || ob->type != OB_MESH) {
return false;
}
- if (!ob->data || ID_IS_LINKED(ob->data)) {
+ if (!ob->data || ID_IS_LINKED(ob->data) || ID_IS_OVERRIDE_LIBRARY(ob->data)) {
return false;
}
return true;
diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c
index be105a23a84..3644c3177d3 100644
--- a/source/blender/editors/sculpt_paint/sculpt.c
+++ b/source/blender/editors/sculpt_paint/sculpt.c
@@ -3699,7 +3699,7 @@ static void do_tiled(
SculptSession *ss = ob->sculpt;
StrokeCache *cache = ss->cache;
const float radius = cache->radius;
- BoundBox *bb = BKE_object_boundbox_get(ob);
+ const BoundBox *bb = BKE_object_boundbox_get(ob);
const float *bbMin = bb->vec[0];
const float *bbMax = bb->vec[6];
const float *step = sd->paint.tile_offset;
diff --git a/source/blender/editors/sculpt_paint/sculpt_ops.c b/source/blender/editors/sculpt_paint/sculpt_ops.c
index 53e8649585a..cd174681ccb 100644
--- a/source/blender/editors/sculpt_paint/sculpt_ops.c
+++ b/source/blender/editors/sculpt_paint/sculpt_ops.c
@@ -616,7 +616,7 @@ static int vertex_to_loop_colors_exec(bContext *C, wmOperator *UNUSED(op))
ID *data;
data = ob->data;
- if (data && ID_IS_LINKED(data)) {
+ if (data == NULL || ID_IS_LINKED(data) || ID_IS_OVERRIDE_LIBRARY(data)) {
return OPERATOR_CANCELLED;
}
@@ -681,7 +681,7 @@ static int loop_to_vertex_colors_exec(bContext *C, wmOperator *UNUSED(op))
ID *data;
data = ob->data;
- if (data && ID_IS_LINKED(data)) {
+ if (data == NULL || ID_IS_LINKED(data) || ID_IS_OVERRIDE_LIBRARY(data)) {
return OPERATOR_CANCELLED;
}
diff --git a/source/blender/editors/space_buttons/buttons_ops.c b/source/blender/editors/space_buttons/buttons_ops.c
index f91ed5eb4f3..10fb008049d 100644
--- a/source/blender/editors/space_buttons/buttons_ops.c
+++ b/source/blender/editors/space_buttons/buttons_ops.c
@@ -207,13 +207,13 @@ static int file_browse_exec(bContext *C, wmOperator *op)
/* Do this first so '//' isn't converted to '//\' on windows. */
BLI_path_slash_ensure(path);
if (is_relative) {
- const int path_len = BLI_strncpy_rlen(path, str, FILE_MAX);
BLI_path_rel(path, BKE_main_blendfile_path(bmain));
- str = MEM_reallocN(str, path_len + 2);
- BLI_strncpy(str, path, FILE_MAX);
+ str_len = strlen(path);
+ str = MEM_reallocN(str, str_len + 1);
+ memcpy(str, path, str_len + 1);
}
else {
- str = MEM_reallocN(str, str_len + 2);
+ str = MEM_reallocN(str, str_len + 1);
}
}
else {
diff --git a/source/blender/editors/space_file/fsmenu.c b/source/blender/editors/space_file/fsmenu.c
index ae0e5b23d55..65354591034 100644
--- a/source/blender/editors/space_file/fsmenu.c
+++ b/source/blender/editors/space_file/fsmenu.c
@@ -463,7 +463,12 @@ void fsmenu_insert_entry(struct FSMenu *fsmenu,
ED_fsmenu_entry_set_icon(fsm_iter, icon);
- fsmenu_entry_refresh_valid(fsm_iter);
+ if (flag & FS_INSERT_NO_VALIDATE) {
+ fsm_iter->valid = true;
+ }
+ else {
+ fsmenu_entry_refresh_valid(fsm_iter);
+ }
if (fsm_prev) {
if (flag & FS_INSERT_FIRST) {
@@ -689,7 +694,12 @@ void fsmenu_read_system(struct FSMenu *fsmenu, int read_bookmarks)
break;
}
- fsmenu_insert_entry(fsmenu, FS_CATEGORY_SYSTEM, tmps, name, icon, FS_INSERT_SORTED);
+ fsmenu_insert_entry(fsmenu,
+ FS_CATEGORY_SYSTEM,
+ tmps,
+ name,
+ icon,
+ FS_INSERT_SORTED | FS_INSERT_NO_VALIDATE);
}
}
diff --git a/source/blender/editors/space_node/drawnode.cc b/source/blender/editors/space_node/drawnode.cc
index 365a17c0a04..958a9fdfc60 100644
--- a/source/blender/editors/space_node/drawnode.cc
+++ b/source/blender/editors/space_node/drawnode.cc
@@ -791,6 +791,9 @@ static void node_composit_set_butfunc(bNodeType *ntype)
ntype->draw_buttons = node_composit_buts_image;
ntype->draw_buttons_ex = node_composit_buts_image_ex;
break;
+ case CMP_NODE_NORMAL:
+ ntype->draw_buttons = node_buts_normal;
+ break;
case CMP_NODE_CURVE_RGB:
ntype->draw_buttons = node_buts_curvecol;
break;
@@ -1299,8 +1302,7 @@ static void std_node_socket_draw(
uiItemL(row, text, 0);
if (socket_needs_attribute_search(*node, *sock)) {
- const bNodeTree *node_tree = (const bNodeTree *)node_ptr->owner_id;
- node_geometry_add_attribute_search_button(*C, *node_tree, *node, *ptr, *row);
+ node_geometry_add_attribute_search_button(*C, *node, *ptr, *row);
}
else {
uiItemR(row, ptr, "default_value", DEFAULT_FLAGS, "", 0);
@@ -1556,7 +1558,6 @@ bool node_link_bezier_handles(const View2D *v2d,
}
/* in v0 and v3 we put begin/end points */
- int toreroute, fromreroute;
if (link.fromsock) {
vec[0][0] = link.fromsock->locx;
vec[0][1] = link.fromsock->locy;
@@ -1567,14 +1568,12 @@ bool node_link_bezier_handles(const View2D *v2d,
link.fromsock->total_inputs);
copy_v2_v2(vec[0], position);
}
- fromreroute = (link.fromnode && link.fromnode->type == NODE_REROUTE);
}
else {
if (snode == nullptr) {
return false;
}
copy_v2_v2(vec[0], cursor);
- fromreroute = 0;
}
if (link.tosock) {
vec[3][0] = link.tosock->locx;
@@ -1586,14 +1585,12 @@ bool node_link_bezier_handles(const View2D *v2d,
link.tosock->total_inputs);
copy_v2_v2(vec[3], position);
}
- toreroute = (link.tonode && link.tonode->type == NODE_REROUTE);
}
else {
if (snode == nullptr) {
return false;
}
copy_v2_v2(vec[3], cursor);
- toreroute = 0;
}
/* may be called outside of drawing (so pass spacetype) */
@@ -1607,37 +1604,12 @@ bool node_link_bezier_handles(const View2D *v2d,
}
const float dist = curving * 0.10f * fabsf(vec[0][0] - vec[3][0]);
- const float deltax = vec[3][0] - vec[0][0];
- const float deltay = vec[3][1] - vec[0][1];
- /* check direction later, for top sockets */
- if (fromreroute) {
- if (fabsf(deltax) > fabsf(deltay)) {
- vec[1][1] = vec[0][1];
- vec[1][0] = vec[0][0] + (deltax > 0 ? dist : -dist);
- }
- else {
- vec[1][0] = vec[0][0];
- vec[1][1] = vec[0][1] + (deltay > 0 ? dist : -dist);
- }
- }
- else {
- vec[1][0] = vec[0][0] + dist;
- vec[1][1] = vec[0][1];
- }
- if (toreroute) {
- if (fabsf(deltax) > fabsf(deltay)) {
- vec[2][1] = vec[3][1];
- vec[2][0] = vec[3][0] + (deltax > 0 ? -dist : dist);
- }
- else {
- vec[2][0] = vec[3][0];
- vec[2][1] = vec[3][1] + (deltay > 0 ? -dist : dist);
- }
- }
- else {
- vec[2][0] = vec[3][0] - dist;
- vec[2][1] = vec[3][1];
- }
+
+ vec[1][0] = vec[0][0] + dist;
+ vec[1][1] = vec[0][1];
+
+ vec[2][0] = vec[3][0] - dist;
+ vec[2][1] = vec[3][1];
if (v2d && min_ffff(vec[0][0], vec[1][0], vec[2][0], vec[3][0]) > v2d->cur.xmax) {
return false; /* clipped */
diff --git a/source/blender/editors/space_node/node_draw.cc b/source/blender/editors/space_node/node_draw.cc
index 7f0c426922b..4ab81bac9aa 100644
--- a/source/blender/editors/space_node/node_draw.cc
+++ b/source/blender/editors/space_node/node_draw.cc
@@ -69,6 +69,7 @@
#include "NOD_geometry_nodes_eval_log.hh"
#include "NOD_node_declaration.hh"
+#include "FN_field.hh"
#include "FN_field_cpp_type.hh"
#include "node_intern.hh" /* own include */
@@ -2574,20 +2575,14 @@ static void reroute_node_draw(
if (node.label[0] != '\0') {
/* draw title (node label) */
BLI_strncpy(showname, node.label, sizeof(showname));
- uiDefBut(&block,
- UI_BTYPE_LABEL,
- 0,
- showname,
- (int)(rct.xmin - NODE_DYS),
- (int)(rct.ymax),
- (short)512,
- (short)NODE_DY,
- nullptr,
- 0,
- 0,
- 0,
- 0,
- nullptr);
+ const short width = 512;
+ const int x = BLI_rctf_cent_x(&node.totr) - (width / 2);
+ const int y = node.totr.ymax;
+
+ uiBut *label_but = uiDefBut(
+ &block, UI_BTYPE_LABEL, 0, showname, x, y, width, (short)NODE_DY, NULL, 0, 0, 0, 0, NULL);
+
+ UI_but_drawflag_disable(label_but, UI_BUT_TEXT_LEFT);
}
/* only draw input socket. as they all are placed on the same position.
diff --git a/source/blender/editors/space_node/node_geometry_attribute_search.cc b/source/blender/editors/space_node/node_geometry_attribute_search.cc
index 5a6fe911a05..2536496b50d 100644
--- a/source/blender/editors/space_node/node_geometry_attribute_search.cc
+++ b/source/blender/editors/space_node/node_geometry_attribute_search.cc
@@ -14,11 +14,13 @@
#include "DNA_space_types.h"
#include "BKE_context.h"
+#include "BKE_node_tree_update.h"
#include "BKE_object.h"
#include "RNA_access.h"
#include "RNA_enum_types.h"
+#include "ED_node.h"
#include "ED_screen.h"
#include "ED_undo.h"
@@ -38,14 +40,66 @@ using geo_log::GeometryAttributeInfo;
namespace blender::ed::space_node {
struct AttributeSearchData {
- const bNodeTree *tree;
- const bNode *node;
- bNodeSocket *socket;
+ char node_name[MAX_NAME];
+ char socket_identifier[MAX_NAME];
};
/* This class must not have a destructor, since it is used by buttons and freed with #MEM_freeN. */
BLI_STATIC_ASSERT(std::is_trivially_destructible_v<AttributeSearchData>, "");
+static Vector<const GeometryAttributeInfo *> get_attribute_info_from_context(
+ const bContext &C, AttributeSearchData &data)
+{
+ SpaceNode *snode = CTX_wm_space_node(&C);
+ if (!snode) {
+ BLI_assert_unreachable();
+ return {};
+ }
+ bNodeTree *node_tree = snode->edittree;
+ if (node_tree == nullptr) {
+ BLI_assert_unreachable();
+ return {};
+ }
+ bNode *node = nodeFindNodebyName(node_tree, data.node_name);
+ if (node == nullptr) {
+ BLI_assert_unreachable();
+ return {};
+ }
+
+ /* For the attribute input node, collect attribute information from all nodes in the group. */
+ if (node->type == GEO_NODE_INPUT_NAMED_ATTRIBUTE) {
+ const geo_log::TreeLog *tree_log = geo_log::ModifierLog::find_tree_by_node_editor_context(
+ *snode);
+ if (tree_log == nullptr) {
+ return {};
+ }
+
+ Vector<const GeometryAttributeInfo *> attributes;
+ Set<StringRef> names;
+ tree_log->foreach_node_log([&](const geo_log::NodeLog &node_log) {
+ for (const geo_log::SocketLog &socket_log : node_log.input_logs()) {
+ const geo_log::ValueLog *value_log = socket_log.value();
+ if (const geo_log::GeometryValueLog *geo_value_log =
+ dynamic_cast<const geo_log::GeometryValueLog *>(value_log)) {
+ for (const GeometryAttributeInfo &attribute : geo_value_log->attributes()) {
+ if (names.add(attribute.name)) {
+ attributes.append(&attribute);
+ }
+ }
+ }
+ }
+ });
+ return attributes;
+ }
+
+ const geo_log::NodeLog *node_log = geo_log::ModifierLog::find_node_by_node_editor_context(
+ *snode, data.node_name);
+ if (node_log == nullptr) {
+ return {};
+ }
+ return node_log->lookup_available_attributes();
+}
+
static void attribute_search_update_fn(
const bContext *C, void *arg, const char *str, uiSearchItems *items, const bool is_first)
{
@@ -55,15 +109,45 @@ static void attribute_search_update_fn(
AttributeSearchData *data = static_cast<AttributeSearchData *>(arg);
- SpaceNode *snode = CTX_wm_space_node(C);
- const geo_log::NodeLog *node_log = geo_log::ModifierLog::find_node_by_node_editor_context(
- *snode, *data->node);
- if (node_log == nullptr) {
- return;
+ Vector<const GeometryAttributeInfo *> infos = get_attribute_info_from_context(*C, *data);
+
+ /* Remove the deprecated normal attribute from the search. */
+ for (const int i : infos.index_range()) {
+ if (infos[i]->domain == ATTR_DOMAIN_FACE && infos[i]->name == "normal") {
+ infos.remove(i);
+ break;
+ }
}
- blender::Vector<const GeometryAttributeInfo *> infos = node_log->lookup_available_attributes();
- blender::ui::attribute_search_add_items(str, true, infos, items, is_first);
+ ui::attribute_search_add_items(str, true, infos, items, is_first);
+}
+
+/**
+ * Some custom data types don't correspond to node types and therefore can't be
+ * used by the named attribute input node. Find the best option or fallback to float.
+ */
+static CustomDataType data_type_in_attribute_input_node(const CustomDataType type)
+{
+ switch (type) {
+ case CD_PROP_FLOAT:
+ case CD_PROP_INT32:
+ case CD_PROP_FLOAT3:
+ case CD_PROP_COLOR:
+ case CD_PROP_BOOL:
+ return type;
+ case CD_MLOOPCOL:
+ return CD_PROP_COLOR;
+ case CD_PROP_STRING:
+ /* Unsupported currently. */
+ return CD_PROP_FLOAT;
+ case CD_PROP_FLOAT2:
+ /* No 2D vector sockets currently. */
+ return CD_PROP_FLOAT3;
+ case CD_PROP_INT8:
+ return CD_PROP_INT32;
+ default:
+ return CD_PROP_FLOAT;
+ }
}
static void attribute_search_exec_fn(bContext *C, void *data_v, void *item_v)
@@ -71,21 +155,62 @@ static void attribute_search_exec_fn(bContext *C, void *data_v, void *item_v)
if (ED_screen_animation_playing(CTX_wm_manager(C))) {
return;
}
- if (item_v == nullptr) {
+ GeometryAttributeInfo *item = (GeometryAttributeInfo *)item_v;
+ if (item == nullptr) {
+ return;
+ }
+ SpaceNode *snode = CTX_wm_space_node(C);
+ if (!snode) {
+ BLI_assert_unreachable();
+ return;
+ }
+ bNodeTree *node_tree = snode->edittree;
+ if (node_tree == nullptr) {
+ BLI_assert_unreachable();
return;
}
AttributeSearchData *data = static_cast<AttributeSearchData *>(data_v);
- GeometryAttributeInfo *item = (GeometryAttributeInfo *)item_v;
+ bNode *node = nodeFindNodebyName(node_tree, data->node_name);
+ if (node == nullptr) {
+ BLI_assert_unreachable();
+ return;
+ }
+ bNodeSocket *socket = bke::node_find_enabled_input_socket(*node, data->socket_identifier);
+ if (socket == nullptr) {
+ BLI_assert_unreachable();
+ return;
+ }
+ BLI_assert(socket->type == SOCK_STRING);
+
+ /* For the attribute input node, also adjust the type and links connected to the output. */
+ if (node->type == GEO_NODE_INPUT_NAMED_ATTRIBUTE) {
+ NodeGeometryInputNamedAttribute &storage = *(NodeGeometryInputNamedAttribute *)node->storage;
+ const CustomDataType new_type = data_type_in_attribute_input_node(item->data_type);
+ if (new_type != storage.data_type) {
+ storage.data_type = new_type;
+ /* Make the output socket with the new type on the attribute input node active. */
+ node->typeinfo->updatefunc(node_tree, node);
+
+ /* Relink all node links to the newly active output socket. */
+ bNodeSocket *output_socket = bke::node_find_enabled_output_socket(*node, "Attribute");
+ LISTBASE_FOREACH (bNodeLink *, link, &node_tree->links) {
+ if (link->fromnode == node) {
+ link->fromsock = output_socket;
+ BKE_ntree_update_tag_link_changed(node_tree);
+ }
+ }
+ }
+ BKE_ntree_update_tag_node_property(node_tree, node);
+ ED_node_tree_propagate_change(C, CTX_data_main(C), node_tree);
+ }
- bNodeSocket &socket = *data->socket;
- bNodeSocketValueString *value = static_cast<bNodeSocketValueString *>(socket.default_value);
+ bNodeSocketValueString *value = static_cast<bNodeSocketValueString *>(socket->default_value);
BLI_strncpy(value->value, item->name.c_str(), MAX_NAME);
ED_undo_push(C, "Assign Attribute Name");
}
void node_geometry_add_attribute_search_button(const bContext &UNUSED(C),
- const bNodeTree &node_tree,
const bNode &node,
PointerRNA &socket_ptr,
uiLayout &layout)
@@ -109,8 +234,10 @@ void node_geometry_add_attribute_search_button(const bContext &UNUSED(C),
0.0f,
"");
- AttributeSearchData *data = MEM_new<AttributeSearchData>(
- __func__, AttributeSearchData{&node_tree, &node, (bNodeSocket *)socket_ptr.data});
+ const bNodeSocket &socket = *static_cast<const bNodeSocket *>(socket_ptr.data);
+ AttributeSearchData *data = MEM_new<AttributeSearchData>(__func__);
+ BLI_strncpy(data->node_name, node.name, sizeof(data->node_name));
+ BLI_strncpy(data->socket_identifier, socket.identifier, sizeof(data->socket_identifier));
UI_but_func_search_set_results_are_suggestions(but, true);
UI_but_func_search_set_sep_string(but, UI_MENU_ARROW_SEP);
diff --git a/source/blender/editors/space_node/node_group.cc b/source/blender/editors/space_node/node_group.cc
index 789476a8179..160a379d3c6 100644
--- a/source/blender/editors/space_node/node_group.cc
+++ b/source/blender/editors/space_node/node_group.cc
@@ -841,6 +841,12 @@ static void node_group_make_insert_selected(const bContext &C, bNodeTree &ntree,
nodeRemLink(&ntree, link);
}
else if (toselect && !fromselect) {
+ /* Remove hidden links to not create unconnected sockets in the interface. */
+ if (nodeLinkIsHidden(link)) {
+ nodeRemLink(&ntree, link);
+ continue;
+ }
+
bNodeSocket *link_sock;
bNode *link_node;
node_socket_skip_reroutes(&ntree.links, link->tonode, link->tosock, &link_node, &link_sock);
@@ -861,6 +867,12 @@ static void node_group_make_insert_selected(const bContext &C, bNodeTree &ntree,
link->tosock = node_group_find_input_socket(gnode, iosock->identifier);
}
else if (fromselect && !toselect) {
+ /* Remove hidden links to not create unconnected sockets in the interface. */
+ if (nodeLinkIsHidden(link)) {
+ nodeRemLink(&ntree, link);
+ continue;
+ }
+
/* First check whether the source of this link is already connected to an output.
* If yes, reuse that output instead of duplicating it. */
bool connected = false;
diff --git a/source/blender/editors/space_node/node_intern.hh b/source/blender/editors/space_node/node_intern.hh
index cd40573607d..44163cd5ae3 100644
--- a/source/blender/editors/space_node/node_intern.hh
+++ b/source/blender/editors/space_node/node_intern.hh
@@ -353,7 +353,6 @@ void NODE_GGT_backdrop_corner_pin(wmGizmoGroupType *gzgt);
/* node_geometry_attribute_search.cc */
void node_geometry_add_attribute_search_button(const bContext &C,
- const bNodeTree &node_tree,
const bNode &node,
PointerRNA &socket_ptr,
uiLayout &layout);
diff --git a/source/blender/editors/space_node/node_templates.cc b/source/blender/editors/space_node/node_templates.cc
index b63cb2eeee5..e92e0571157 100644
--- a/source/blender/editors/space_node/node_templates.cc
+++ b/source/blender/editors/space_node/node_templates.cc
@@ -884,7 +884,7 @@ static void ui_node_draw_input(
if (node_tree->type == NTREE_GEOMETRY && snode != nullptr) {
/* Only add the attribute search in the node editor, in other places there is not
* enough context. */
- node_geometry_add_attribute_search_button(*C, *node_tree, *node, inputptr, *row);
+ node_geometry_add_attribute_search_button(*C, *node, inputptr, *row);
}
else {
uiItemR(sub, &inputptr, "default_value", 0, "", ICON_NONE);
diff --git a/source/blender/editors/space_outliner/CMakeLists.txt b/source/blender/editors/space_outliner/CMakeLists.txt
index b57525854d6..fae0e4be2a8 100644
--- a/source/blender/editors/space_outliner/CMakeLists.txt
+++ b/source/blender/editors/space_outliner/CMakeLists.txt
@@ -38,7 +38,8 @@ set(SRC
tree/tree_display_data.cc
tree/tree_display_libraries.cc
tree/tree_display_orphaned.cc
- tree/tree_display_override_library.cc
+ tree/tree_display_override_library_properties.cc
+ tree/tree_display_override_library_hierarchies.cc
tree/tree_display_scenes.cc
tree/tree_display_sequencer.cc
tree/tree_display_view_layer.cc
diff --git a/source/blender/editors/space_outliner/outliner_collections.cc b/source/blender/editors/space_outliner/outliner_collections.cc
index a4ff44512ef..8ca2ffe6a9c 100644
--- a/source/blender/editors/space_outliner/outliner_collections.cc
+++ b/source/blender/editors/space_outliner/outliner_collections.cc
@@ -354,7 +354,7 @@ void outliner_collection_delete(
else {
LISTBASE_FOREACH (CollectionParent *, cparent, &collection->parents) {
Collection *parent = cparent->collection;
- if (ID_IS_LINKED(parent)) {
+ if (ID_IS_LINKED(parent) || ID_IS_OVERRIDE_LIBRARY(parent)) {
skip = true;
break;
}
@@ -366,7 +366,7 @@ void outliner_collection_delete(
ID *scene_owner = id_type->owner_get(bmain, &parent->id);
BLI_assert(GS(scene_owner->name) == ID_SCE);
- if (ID_IS_LINKED(scene_owner)) {
+ if (ID_IS_LINKED(scene_owner) || ID_IS_OVERRIDE_LIBRARY(scene_owner)) {
skip = true;
break;
}
@@ -603,7 +603,9 @@ static int collection_duplicate_exec(bContext *C, wmOperator *op)
if (ID_IS_LINKED(scene_owner) || ID_IS_OVERRIDE_LIBRARY(scene_owner)) {
scene_owner = CTX_data_scene(C);
- parent = ID_IS_LINKED(scene_owner) ? nullptr : scene_owner->master_collection;
+ parent = (ID_IS_LINKED(scene_owner) || ID_IS_OVERRIDE_LIBRARY(scene_owner)) ?
+ nullptr :
+ scene_owner->master_collection;
}
}
@@ -1293,6 +1295,7 @@ static bool collection_disable_render_poll(bContext *C)
static int collection_flag_exec(bContext *C, wmOperator *op)
{
+ Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
ViewLayer *view_layer = CTX_data_view_layer(C);
SpaceOutliner *space_outliner = CTX_wm_space_outliner(C);
@@ -1319,7 +1322,7 @@ static int collection_flag_exec(bContext *C, wmOperator *op)
LayerCollection *layer_collection = reinterpret_cast<LayerCollection *>(
BLI_gsetIterator_getKey(&collections_to_edit_iter));
Collection *collection = layer_collection->collection;
- if (ID_IS_LINKED(collection)) {
+ if (!BKE_id_is_editable(bmain, &collection->id)) {
continue;
}
if (clear) {
@@ -1347,7 +1350,7 @@ static int collection_flag_exec(bContext *C, wmOperator *op)
GSET_ITER (collections_to_edit_iter, data.collections_to_edit) {
Collection *collection = reinterpret_cast<Collection *>(
BLI_gsetIterator_getKey(&collections_to_edit_iter));
- if (ID_IS_LINKED(collection)) {
+ if (!BKE_id_is_editable(bmain, &collection->id)) {
continue;
}
@@ -1600,7 +1603,7 @@ static int outliner_color_tag_set_exec(bContext *C, wmOperator *op)
if (collection == scene->master_collection) {
continue;
}
- if (ID_IS_LINKED(collection)) {
+ if (!BKE_id_is_editable(CTX_data_main(C), &collection->id)) {
BKE_report(op->reports, RPT_WARNING, "Can't add a color tag to a linked collection");
continue;
}
diff --git a/source/blender/editors/space_outliner/outliner_dragdrop.cc b/source/blender/editors/space_outliner/outliner_dragdrop.cc
index 30b81b2ecb2..88640210ea3 100644
--- a/source/blender/editors/space_outliner/outliner_dragdrop.cc
+++ b/source/blender/editors/space_outliner/outliner_dragdrop.cc
@@ -22,6 +22,7 @@
#include "BKE_collection.h"
#include "BKE_context.h"
#include "BKE_layer.h"
+#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_material.h"
#include "BKE_object.h"
@@ -374,7 +375,7 @@ static void parent_drop_set_parents(bContext *C,
Object *object = (Object *)drag_id->id;
/* Do nothing to linked data */
- if (ID_IS_LINKED(object)) {
+ if (!BKE_id_is_editable(bmain, &object->id)) {
linked_objects = true;
continue;
}
@@ -387,7 +388,7 @@ static void parent_drop_set_parents(bContext *C,
}
if (linked_objects) {
- BKE_report(reports, RPT_INFO, "Can't edit library linked object(s)");
+ BKE_report(reports, RPT_INFO, "Can't edit library linked or non-editable override object(s)");
}
if (parent_set) {
@@ -556,7 +557,7 @@ static int scene_drop_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent
Scene *scene = (Scene *)outliner_ID_drop_find(C, event, ID_SCE);
Object *ob = (Object *)WM_drag_get_local_ID_from_event(event, ID_OB);
- if (ELEM(nullptr, ob, scene) || ID_IS_LINKED(scene)) {
+ if (ELEM(nullptr, ob, scene) || !BKE_id_is_editable(bmain, &scene->id)) {
return OPERATOR_CANCELLED;
}
@@ -748,7 +749,7 @@ static bool datastack_drop_init(bContext *C, const wmEvent *event, StackDropData
ob = nullptr;
}
- if (ob && ID_IS_LINKED(&ob->id)) {
+ if (ob && !BKE_id_is_editable(CTX_data_main(C), &ob->id)) {
return false;
}
@@ -1107,8 +1108,8 @@ struct CollectionDrop {
static Collection *collection_parent_from_ID(ID *id)
{
- /* Can't change linked parent collections. */
- if (!id || ID_IS_LINKED(id)) {
+ /* Can't change linked or override parent collections. */
+ if (!id || ID_IS_LINKED(id) || ID_IS_OVERRIDE_LIBRARY(id)) {
return nullptr;
}
@@ -1134,7 +1135,7 @@ static bool collection_drop_init(
}
Collection *to_collection = outliner_collection_from_tree_element(te);
- if (ID_IS_LINKED(to_collection)) {
+ if (ID_IS_LINKED(to_collection) || ID_IS_OVERRIDE_LIBRARY(to_collection)) {
return false;
}
diff --git a/source/blender/editors/space_outliner/outliner_draw.cc b/source/blender/editors/space_outliner/outliner_draw.cc
index 9857abb3da7..d204e12b41d 100644
--- a/source/blender/editors/space_outliner/outliner_draw.cc
+++ b/source/blender/editors/space_outliner/outliner_draw.cc
@@ -2165,8 +2165,10 @@ static void outliner_draw_mode_column_toggle(uiBlock *block,
/* Mode toggling handles its own undo state because undo steps need to be grouped. */
UI_but_flag_disable(but, UI_BUT_UNDO);
- if (ID_IS_LINKED(&ob->id)) {
- UI_but_disable(but, TIP_("Can't edit external library data"));
+ if (ID_IS_LINKED(&ob->id) ||
+ (ID_IS_OVERRIDE_LIBRARY_REAL(ob) &&
+ (ob->id.override_library->flag & IDOVERRIDE_LIBRARY_FLAG_SYSTEM_DEFINED) != 0)) {
+ UI_but_disable(but, TIP_("Can't edit library or non-editable override data"));
}
}
@@ -3897,6 +3899,12 @@ void draw_outliner(const bContext *C)
/* Default to no emboss for outliner UI. */
UI_block_emboss_set(block, UI_EMBOSS_NONE_OR_STATUS);
+ if (space_outliner->outlinevis == SO_OVERRIDES_LIBRARY) {
+ /* Draw overrides status columns. */
+ outliner_draw_overrides_warning_buts(
+ block, region, space_outliner, &space_outliner->tree, true);
+ }
+
if (space_outliner->outlinevis == SO_DATA_API) {
int buttons_start_x = outliner_data_api_buttons_start_x(tree_width);
/* draw rna buttons */
@@ -3911,11 +3919,8 @@ void draw_outliner(const bContext *C)
/* draw user toggle columns */
outliner_draw_userbuts(block, region, space_outliner, &space_outliner->tree);
}
- else if (space_outliner->outlinevis == SO_OVERRIDES_LIBRARY) {
- /* Draw overrides status columns. */
- outliner_draw_overrides_warning_buts(
- block, region, space_outliner, &space_outliner->tree, true);
-
+ else if ((space_outliner->outlinevis == SO_OVERRIDES_LIBRARY) &&
+ (space_outliner->lib_override_view_mode == SO_LIB_OVERRIDE_VIEW_PROPERTIES)) {
UI_block_emboss_set(block, UI_EMBOSS);
UI_block_flag_enable(block, UI_BLOCK_NO_DRAW_OVERRIDDEN_STATE);
const int x = region->v2d.cur.xmax - right_column_width;
diff --git a/source/blender/editors/space_outliner/outliner_edit.cc b/source/blender/editors/space_outliner/outliner_edit.cc
index ae67e7108bf..d6c5901b546 100644
--- a/source/blender/editors/space_outliner/outliner_edit.cc
+++ b/source/blender/editors/space_outliner/outliner_edit.cc
@@ -30,6 +30,7 @@
#include "BKE_context.h"
#include "BKE_idtype.h"
#include "BKE_lib_id.h"
+#include "BKE_lib_override.h"
#include "BKE_lib_query.h"
#include "BKE_lib_remap.h"
#include "BKE_main.h"
diff --git a/source/blender/editors/space_outliner/outliner_select.cc b/source/blender/editors/space_outliner/outliner_select.cc
index a202ded6deb..fd0ee422df0 100644
--- a/source/blender/editors/space_outliner/outliner_select.cc
+++ b/source/blender/editors/space_outliner/outliner_select.cc
@@ -31,6 +31,7 @@
#include "BKE_gpencil.h"
#include "BKE_gpencil_modifier.h"
#include "BKE_layer.h"
+#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_modifier.h"
#include "BKE_object.h"
@@ -116,8 +117,8 @@ static void do_outliner_item_posemode_toggle(bContext *C, Scene *scene, Base *ba
Main *bmain = CTX_data_main(C);
Object *ob = base->object;
- if (ID_IS_LINKED(ob)) {
- BKE_report(CTX_wm_reports(C), RPT_WARNING, "Cannot pose libdata");
+ if (!BKE_id_is_editable(CTX_data_main(C), &ob->id)) {
+ BKE_report(CTX_wm_reports(C), RPT_WARNING, "Cannot pose non-editable data");
return;
}
diff --git a/source/blender/editors/space_outliner/outliner_tools.cc b/source/blender/editors/space_outliner/outliner_tools.cc
index 0aea4521204..22e42c762ca 100644
--- a/source/blender/editors/space_outliner/outliner_tools.cc
+++ b/source/blender/editors/space_outliner/outliner_tools.cc
@@ -31,6 +31,7 @@
#include "BLI_blenlib.h"
#include "BLI_ghash.h"
+#include "BLI_set.hh"
#include "BLI_utildefines.h"
#include "BKE_anim_data.h"
@@ -46,6 +47,7 @@
#include "BKE_lib_id.h"
#include "BKE_lib_override.h"
#include "BKE_lib_query.h"
+#include "BKE_lib_remap.h"
#include "BKE_main.h"
#include "BKE_object.h"
#include "BKE_report.h"
@@ -87,6 +89,8 @@ static CLG_LogRef LOG = {"ed.outliner.tools"};
using namespace blender::ed::outliner;
+using blender::Set;
+
/* -------------------------------------------------------------------- */
/** \name ID/Library/Data Set/Un-link Utilities
* \{ */
@@ -755,8 +759,50 @@ struct OutlinerLibOverrideData {
* instead of re-applying relevant existing ID pointer property override operations. Helps
* solving broken overrides while not losing *all* of your overrides. */
bool do_resync_hierarchy_enforce;
+
+ /** The override hierarchy root, when known/created. */
+ ID *id_hierarchy_root_override;
+
+ /** A hash of the selected tree elements' ID 'uuid'. Used to clear 'system override' flags on
+ * their newly-created liboverrides in post-process step of override hierarchy creation. */
+ Set<uint> selected_id_uid;
};
+/* Store 'UUID' of IDs of selected elements in the Outliner tree, before generating the override
+ * hierarchy. */
+static void id_override_library_create_hierarchy_pre_process_fn(bContext *UNUSED(C),
+ ReportList *UNUSED(reports),
+ Scene *UNUSED(scene),
+ TreeElement *UNUSED(te),
+ TreeStoreElem *UNUSED(tsep),
+ TreeStoreElem *tselem,
+ void *user_data)
+{
+ BLI_assert(TSE_IS_REAL_ID(tselem));
+
+ OutlinerLibOverrideData *data = reinterpret_cast<OutlinerLibOverrideData *>(user_data);
+ const bool do_hierarchy = data->do_hierarchy;
+ ID *id_root_reference = tselem->id;
+
+ BLI_assert(do_hierarchy);
+ UNUSED_VARS_NDEBUG(do_hierarchy);
+
+ data->selected_id_uid.add(id_root_reference->session_uuid);
+
+ if (GS(id_root_reference->name) == ID_GR && (tselem->flag & TSE_CLOSED) != 0) {
+ /* If selected element is a (closed) collection, check all of its objects recursively, and also
+ * consider the armature ones as 'selected' (i.e. to not become system overrides). */
+ Collection *root_collection = reinterpret_cast<Collection *>(id_root_reference);
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN (root_collection, object_iter) {
+ if (id_root_reference->lib == object_iter->id.lib && object_iter->type == OB_ARMATURE) {
+ printf("Foooo\n");
+ data->selected_id_uid.add(object_iter->id.session_uuid);
+ }
+ }
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
+ }
+}
+
static void id_override_library_create_fn(bContext *C,
ReportList *reports,
Scene *scene,
@@ -782,7 +828,7 @@ static void id_override_library_create_fn(bContext *C,
bool is_override_instancing_object = false;
if (tsep != nullptr && tsep->type == TSE_SOME_ID && tsep->id != nullptr &&
GS(tsep->id->name) == ID_OB && !ID_IS_OVERRIDE_LIBRARY(tsep->id)) {
- Object *ob = (Object *)tsep->id;
+ Object *ob = reinterpret_cast<Object *>(tsep->id);
if (ob->type == OB_EMPTY && &ob->instance_collection->id == id_root_reference) {
BLI_assert(GS(id_root_reference->name) == ID_GR);
/* Empty instantiating the collection we override, we need to pass it to BKE overriding code
@@ -895,6 +941,7 @@ static void id_override_library_create_fn(bContext *C,
return;
}
+ ID *id_root_override = nullptr;
success = BKE_lib_override_library_create(bmain,
CTX_data_scene(C),
CTX_data_view_layer(C),
@@ -902,7 +949,22 @@ static void id_override_library_create_fn(bContext *C,
id_root_reference,
id_hierarchy_root_reference,
id_instance_hint,
- nullptr);
+ &id_root_override);
+
+ BLI_assert(id_root_override != nullptr);
+ BLI_assert(!ID_IS_LINKED(id_root_override));
+ BLI_assert(ID_IS_OVERRIDE_LIBRARY_REAL(id_root_override));
+ if (ID_IS_LINKED(id_hierarchy_root_reference)) {
+ BLI_assert(
+ id_root_override->override_library->hierarchy_root->override_library->reference ==
+ id_hierarchy_root_reference);
+ data->id_hierarchy_root_override = id_root_override->override_library->hierarchy_root;
+ }
+ else {
+ BLI_assert(id_root_override->override_library->hierarchy_root ==
+ id_hierarchy_root_reference);
+ data->id_hierarchy_root_override = id_root_override->override_library->hierarchy_root;
+ }
}
else if (ID_IS_OVERRIDABLE_LIBRARY(id_root_reference)) {
success = BKE_lib_override_library_create_from_id(bmain, id_root_reference, true) != nullptr;
@@ -926,6 +988,44 @@ static void id_override_library_create_fn(bContext *C,
}
}
+/* Clear system override flag from newly created overrides which linked reference were previously
+ * selected in the Outliner tree. */
+static void id_override_library_create_hierarchy_post_process(bContext *C,
+ OutlinerLibOverrideData *data)
+{
+ Main *bmain = CTX_data_main(C);
+ ID *id_hierarchy_root_override = data->id_hierarchy_root_override;
+
+ ID *id_iter;
+ FOREACH_MAIN_ID_BEGIN (bmain, id_iter) {
+ if (ID_IS_LINKED(id_iter) || !ID_IS_OVERRIDE_LIBRARY_REAL(id_iter) ||
+ id_iter->override_library->hierarchy_root != id_hierarchy_root_override) {
+ continue;
+ }
+ if (data->selected_id_uid.contains(id_iter->override_library->reference->session_uuid)) {
+ id_iter->override_library->flag &= ~IDOVERRIDE_LIBRARY_FLAG_SYSTEM_DEFINED;
+ }
+ }
+ FOREACH_MAIN_ID_END;
+}
+
+static void id_override_library_toggle_flag_fn(bContext *UNUSED(C),
+ ReportList *UNUSED(reports),
+ Scene *UNUSED(scene),
+ TreeElement *UNUSED(te),
+ TreeStoreElem *UNUSED(tsep),
+ TreeStoreElem *tselem,
+ void *user_data)
+{
+ BLI_assert(TSE_IS_REAL_ID(tselem));
+ ID *id = tselem->id;
+
+ if (ID_IS_OVERRIDE_LIBRARY_REAL(id)) {
+ const uint flag = POINTER_AS_UINT(user_data);
+ id->override_library->flag ^= flag;
+ }
+}
+
static void id_override_library_reset_fn(bContext *C,
ReportList *UNUSED(reports),
Scene *UNUSED(scene),
@@ -943,10 +1043,10 @@ static void id_override_library_reset_fn(bContext *C,
Main *bmain = CTX_data_main(C);
if (do_hierarchy) {
- BKE_lib_override_library_id_hierarchy_reset(bmain, id_root);
+ BKE_lib_override_library_id_hierarchy_reset(bmain, id_root, false);
}
else {
- BKE_lib_override_library_id_reset(bmain, id_root);
+ BKE_lib_override_library_id_reset(bmain, id_root, false);
}
WM_event_add_notifier(C, NC_WM | ND_DATACHANGED, nullptr);
@@ -998,40 +1098,76 @@ static void id_override_library_resync_fn(bContext *C,
}
}
-static void id_override_library_delete_fn(bContext *C,
- ReportList *UNUSED(reports),
- Scene *UNUSED(scene),
- TreeElement *te,
- TreeStoreElem *UNUSED(tsep),
- TreeStoreElem *tselem,
- void *UNUSED(user_data))
+static void id_override_library_clear_hierarchy_fn(bContext *C,
+ ReportList *UNUSED(reports),
+ Scene *UNUSED(scene),
+ TreeElement *te,
+ TreeStoreElem *UNUSED(tsep),
+ TreeStoreElem *tselem,
+ void *UNUSED(user_data))
{
BLI_assert(TSE_IS_REAL_ID(tselem));
ID *id_root = tselem->id;
- if (ID_IS_OVERRIDE_LIBRARY_REAL(id_root)) {
- Main *bmain = CTX_data_main(C);
+ if (!ID_IS_OVERRIDE_LIBRARY_REAL(id_root)) {
+ CLOG_WARN(&LOG, "Could not delete library override of data block '%s'", id_root->name);
+ return;
+ }
- id_root->tag |= LIB_TAG_DOIT;
+ Main *bmain = CTX_data_main(C);
- /* Tag all linked parents in tree hierarchy to be also overridden. */
- while ((te = te->parent) != nullptr) {
- if (!TSE_IS_REAL_ID(te->store_elem)) {
- continue;
- }
- if (!ID_IS_OVERRIDE_LIBRARY_REAL(te->store_elem->id)) {
- break;
- }
- te->store_elem->id->tag |= LIB_TAG_DOIT;
+ id_root->tag |= LIB_TAG_DOIT;
+
+ /* Tag all override parents in tree hierarchy to be also processed. */
+ while ((te = te->parent) != nullptr) {
+ if (!TSE_IS_REAL_ID(te->store_elem)) {
+ continue;
}
+ if (!ID_IS_OVERRIDE_LIBRARY_REAL(te->store_elem->id)) {
+ break;
+ }
+ te->store_elem->id->tag |= LIB_TAG_DOIT;
+ }
- BKE_lib_override_library_delete(bmain, id_root);
+ BKE_lib_override_library_delete(bmain, id_root);
- WM_event_add_notifier(C, NC_WINDOW, nullptr);
+ WM_event_add_notifier(C, NC_WINDOW, nullptr);
+}
+
+static void id_override_library_clear_single_fn(bContext *C,
+ ReportList *reports,
+ Scene *UNUSED(scene),
+ TreeElement *UNUSED(te),
+ TreeStoreElem *UNUSED(tsep),
+ TreeStoreElem *tselem,
+ void *UNUSED(user_data))
+{
+ BLI_assert(TSE_IS_REAL_ID(tselem));
+ Main *bmain = CTX_data_main(C);
+ ID *id = tselem->id;
+
+ if (!ID_IS_OVERRIDE_LIBRARY_REAL(id)) {
+ BKE_reportf(reports,
+ RPT_WARNING,
+ "Cannot clear embedded library override id '%s', only overrides of real "
+ "data-blocks can be directly deleted",
+ id->name);
+ return;
+ }
+
+ /* If given ID is not using any other override (it's a 'leaf' in the override hierarchy),
+ * delete it and remap its usages to its linked reference. Otherwise, keep it as a reset system
+ * override. */
+ if (BKE_lib_override_library_is_hierarchy_leaf(bmain, id)) {
+ BKE_libblock_remap(bmain, id, id->override_library->reference, ID_REMAP_SKIP_INDIRECT_USAGE);
+ BKE_id_delete(bmain, id);
}
else {
- CLOG_WARN(&LOG, "Could not delete library override of data block '%s'", id_root->name);
+ BKE_lib_override_library_id_reset(bmain, id, true);
}
+
+ WM_event_add_notifier(C, NC_WINDOW, nullptr);
+ return;
}
static void id_fake_user_set_fn(bContext *UNUSED(C),
@@ -1829,11 +1965,13 @@ enum eOutlinerIdOpTypes {
OUTLINER_IDOP_LOCAL,
OUTLINER_IDOP_OVERRIDE_LIBRARY_CREATE,
OUTLINER_IDOP_OVERRIDE_LIBRARY_CREATE_HIERARCHY,
+ OUTLINER_IDOP_OVERRIDE_LIBRARY_MAKE_EDITABLE,
OUTLINER_IDOP_OVERRIDE_LIBRARY_RESET,
OUTLINER_IDOP_OVERRIDE_LIBRARY_RESET_HIERARCHY,
OUTLINER_IDOP_OVERRIDE_LIBRARY_RESYNC_HIERARCHY,
OUTLINER_IDOP_OVERRIDE_LIBRARY_RESYNC_HIERARCHY_ENFORCE,
- OUTLINER_IDOP_OVERRIDE_LIBRARY_DELETE_HIERARCHY,
+ OUTLINER_IDOP_OVERRIDE_LIBRARY_CLEAR_HIERARCHY,
+ OUTLINER_IDOP_OVERRIDE_LIBRARY_CLEAR_SINGLE,
OUTLINER_IDOP_SINGLE,
OUTLINER_IDOP_DELETE,
OUTLINER_IDOP_REMAP,
@@ -1872,6 +2010,11 @@ static const EnumPropertyItem prop_id_op_types[] = {
"Make Library Override Hierarchy",
"Make a local override of this linked data-block, and its hierarchy of dependencies - only "
"applies to active Outliner item"},
+ {OUTLINER_IDOP_OVERRIDE_LIBRARY_MAKE_EDITABLE,
+ "OVERRIDE_LIBRARY_MAKE_EDITABLE",
+ 0,
+ "Make Library Override Editable",
+ "Make the library override data-block editable"},
{OUTLINER_IDOP_OVERRIDE_LIBRARY_RESET,
"OVERRIDE_LIBRARY_RESET",
0,
@@ -1895,12 +2038,18 @@ static const EnumPropertyItem prop_id_op_types[] = {
"Rebuild this local override from its linked reference, as well as its hierarchy of "
"dependencies, enforcing that hierarchy to match the linked data (i.e. ignoring exiting "
"overrides on data-blocks pointer properties)"},
- {OUTLINER_IDOP_OVERRIDE_LIBRARY_DELETE_HIERARCHY,
- "OVERRIDE_LIBRARY_DELETE_HIERARCHY",
+ {OUTLINER_IDOP_OVERRIDE_LIBRARY_CLEAR_HIERARCHY,
+ "OVERRIDE_LIBRARY_CLEAR_HIERARCHY",
0,
- "Delete Library Override Hierarchy",
+ "Clear Library Override Hierarchy",
"Delete this local override (including its hierarchy of override dependencies) and relink "
"its usages to the linked data-blocks"},
+ {OUTLINER_IDOP_OVERRIDE_LIBRARY_CLEAR_SINGLE,
+ "OVERRIDE_LIBRARY_CLEAR_SINGLE",
+ 0,
+ "Clear Single Library Override",
+ "Delete this local override if possible, else reset it and mark it as non editable, and "
+ "relink its usages to the linked data-blocks"},
{0, "", 0, nullptr, nullptr},
{OUTLINER_IDOP_COPY, "COPY", ICON_COPYDOWN, "Copy", ""},
{OUTLINER_IDOP_PASTE, "PASTE", ICON_PASTEDOWN, "Paste", ""},
@@ -1944,11 +2093,19 @@ static bool outliner_id_operation_item_poll(bContext *C,
return true;
}
return false;
+ case OUTLINER_IDOP_OVERRIDE_LIBRARY_MAKE_EDITABLE:
+ if (ID_IS_OVERRIDE_LIBRARY_REAL(tselem->id) && !ID_IS_LINKED(tselem->id)) {
+ if (tselem->id->override_library->flag & IDOVERRIDE_LIBRARY_FLAG_SYSTEM_DEFINED) {
+ return true;
+ }
+ }
+ return false;
case OUTLINER_IDOP_OVERRIDE_LIBRARY_RESET:
case OUTLINER_IDOP_OVERRIDE_LIBRARY_RESET_HIERARCHY:
case OUTLINER_IDOP_OVERRIDE_LIBRARY_RESYNC_HIERARCHY:
case OUTLINER_IDOP_OVERRIDE_LIBRARY_RESYNC_HIERARCHY_ENFORCE:
- case OUTLINER_IDOP_OVERRIDE_LIBRARY_DELETE_HIERARCHY:
+ case OUTLINER_IDOP_OVERRIDE_LIBRARY_CLEAR_HIERARCHY:
+ case OUTLINER_IDOP_OVERRIDE_LIBRARY_CLEAR_SINGLE:
if (ID_IS_OVERRIDE_LIBRARY_REAL(tselem->id) && !ID_IS_LINKED(tselem->id)) {
return true;
}
@@ -2115,11 +2272,32 @@ static int outliner_id_operation_exec(bContext *C, wmOperator *op)
scene,
space_outliner,
&space_outliner->tree,
+ id_override_library_create_hierarchy_pre_process_fn,
+ &override_data);
+ outliner_do_libdata_operation(C,
+ op->reports,
+ scene,
+ space_outliner,
+ &space_outliner->tree,
id_override_library_create_fn,
&override_data);
+ id_override_library_create_hierarchy_post_process(C, &override_data);
+
ED_undo_push(C, "Overridden Data Hierarchy");
break;
}
+ case OUTLINER_IDOP_OVERRIDE_LIBRARY_MAKE_EDITABLE: {
+ outliner_do_libdata_operation(C,
+ op->reports,
+ scene,
+ space_outliner,
+ &space_outliner->tree,
+ id_override_library_toggle_flag_fn,
+ POINTER_FROM_UINT(IDOVERRIDE_LIBRARY_FLAG_SYSTEM_DEFINED));
+
+ ED_undo_push(C, "Make Overridden Data Editable");
+ break;
+ }
case OUTLINER_IDOP_OVERRIDE_LIBRARY_RESET: {
OutlinerLibOverrideData override_data{};
outliner_do_libdata_operation(C,
@@ -2172,17 +2350,26 @@ static int outliner_id_operation_exec(bContext *C, wmOperator *op)
ED_undo_push(C, "Resync Overridden Data Hierarchy");
break;
}
- case OUTLINER_IDOP_OVERRIDE_LIBRARY_DELETE_HIERARCHY: {
- OutlinerLibOverrideData override_data{};
- override_data.do_hierarchy = true;
+ case OUTLINER_IDOP_OVERRIDE_LIBRARY_CLEAR_HIERARCHY: {
outliner_do_libdata_operation(C,
op->reports,
scene,
space_outliner,
&space_outliner->tree,
- id_override_library_delete_fn,
- &override_data);
- ED_undo_push(C, "Delete Overridden Data Hierarchy");
+ id_override_library_clear_hierarchy_fn,
+ nullptr);
+ ED_undo_push(C, "Clear Overridden Data Hierarchy");
+ break;
+ }
+ case OUTLINER_IDOP_OVERRIDE_LIBRARY_CLEAR_SINGLE: {
+ outliner_do_libdata_operation(C,
+ op->reports,
+ scene,
+ space_outliner,
+ &space_outliner->tree,
+ id_override_library_clear_single_fn,
+ nullptr);
+ ED_undo_push(C, "Clear Overridden Data Hierarchy");
break;
}
case OUTLINER_IDOP_SINGLE: {
diff --git a/source/blender/editors/space_outliner/outliner_tree.cc b/source/blender/editors/space_outliner/outliner_tree.cc
index 19fe40b612e..bbd9b48c260 100644
--- a/source/blender/editors/space_outliner/outliner_tree.cc
+++ b/source/blender/editors/space_outliner/outliner_tree.cc
@@ -712,7 +712,8 @@ static void outliner_add_id_contents(SpaceOutliner *space_outliner,
else {
/* do not extend Armature when we have posemode */
tselem = TREESTORE(te->parent);
- if (GS(tselem->id->name) == ID_OB && ((Object *)tselem->id)->mode & OB_MODE_POSE) {
+ if (TSE_IS_REAL_ID(tselem) && GS(tselem->id->name) == ID_OB &&
+ ((Object *)tselem->id)->mode & OB_MODE_POSE) {
/* pass */
}
else {
diff --git a/source/blender/editors/space_outliner/outliner_utils.cc b/source/blender/editors/space_outliner/outliner_utils.cc
index ed5a2108d3c..7526cc7ef5c 100644
--- a/source/blender/editors/space_outliner/outliner_utils.cc
+++ b/source/blender/editors/space_outliner/outliner_utils.cc
@@ -324,6 +324,9 @@ float outliner_right_columns_width(const SpaceOutliner *space_outliner)
case SO_LIBRARIES:
return 0.0f;
case SO_OVERRIDES_LIBRARY:
+ if (space_outliner->lib_override_view_mode != SO_LIB_OVERRIDE_VIEW_PROPERTIES) {
+ return 0.0f;
+ }
num_columns = OL_RNA_COL_SIZEX / UI_UNIT_X;
break;
case SO_ID_ORPHANS:
diff --git a/source/blender/editors/space_outliner/tree/tree_display.cc b/source/blender/editors/space_outliner/tree/tree_display.cc
index f9141dffd6a..141c68594e8 100644
--- a/source/blender/editors/space_outliner/tree/tree_display.cc
+++ b/source/blender/editors/space_outliner/tree/tree_display.cc
@@ -30,7 +30,13 @@ std::unique_ptr<AbstractTreeDisplay> AbstractTreeDisplay::createFromDisplayMode(
case SO_ID_ORPHANS:
return std::make_unique<TreeDisplayIDOrphans>(space_outliner);
case SO_OVERRIDES_LIBRARY:
- return std::make_unique<TreeDisplayOverrideLibrary>(space_outliner);
+ switch ((eSpaceOutliner_LibOverrideViewMode)space_outliner.lib_override_view_mode) {
+ case SO_LIB_OVERRIDE_VIEW_PROPERTIES:
+ return std::make_unique<TreeDisplayOverrideLibraryProperties>(space_outliner);
+ case SO_LIB_OVERRIDE_VIEW_HIERARCHIES:
+ return std::make_unique<TreeDisplayOverrideLibraryHierarchies>(space_outliner);
+ }
+ break;
case SO_VIEW_LAYER:
return std::make_unique<TreeDisplayViewLayer>(space_outliner);
}
diff --git a/source/blender/editors/space_outliner/tree/tree_display.hh b/source/blender/editors/space_outliner/tree/tree_display.hh
index a60d3339042..327f29aa15e 100644
--- a/source/blender/editors/space_outliner/tree/tree_display.hh
+++ b/source/blender/editors/space_outliner/tree/tree_display.hh
@@ -35,6 +35,8 @@ struct ViewLayer;
namespace blender::ed::outliner {
+class TreeElementID;
+
/**
* \brief The data to build the tree from.
*/
@@ -127,11 +129,11 @@ class TreeDisplayLibraries final : public AbstractTreeDisplay {
/* Library Overrides Tree-Display. */
/**
- * \brief Tree-Display for the Library Overrides display mode.
+ * \brief Tree-Display for the Library Overrides display mode, Properties view mode.
*/
-class TreeDisplayOverrideLibrary final : public AbstractTreeDisplay {
+class TreeDisplayOverrideLibraryProperties final : public AbstractTreeDisplay {
public:
- TreeDisplayOverrideLibrary(SpaceOutliner &space_outliner);
+ TreeDisplayOverrideLibraryProperties(SpaceOutliner &space_outliner);
ListBase buildTree(const TreeSourceData &source_data) override;
@@ -140,6 +142,22 @@ class TreeDisplayOverrideLibrary final : public AbstractTreeDisplay {
short id_filter_get() const;
};
+/**
+ * \brief Tree-Display for the Library Overrides display mode, Hierarchies view mode.
+ */
+class TreeDisplayOverrideLibraryHierarchies final : public AbstractTreeDisplay {
+ public:
+ TreeDisplayOverrideLibraryHierarchies(SpaceOutliner &space_outliner);
+
+ ListBase buildTree(const TreeSourceData &source_data) override;
+
+ private:
+ ListBase build_hierarchy_for_lib_or_main(Main *bmain,
+ TreeElement &parent_te,
+ Library *lib = nullptr);
+ void build_hierarchy_for_ID(Main *bmain, ID &override_root_id, TreeElementID &te_id) const;
+};
+
/* -------------------------------------------------------------------- */
/* Video Sequencer Tree-Display */
diff --git a/source/blender/editors/space_outliner/tree/tree_display_override_library_hierarchies.cc b/source/blender/editors/space_outliner/tree/tree_display_override_library_hierarchies.cc
new file mode 100644
index 00000000000..4b568a6004d
--- /dev/null
+++ b/source/blender/editors/space_outliner/tree/tree_display_override_library_hierarchies.cc
@@ -0,0 +1,224 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+/** \file
+ * \ingroup spoutliner
+ */
+
+#include "DNA_ID.h"
+#include "DNA_collection_types.h"
+#include "DNA_key_types.h"
+#include "DNA_space_types.h"
+
+#include "BLI_listbase.h"
+#include "BLI_map.hh"
+#include "BLI_set.hh"
+
+#include "BLT_translation.h"
+
+#include "BKE_collection.h"
+#include "BKE_lib_query.h"
+#include "BKE_main.h"
+
+#include "../outliner_intern.hh"
+#include "common.hh"
+#include "tree_display.hh"
+#include "tree_element_id.hh"
+
+namespace blender::ed::outliner {
+
+class AbstractTreeElement;
+
+TreeDisplayOverrideLibraryHierarchies::TreeDisplayOverrideLibraryHierarchies(
+ SpaceOutliner &space_outliner)
+ : AbstractTreeDisplay(space_outliner)
+{
+}
+
+/* XXX Remove expanded subtree, we add our own items here. Expanding should probably be
+ * optional. */
+static void remove_expanded_children(TreeElement &te)
+{
+ outliner_free_tree(&te.subtree);
+}
+
+ListBase TreeDisplayOverrideLibraryHierarchies::buildTree(const TreeSourceData &source_data)
+{
+ ListBase tree = {nullptr};
+
+ /* First step: Build "Current File" hierarchy. */
+ TreeElement *current_file_te = outliner_add_element(
+ &space_outliner_, &tree, source_data.bmain, nullptr, TSE_ID_BASE, -1);
+ current_file_te->name = IFACE_("Current File");
+ {
+ AbstractTreeElement::uncollapse_by_default(current_file_te);
+ build_hierarchy_for_lib_or_main(source_data.bmain, *current_file_te);
+
+ /* Add dummy child if there's nothing to display. */
+ if (BLI_listbase_is_empty(&current_file_te->subtree)) {
+ TreeElement *dummy_te = outliner_add_element(
+ &space_outliner_, &current_file_te->subtree, nullptr, current_file_te, TSE_ID_BASE, 0);
+ dummy_te->name = IFACE_("No Library Overrides");
+ }
+ }
+
+ /* Second step: Build hierarchies for external libraries. */
+ for (Library *lib = (Library *)source_data.bmain->libraries.first; lib;
+ lib = (Library *)lib->id.next) {
+ TreeElement *tenlib = outliner_add_element(
+ &space_outliner_, &tree, lib, nullptr, TSE_SOME_ID, 0);
+ build_hierarchy_for_lib_or_main(source_data.bmain, *tenlib, lib);
+ }
+
+ /* Remove top level library elements again that don't contain any overrides. */
+ LISTBASE_FOREACH_MUTABLE (TreeElement *, top_level_te, &tree) {
+ if (top_level_te == current_file_te) {
+ continue;
+ }
+
+ if (BLI_listbase_is_empty(&top_level_te->subtree)) {
+ outliner_free_tree_element(top_level_te, &tree);
+ }
+ }
+
+ return tree;
+}
+
+ListBase TreeDisplayOverrideLibraryHierarchies::build_hierarchy_for_lib_or_main(
+ Main *bmain, TreeElement &parent_te, Library *lib)
+{
+ ListBase tree = {nullptr};
+
+ /* Keep track over which ID base elements were already added, and expand them once added. */
+ Map<ID_Type, TreeElement *> id_base_te_map;
+ /* Index for the ID base elements ("Objects", "Materials", etc). */
+ int base_index = 0;
+
+ ID *iter_id;
+ FOREACH_MAIN_ID_BEGIN (bmain, iter_id) {
+ if (!ID_IS_OVERRIDE_LIBRARY_REAL(iter_id) || !ID_IS_OVERRIDE_LIBRARY_HIERARCHY_ROOT(iter_id)) {
+ continue;
+ }
+ if (iter_id->lib != lib) {
+ continue;
+ }
+
+ TreeElement *new_base_te = id_base_te_map.lookup_or_add_cb(GS(iter_id->name), [&]() {
+ TreeElement *new_te = outliner_add_element(&space_outliner_,
+ &parent_te.subtree,
+ lib ? (void *)lib : bmain,
+ &parent_te,
+ TSE_ID_BASE,
+ base_index++);
+ new_te->name = outliner_idcode_to_plural(GS(iter_id->name));
+ return new_te;
+ });
+
+ TreeElement *new_id_te = outliner_add_element(
+ &space_outliner_, &new_base_te->subtree, iter_id, new_base_te, TSE_SOME_ID, 0);
+ remove_expanded_children(*new_id_te);
+
+ build_hierarchy_for_ID(bmain, *iter_id, *tree_element_cast<TreeElementID>(new_id_te));
+ }
+ FOREACH_MAIN_ID_END;
+
+ return tree;
+}
+
+struct BuildHierarchyForeachIDCbData {
+ /* Don't allow copies, the sets below would need deep copying. */
+ BuildHierarchyForeachIDCbData(const BuildHierarchyForeachIDCbData &) = delete;
+
+ Main &bmain;
+ SpaceOutliner &space_outliner;
+ ID &override_root_id;
+
+ /* The tree element to expand. Changes with every level of recursion. */
+ TreeElementID *parent_te;
+ /* The ancestor IDs leading to the current ID, to avoid IDs recursing into themselves. Changes
+ * with every level of recursion. */
+ Set<ID *> parent_ids{};
+ /* The IDs that were already added to #parent_te, to avoid duplicates. Entirely new set with
+ * every level of recursion. */
+ Set<ID *> sibling_ids{};
+};
+
+static int build_hierarchy_foreach_ID_cb(LibraryIDLinkCallbackData *cb_data)
+{
+ if (!*cb_data->id_pointer) {
+ return IDWALK_RET_NOP;
+ }
+
+ BuildHierarchyForeachIDCbData &build_data = *reinterpret_cast<BuildHierarchyForeachIDCbData *>(
+ cb_data->user_data);
+ /* Note that this may be an embedded ID (see #real_override_id). */
+ ID &id = **cb_data->id_pointer;
+ /* If #id is an embedded ID, this will be set to the owner, which is a real ID and contains the
+ * override data. So queries of override data should be done via this, but the actual tree
+ * element we add is the embedded ID. */
+ const ID *real_override_id = &id;
+
+ if (ID_IS_OVERRIDE_LIBRARY_VIRTUAL(&id)) {
+ if (GS(id.name) == ID_KE) {
+ Key *key = (Key *)&id;
+ real_override_id = key->from;
+ }
+ else if (id.flag & LIB_EMBEDDED_DATA) {
+ /* TODO Needs double-checking if this handles all embedded IDs correctly. */
+ real_override_id = cb_data->id_owner;
+ }
+ }
+
+ if (!ID_IS_OVERRIDE_LIBRARY(real_override_id)) {
+ return IDWALK_RET_NOP;
+ }
+ /* Is this ID part of the same override hierarchy? */
+ if (real_override_id->override_library->hierarchy_root != &build_data.override_root_id) {
+ return IDWALK_RET_NOP;
+ }
+
+ /* Avoid endless recursion: If there is an ancestor for this ID already, it recurses into itself.
+ */
+ if (build_data.parent_ids.lookup_key_default(&id, nullptr)) {
+ return IDWALK_RET_NOP;
+ }
+
+ /* Avoid duplicates: If there is a sibling for this ID already, the same ID is just used multiple
+ * times by the same parent. */
+ if (build_data.sibling_ids.lookup_key_default(&id, nullptr)) {
+ return IDWALK_RET_NOP;
+ }
+
+ TreeElement *new_te = outliner_add_element(&build_data.space_outliner,
+ &build_data.parent_te->getLegacyElement().subtree,
+ &id,
+ &build_data.parent_te->getLegacyElement(),
+ TSE_SOME_ID,
+ 0);
+ remove_expanded_children(*new_te);
+ build_data.sibling_ids.add(&id);
+
+ BuildHierarchyForeachIDCbData child_build_data{build_data.bmain,
+ build_data.space_outliner,
+ build_data.override_root_id,
+ tree_element_cast<TreeElementID>(new_te)};
+ child_build_data.parent_ids = build_data.parent_ids;
+ child_build_data.parent_ids.add(&id);
+ child_build_data.sibling_ids.reserve(10);
+ BKE_library_foreach_ID_link(
+ &build_data.bmain, &id, build_hierarchy_foreach_ID_cb, &child_build_data, IDWALK_READONLY);
+
+ return IDWALK_RET_NOP;
+}
+
+void TreeDisplayOverrideLibraryHierarchies::build_hierarchy_for_ID(Main *bmain,
+ ID &override_root_id,
+ TreeElementID &te_id) const
+{
+ BuildHierarchyForeachIDCbData build_data{*bmain, space_outliner_, override_root_id, &te_id};
+ build_data.parent_ids.add(&override_root_id);
+
+ BKE_library_foreach_ID_link(
+ bmain, &te_id.get_ID(), build_hierarchy_foreach_ID_cb, &build_data, IDWALK_READONLY);
+}
+
+} // namespace blender::ed::outliner
diff --git a/source/blender/editors/space_outliner/tree/tree_display_override_library.cc b/source/blender/editors/space_outliner/tree/tree_display_override_library_properties.cc
index b5c0a10c834..4c57f91a0a7 100644
--- a/source/blender/editors/space_outliner/tree/tree_display_override_library.cc
+++ b/source/blender/editors/space_outliner/tree/tree_display_override_library_properties.cc
@@ -25,12 +25,12 @@ namespace blender::ed::outliner {
/* Convenience/readability. */
template<typename T> using List = ListBaseWrapper<T>;
-TreeDisplayOverrideLibrary::TreeDisplayOverrideLibrary(SpaceOutliner &space_outliner)
+TreeDisplayOverrideLibraryProperties::TreeDisplayOverrideLibraryProperties(SpaceOutliner &space_outliner)
: AbstractTreeDisplay(space_outliner)
{
}
-ListBase TreeDisplayOverrideLibrary::buildTree(const TreeSourceData &source_data)
+ListBase TreeDisplayOverrideLibraryProperties::buildTree(const TreeSourceData &source_data)
{
ListBase tree = add_library_contents(*source_data.bmain);
@@ -44,7 +44,7 @@ ListBase TreeDisplayOverrideLibrary::buildTree(const TreeSourceData &source_data
return tree;
}
-ListBase TreeDisplayOverrideLibrary::add_library_contents(Main &mainvar)
+ListBase TreeDisplayOverrideLibraryProperties::add_library_contents(Main &mainvar)
{
ListBase tree = {nullptr};
@@ -69,7 +69,7 @@ ListBase TreeDisplayOverrideLibrary::add_library_contents(Main &mainvar)
/* check if there's data in current id list */
for (ID *id_iter : List<ID>(lbarray[a])) {
- if (ID_IS_OVERRIDE_LIBRARY_REAL(id_iter)) {
+ if (ID_IS_OVERRIDE_LIBRARY_REAL(id_iter) && !ID_IS_LINKED(id_iter)) {
id = id_iter;
break;
}
@@ -93,7 +93,7 @@ ListBase TreeDisplayOverrideLibrary::add_library_contents(Main &mainvar)
}
for (ID *id : List<ID>(lbarray[a])) {
- if (ID_IS_OVERRIDE_LIBRARY_REAL(id)) {
+ if (ID_IS_OVERRIDE_LIBRARY_REAL(id) && !ID_IS_LINKED(id)) {
TreeElement *override_tree_element = outliner_add_element(
&space_outliner_, lb_to_expand, id, id_base_te, TSE_LIBRARY_OVERRIDE_BASE, 0);
@@ -114,7 +114,7 @@ ListBase TreeDisplayOverrideLibrary::add_library_contents(Main &mainvar)
return tree;
}
-short TreeDisplayOverrideLibrary::id_filter_get() const
+short TreeDisplayOverrideLibraryProperties::id_filter_get() const
{
if (space_outliner_.filter & SO_FILTER_ID_TYPE) {
return space_outliner_.filter_id_type;
diff --git a/source/blender/editors/space_outliner/tree/tree_element.cc b/source/blender/editors/space_outliner/tree/tree_element.cc
index ca67aad00db..7fe3f08b3be 100644
--- a/source/blender/editors/space_outliner/tree/tree_element.cc
+++ b/source/blender/editors/space_outliner/tree/tree_element.cc
@@ -98,6 +98,13 @@ std::unique_ptr<AbstractTreeElement> AbstractTreeElement::createFromType(const i
return nullptr;
}
+void AbstractTreeElement::uncollapse_by_default(TreeElement *legacy_te)
+{
+ if (!TREESTORE(legacy_te)->used) {
+ TREESTORE(legacy_te)->flag &= ~TSE_CLOSED;
+ }
+}
+
void tree_element_expand(const AbstractTreeElement &tree_element, SpaceOutliner &space_outliner)
{
/* Most types can just expand. IDs optionally expand (hence the poll) and do additional, common
diff --git a/source/blender/editors/space_outliner/tree/tree_element.hh b/source/blender/editors/space_outliner/tree/tree_element.hh
index 6f2d803ae96..c6593a517dd 100644
--- a/source/blender/editors/space_outliner/tree/tree_element.hh
+++ b/source/blender/editors/space_outliner/tree/tree_element.hh
@@ -50,6 +50,19 @@ class AbstractTreeElement {
return true;
}
+ TreeElement &getLegacyElement()
+ {
+ return legacy_te_;
+ }
+
+ /**
+ * Expand this tree element if it is displayed for the first time (as identified by its
+ * tree-store element).
+ *
+ * Static for now to allow doing this from the legacy tree element.
+ */
+ static void uncollapse_by_default(TreeElement *legacy_te);
+
friend void tree_element_expand(const AbstractTreeElement &tree_element,
SpaceOutliner &space_outliner);
diff --git a/source/blender/editors/space_outliner/tree/tree_element_id.hh b/source/blender/editors/space_outliner/tree/tree_element_id.hh
index b7519fe06f9..c2bbfd9f107 100644
--- a/source/blender/editors/space_outliner/tree/tree_element_id.hh
+++ b/source/blender/editors/space_outliner/tree/tree_element_id.hh
@@ -35,6 +35,11 @@ class TreeElementID : public AbstractTreeElement {
return false;
}
+ ID &get_ID()
+ {
+ return id_;
+ }
+
protected:
/* ID types with animation data can use this. */
void expand_animation_data(SpaceOutliner &, const AnimData *) const;
diff --git a/source/blender/editors/space_sequencer/sequencer_edit.c b/source/blender/editors/space_sequencer/sequencer_edit.c
index 3ccdf701a86..283bd99cd5d 100644
--- a/source/blender/editors/space_sequencer/sequencer_edit.c
+++ b/source/blender/editors/space_sequencer/sequencer_edit.c
@@ -1643,35 +1643,6 @@ void SEQUENCER_OT_split(struct wmOperatorType *ot)
/** \name Duplicate Strips Operator
* \{ */
-static void sequencer_backup_original_animation(Scene *scene, ListBase *list)
-{
- if (scene->adt == NULL || scene->adt->action == NULL ||
- BLI_listbase_is_empty(&scene->adt->action->curves)) {
- return;
- }
-
- BLI_movelisttolist(list, &scene->adt->action->curves);
-}
-
-static void sequencer_restore_original_animation(Scene *scene, ListBase *list)
-{
- if (scene->adt == NULL || scene->adt->action == NULL || BLI_listbase_is_empty(list)) {
- return;
- }
-
- BLI_movelisttolist(&scene->adt->action->curves, list);
-}
-
-static void sequencer_duplicate_animation(Scene *scene, Sequence *seq, ListBase *curves_backup)
-{
- GSet *fcurves = SEQ_fcurves_by_strip_get(seq, curves_backup);
- GSET_FOREACH_BEGIN (FCurve *, fcu, fcurves) {
- FCurve *fcu_cpy = BKE_fcurve_copy(fcu);
- BLI_addtail(&scene->adt->action->curves, fcu_cpy);
- }
- GSET_FOREACH_END();
-}
-
static int sequencer_add_duplicate_exec(bContext *C, wmOperator *UNUSED(op))
{
Scene *scene = CTX_data_scene(C);
@@ -1697,7 +1668,7 @@ static int sequencer_add_duplicate_exec(bContext *C, wmOperator *UNUSED(op))
* original curves from backup.
*/
ListBase fcurves_original_backup = {NULL, NULL};
- sequencer_backup_original_animation(scene, &fcurves_original_backup);
+ SEQ_animation_backup_original(scene, &fcurves_original_backup);
Sequence *seq = duplicated_strips.first;
@@ -1712,11 +1683,11 @@ static int sequencer_add_duplicate_exec(bContext *C, wmOperator *UNUSED(op))
SEQ_select_active_set(scene, seq);
}
seq->flag &= ~(SEQ_LEFTSEL + SEQ_RIGHTSEL + SEQ_LOCK);
- sequencer_duplicate_animation(scene, seq, &fcurves_original_backup);
+ SEQ_animation_duplicate(scene, seq, &fcurves_original_backup);
SEQ_ensure_unique_name(seq, scene);
}
- sequencer_restore_original_animation(scene, &fcurves_original_backup);
+ SEQ_animation_restore_original(scene, &fcurves_original_backup);
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
return OPERATOR_FINISHED;
@@ -2622,7 +2593,7 @@ static int sequencer_paste_exec(bContext *C, wmOperator *op)
*/
ListBase fcurves_original_backup = {NULL, NULL};
- sequencer_backup_original_animation(scene, &fcurves_original_backup);
+ SEQ_animation_backup_original(scene, &fcurves_original_backup);
sequencer_paste_animation(C);
/* Copy strips, temporarily restoring pointers to actual data-blocks. This
@@ -2654,7 +2625,7 @@ static int sequencer_paste_exec(bContext *C, wmOperator *op)
}
}
- sequencer_restore_original_animation(scene, &fcurves_original_backup);
+ SEQ_animation_restore_original(scene, &fcurves_original_backup);
DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS);
DEG_relations_tag_update(bmain);
diff --git a/source/blender/editors/space_spreadsheet/spreadsheet_data_source_geometry.cc b/source/blender/editors/space_spreadsheet/spreadsheet_data_source_geometry.cc
index 0ad64db1b6d..4afa70d9ef6 100644
--- a/source/blender/editors/space_spreadsheet/spreadsheet_data_source_geometry.cc
+++ b/source/blender/editors/space_spreadsheet/spreadsheet_data_source_geometry.cc
@@ -4,6 +4,7 @@
#include "BKE_context.h"
#include "BKE_editmesh.h"
+#include "BKE_geometry_fields.hh"
#include "BKE_global.h"
#include "BKE_lib_id.h"
#include "BKE_mesh.h"
diff --git a/source/blender/editors/space_text/text_ops.c b/source/blender/editors/space_text/text_ops.c
index 15fea301b1c..49c0236866d 100644
--- a/source/blender/editors/space_text/text_ops.c
+++ b/source/blender/editors/space_text/text_ops.c
@@ -165,7 +165,7 @@ BLI_INLINE int text_pixel_x_to_column(SpaceText *st, const int x)
static bool text_new_poll(bContext *UNUSED(C))
{
- return 1;
+ return true;
}
static bool text_data_poll(bContext *C)
@@ -182,15 +182,15 @@ static bool text_edit_poll(bContext *C)
Text *text = CTX_data_edit_text(C);
if (!text) {
- return 0;
+ return false;
}
- if (ID_IS_LINKED(text)) {
+ if (!BKE_id_is_editable(CTX_data_main(C), &text->id)) {
// BKE_report(op->reports, RPT_ERROR, "Cannot edit external library data");
- return 0;
+ return false;
}
- return 1;
+ return true;
}
bool text_space_edit_poll(bContext *C)
@@ -199,15 +199,15 @@ bool text_space_edit_poll(bContext *C)
Text *text = CTX_data_edit_text(C);
if (!st || !text) {
- return 0;
+ return false;
}
- if (ID_IS_LINKED(text)) {
+ if (!BKE_id_is_editable(CTX_data_main(C), &text->id)) {
// BKE_report(op->reports, RPT_ERROR, "Cannot edit external library data");
- return 0;
+ return false;
}
- return 1;
+ return true;
}
static bool text_region_edit_poll(bContext *C)
@@ -217,19 +217,19 @@ static bool text_region_edit_poll(bContext *C)
ARegion *region = CTX_wm_region(C);
if (!st || !text) {
- return 0;
+ return false;
}
if (!region || region->regiontype != RGN_TYPE_WINDOW) {
- return 0;
+ return false;
}
- if (ID_IS_LINKED(text)) {
+ if (!BKE_id_is_editable(CTX_data_main(C), &text->id)) {
// BKE_report(op->reports, RPT_ERROR, "Cannot edit external library data");
- return 0;
+ return false;
}
- return 1;
+ return true;
}
/** \} */
diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c
index e2a027837a7..3f2fbb97de1 100644
--- a/source/blender/editors/space_view3d/space_view3d.c
+++ b/source/blender/editors/space_view3d/space_view3d.c
@@ -8,6 +8,7 @@
#include <stdio.h>
#include <string.h>
+#include "DNA_collection_types.h"
#include "DNA_defaults.h"
#include "DNA_gpencil_types.h"
#include "DNA_lightprobe_types.h"
@@ -47,6 +48,7 @@
#include "ED_screen.h"
#include "ED_space_api.h"
#include "ED_transform.h"
+#include "ED_undo.h"
#include "GPU_matrix.h"
@@ -562,6 +564,24 @@ static bool view3d_collection_drop_poll(bContext *C, wmDrag *drag, const wmEvent
return view3d_drop_id_in_main_region_poll(C, drag, event, ID_GR);
}
+static bool view3d_collection_drop_poll_local_id(bContext *C, wmDrag *drag, const wmEvent *event)
+{
+ if (!view3d_collection_drop_poll(C, drag, event) || (drag->type != WM_DRAG_ID)) {
+ return false;
+ }
+ return true;
+}
+
+static bool view3d_collection_drop_poll_external_asset(bContext *C,
+ wmDrag *drag,
+ const wmEvent *event)
+{
+ if (!view3d_collection_drop_poll(C, drag, event) || (drag->type != WM_DRAG_ASSET)) {
+ return false;
+ }
+ return true;
+}
+
static bool view3d_mat_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event)
{
return view3d_drop_id_in_main_region_poll(C, drag, event, ID_MA);
@@ -682,7 +702,7 @@ static void view3d_ob_drop_matrix_from_snap(V3DSnapCursorState *snap_state,
mat4_to_size(scale, ob->obmat);
rescale_m4(obmat_final, scale);
- BoundBox *bb = BKE_object_boundbox_get(ob);
+ const BoundBox *bb = BKE_object_boundbox_get(ob);
if (bb) {
float offset[3];
BKE_boundbox_calc_center_aabb(bb, offset);
@@ -708,6 +728,8 @@ static void view3d_ob_drop_copy_local_id(wmDrag *drag, wmDropBox *drop)
RNA_float_set_array(drop->ptr, "matrix", &obmat_final[0][0]);
}
+/* Mostly the same logic as #view3d_collection_drop_copy_external_asset(), just different enough to
+ * make sharing code a bit difficult. */
static void view3d_ob_drop_copy_external_asset(wmDrag *drag, wmDropBox *drop)
{
/* NOTE(@campbellbarton): Selection is handled here, de-selecting objects before append,
@@ -749,11 +771,48 @@ static void view3d_ob_drop_copy_external_asset(wmDrag *drag, wmDropBox *drop)
}
}
-static void view3d_collection_drop_copy(wmDrag *drag, wmDropBox *drop)
+static void view3d_collection_drop_copy_local_id(wmDrag *drag, wmDropBox *drop)
{
- ID *id = WM_drag_get_local_ID_or_import_from_asset(drag, ID_GR);
+ ID *id = WM_drag_get_local_ID(drag, ID_GR);
+ RNA_int_set(drop->ptr, "session_uuid", (int)id->session_uuid);
+}
+
+/* Mostly the same logic as #view3d_ob_drop_copy_external_asset(), just different enough to make
+ * sharing code a bit difficult. */
+static void view3d_collection_drop_copy_external_asset(wmDrag *drag, wmDropBox *drop)
+{
+ BLI_assert(drag->type == WM_DRAG_ASSET);
+
+ wmDragAsset *asset_drag = WM_drag_get_asset_data(drag, 0);
+ bContext *C = asset_drag->evil_C;
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+
+ BKE_view_layer_base_deselect_all(view_layer);
+
+ ID *id = WM_drag_asset_id_import(asset_drag, FILE_AUTOSELECT);
+ Collection *collection = (Collection *)id;
+
+ /* TODO(sergey): Only update relations for the current scene. */
+ DEG_relations_tag_update(CTX_data_main(C));
+ WM_event_add_notifier(C, NC_SCENE | ND_LAYER_CONTENT, scene);
RNA_int_set(drop->ptr, "session_uuid", (int)id->session_uuid);
+
+ /* Make an object active, just use the first one in the collection. */
+ CollectionObject *cobject = collection->gobject.first;
+ Base *base = cobject ? BKE_view_layer_base_find(view_layer, cobject->ob) : NULL;
+ if (base) {
+ BLI_assert((base->flag & BASE_SELECTABLE) && (base->flag & BASE_ENABLED_VIEWPORT));
+ BKE_view_layer_base_select_and_set_active(view_layer, base);
+ WM_main_add_notifier(NC_SCENE | ND_OB_ACTIVE, scene);
+ }
+ DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
+ ED_outliner_select_sync_from_object_tag(C);
+
+ /* XXX Without an undo push here, there will be a crash when the user modifies operator
+ * properties. The stuff we do in these drop callbacks just isn't safe over undo/redo. */
+ ED_undo_push(C, "Collection_Drop");
}
static void view3d_id_drop_copy(wmDrag *drag, wmDropBox *drop)
@@ -835,6 +894,19 @@ static void view3d_dropboxes(void)
drop->draw_deactivate = view3d_ob_drop_draw_deactivate;
WM_dropbox_add(lb,
+ "OBJECT_OT_collection_external_asset_drop",
+ view3d_collection_drop_poll_external_asset,
+ view3d_collection_drop_copy_external_asset,
+ WM_drag_free_imported_drag_ID,
+ NULL);
+ WM_dropbox_add(lb,
+ "OBJECT_OT_collection_instance_add",
+ view3d_collection_drop_poll_local_id,
+ view3d_collection_drop_copy_local_id,
+ WM_drag_free_imported_drag_ID,
+ NULL);
+
+ WM_dropbox_add(lb,
"OBJECT_OT_drop_named_material",
view3d_mat_drop_poll,
view3d_id_drop_copy,
@@ -859,12 +931,6 @@ static void view3d_dropboxes(void)
WM_drag_free_imported_drag_ID,
NULL);
WM_dropbox_add(lb,
- "OBJECT_OT_collection_instance_add",
- view3d_collection_drop_poll,
- view3d_collection_drop_copy,
- WM_drag_free_imported_drag_ID,
- NULL);
- WM_dropbox_add(lb,
"OBJECT_OT_data_instance_add",
view3d_object_data_drop_poll,
view3d_id_drop_copy_with_type,
diff --git a/source/blender/editors/space_view3d/view3d_cursor_snap.c b/source/blender/editors/space_view3d/view3d_cursor_snap.c
index 53f7b3d5871..f3e45a14565 100644
--- a/source/blender/editors/space_view3d/view3d_cursor_snap.c
+++ b/source/blender/editors/space_view3d/view3d_cursor_snap.c
@@ -620,9 +620,6 @@ static void v3d_cursor_snap_update(V3DSnapCursorState *state,
snap_elements &= ~SCE_SNAP_MODE_EDGE_PERPENDICULAR;
}
- eSnapSelect snap_select = (state->flag & V3D_SNAPCURSOR_SNAP_ONLY_ACTIVE) ? SNAP_ONLY_ACTIVE :
- SNAP_ALL;
-
eSnapEditType edit_mode_type = (state->flag & V3D_SNAPCURSOR_SNAP_EDIT_GEOM_FINAL) ?
SNAP_GEOM_FINAL :
(state->flag & V3D_SNAPCURSOR_SNAP_EDIT_GEOM_CAGE) ?
@@ -640,7 +637,7 @@ static void v3d_cursor_snap_update(V3DSnapCursorState *state,
v3d,
snap_elements,
&(const struct SnapObjectParams){
- .snap_select = snap_select,
+ .snap_select = SNAP_ALL,
.edit_mode_type = edit_mode_type,
.use_occlusion_test = use_occlusion_test,
},
diff --git a/source/blender/editors/space_view3d/view3d_gizmo_camera.c b/source/blender/editors/space_view3d/view3d_gizmo_camera.c
index 4451d629a04..83f589a64c9 100644
--- a/source/blender/editors/space_view3d/view3d_gizmo_camera.c
+++ b/source/blender/editors/space_view3d/view3d_gizmo_camera.c
@@ -11,6 +11,7 @@
#include "BKE_camera.h"
#include "BKE_context.h"
#include "BKE_layer.h"
+#include "BKE_lib_id.h"
#include "DNA_camera_types.h"
#include "DNA_object_types.h"
@@ -61,7 +62,7 @@ static bool WIDGETGROUP_camera_poll(const bContext *C, wmGizmoGroupType *UNUSED(
if (ob->type == OB_CAMERA) {
Camera *camera = ob->data;
/* TODO: support overrides. */
- if (!ID_IS_LINKED(camera)) {
+ if (BKE_id_is_editable(CTX_data_main(C), &camera->id)) {
return true;
}
}
@@ -384,7 +385,7 @@ static bool WIDGETGROUP_camera_view_poll(const bContext *C, wmGizmoGroupType *UN
if (rv3d->persp == RV3D_CAMOB) {
if (scene->r.mode & R_BORDER) {
/* TODO: support overrides. */
- if (!ID_IS_LINKED(scene)) {
+ if (BKE_id_is_editable(CTX_data_main(C), &scene->id)) {
return true;
}
}
diff --git a/source/blender/editors/space_view3d/view3d_navigate_fly.c b/source/blender/editors/space_view3d/view3d_navigate_fly.c
index af78663fff9..399f422f411 100644
--- a/source/blender/editors/space_view3d/view3d_navigate_fly.c
+++ b/source/blender/editors/space_view3d/view3d_navigate_fly.c
@@ -24,6 +24,7 @@
#include "BLI_math.h"
#include "BKE_context.h"
+#include "BKE_lib_id.h"
#include "BKE_report.h"
#include "BLT_translation.h"
@@ -321,8 +322,12 @@ static bool initFlyInfo(bContext *C, FlyInfo *fly, wmOperator *op, const wmEvent
fly->rv3d->persp = RV3D_PERSP;
}
- if (fly->rv3d->persp == RV3D_CAMOB && ID_IS_LINKED(fly->v3d->camera)) {
- BKE_report(op->reports, RPT_ERROR, "Cannot fly a camera from an external library");
+ if (fly->rv3d->persp == RV3D_CAMOB &&
+ !BKE_id_is_editable(CTX_data_main(C), &fly->v3d->camera->id)) {
+ BKE_report(op->reports,
+ RPT_ERROR,
+ "Cannot navigate a camera from an external library or non-editable override");
+
return false;
}
diff --git a/source/blender/editors/space_view3d/view3d_navigate_walk.c b/source/blender/editors/space_view3d/view3d_navigate_walk.c
index 333c99c2fca..18ed88aeec6 100644
--- a/source/blender/editors/space_view3d/view3d_navigate_walk.c
+++ b/source/blender/editors/space_view3d/view3d_navigate_walk.c
@@ -22,6 +22,7 @@
#include "BLI_utildefines.h"
#include "BKE_context.h"
+#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_report.h"
@@ -503,8 +504,11 @@ static bool initWalkInfo(bContext *C, WalkInfo *walk, wmOperator *op)
walk->rv3d->persp = RV3D_PERSP;
}
- if (walk->rv3d->persp == RV3D_CAMOB && ID_IS_LINKED(walk->v3d->camera)) {
- BKE_report(op->reports, RPT_ERROR, "Cannot navigate a camera from an external library");
+ if (walk->rv3d->persp == RV3D_CAMOB &&
+ !BKE_id_is_editable(CTX_data_main(C), &walk->v3d->camera->id)) {
+ BKE_report(op->reports,
+ RPT_ERROR,
+ "Cannot navigate a camera from an external library or non-editable override");
return false;
}
diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.c
index d9388bc82ef..465f890d9f5 100644
--- a/source/blender/editors/space_view3d/view3d_select.c
+++ b/source/blender/editors/space_view3d/view3d_select.c
@@ -1645,9 +1645,7 @@ static int bone_select_menu_exec(bContext *C, wmOperator *op)
const int name_index = RNA_enum_get(op->ptr, "name");
const struct SelectPick_Params params = {
- .sel_op = ED_select_op_from_booleans(RNA_boolean_get(op->ptr, "extend"),
- RNA_boolean_get(op->ptr, "deselect"),
- RNA_boolean_get(op->ptr, "toggle")),
+ .sel_op = ED_select_op_from_operator(op),
};
View3D *v3d = CTX_wm_view3d(C);
@@ -2746,11 +2744,6 @@ static bool ed_object_select_pick(bContext *C,
if (params->sel_op == SEL_OP_SET) {
if ((found && params->select_passthrough) && (basact->flag & BASE_SELECTED)) {
found = false;
- /* NOTE(@campbellbarton): Experimental behavior to set active even keeping the selection
- * without this it's inconvenient to set the active object. */
- if (basact != oldbasact) {
- use_activate_selected_base = true;
- }
}
else if (found || params->deselect_all) {
/* Deselect everything. */
@@ -2922,14 +2915,10 @@ static int view3d_select_exec(bContext *C, wmOperator *op)
Scene *scene = CTX_data_scene(C);
Object *obedit = CTX_data_edit_object(C);
Object *obact = CTX_data_active_object(C);
- const struct SelectPick_Params params = {
- .sel_op = ED_select_op_from_booleans(RNA_boolean_get(op->ptr, "extend"),
- RNA_boolean_get(op->ptr, "deselect"),
- RNA_boolean_get(op->ptr, "toggle")),
- .deselect_all = RNA_boolean_get(op->ptr, "deselect_all"),
- .select_passthrough = RNA_boolean_get(op->ptr, "select_passthrough"),
- };
+ struct SelectPick_Params params = {0};
+ ED_select_pick_params_from_operator(op, &params);
+
bool center = RNA_boolean_get(op->ptr, "center");
bool enumerate = RNA_boolean_get(op->ptr, "enumerate");
/* Only force object select for edit-mode to support vertex parenting,
diff --git a/source/blender/editors/space_view3d/view3d_utils.c b/source/blender/editors/space_view3d/view3d_utils.c
index 3e788f2d643..744fc61ddcf 100644
--- a/source/blender/editors/space_view3d/view3d_utils.c
+++ b/source/blender/editors/space_view3d/view3d_utils.c
@@ -409,9 +409,6 @@ bool ED_view3d_boundbox_clip_ex(const RegionView3D *rv3d, const BoundBox *bb, fl
if (bb == NULL) {
return true;
}
- if (bb->flag & BOUNDBOX_DISABLED) {
- return true;
- }
mul_m4_m4m4(persmatob, (float(*)[4])rv3d->persmat, obmat);
@@ -423,10 +420,6 @@ bool ED_view3d_boundbox_clip(RegionView3D *rv3d, const BoundBox *bb)
if (bb == NULL) {
return true;
}
- if (bb->flag & BOUNDBOX_DISABLED) {
- return true;
- }
-
return view3d_boundbox_clip_m4(bb, rv3d->persmatob);
}
diff --git a/source/blender/editors/space_view3d/view3d_view.c b/source/blender/editors/space_view3d/view3d_view.c
index e7fcc401523..a56bbb1c1df 100644
--- a/source/blender/editors/space_view3d/view3d_view.c
+++ b/source/blender/editors/space_view3d/view3d_view.c
@@ -18,6 +18,7 @@
#include "BKE_gpencil_modifier.h"
#include "BKE_idprop.h"
#include "BKE_layer.h"
+#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_modifier.h"
#include "BKE_object.h"
@@ -84,7 +85,7 @@ static bool view3d_camera_to_view_poll(bContext *C)
if (ED_view3d_context_user_region(C, &v3d, &region)) {
RegionView3D *rv3d = region->regiondata;
- if (v3d && v3d->camera && !ID_IS_LINKED(v3d->camera)) {
+ if (v3d && v3d->camera && BKE_id_is_editable(CTX_data_main(C), &v3d->camera->id)) {
if (rv3d && (RV3D_LOCK_FLAGS(rv3d) & RV3D_LOCK_ANY_TRANSFORM) == 0) {
if (rv3d->persp != RV3D_CAMOB) {
return true;
diff --git a/source/blender/editors/transform/CMakeLists.txt b/source/blender/editors/transform/CMakeLists.txt
index c8033d9d767..68c4f4e76ca 100644
--- a/source/blender/editors/transform/CMakeLists.txt
+++ b/source/blender/editors/transform/CMakeLists.txt
@@ -90,7 +90,7 @@ set(SRC
transform_orientations.c
transform_snap.c
transform_snap_animation.c
- transform_snap_object.c
+ transform_snap_object.cc
transform_snap_sequencer.c
transform.h
diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c
index 975f4370425..4058d77f42f 100644
--- a/source/blender/editors/transform/transform.c
+++ b/source/blender/editors/transform/transform.c
@@ -59,8 +59,6 @@
* and being able to set it to zero is handy. */
/* #define USE_NUM_NO_ZERO */
-static void drawTransformApply(const struct bContext *C, ARegion *region, void *arg);
-
static void initSnapSpatial(TransInfo *t, float r_snap[2]);
bool transdata_check_local_islands(TransInfo *t, short around)
@@ -845,10 +843,6 @@ int transformEvent(TransInfo *t, const wmEvent *event)
handled = true;
}
else if (event->type == MOUSEMOVE) {
- if (t->modifiers & (MOD_CONSTRAINT_SELECT_AXIS | MOD_CONSTRAINT_SELECT_PLANE)) {
- t->con.mode |= CON_SELECT;
- }
-
copy_v2_v2_int(t->mval, event->mval);
/* Use this for soft redraw. Might cause flicker in object mode */
@@ -1097,6 +1091,7 @@ int transformEvent(TransInfo *t, const wmEvent *event)
/* Confirm. */
postSelectConstraint(t);
t->modifiers &= ~(MOD_CONSTRAINT_SELECT_AXIS | MOD_CONSTRAINT_SELECT_PLANE);
+ t->redraw = TREDRAW_HARD;
}
else {
if (t->options & CTX_CAMERA) {
@@ -1108,6 +1103,7 @@ int transformEvent(TransInfo *t, const wmEvent *event)
restoreTransObjects(t);
transform_mode_init(t, NULL, TFM_TRACKBALL);
}
+ t->redraw = TREDRAW_HARD;
}
else {
t->modifiers |= (event->val == TFM_MODAL_AUTOCONSTRAINT) ?
@@ -1116,13 +1112,13 @@ int transformEvent(TransInfo *t, const wmEvent *event)
if (t->con.mode & CON_APPLY) {
stopConstraint(t);
}
- else {
- initSelectConstraint(t);
- postSelectConstraint(t);
- }
+
+ initSelectConstraint(t);
+ /* Use #TREDRAW_SOFT so that #selectConstraint is only called on the next event.
+ * This allows us to "deselect" the constraint. */
+ t->redraw = TREDRAW_SOFT;
}
}
- t->redraw |= TREDRAW_HARD;
handled = true;
}
break;
@@ -1733,8 +1729,6 @@ bool initTransform(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
initTransInfo(C, t, op, event);
if (t->spacetype == SPACE_VIEW3D) {
- t->draw_handle_apply = ED_region_draw_cb_activate(
- t->region->type, drawTransformApply, t, REGION_DRAW_PRE_VIEW);
t->draw_handle_view = ED_region_draw_cb_activate(
t->region->type, drawTransformView, t, REGION_DRAW_POST_VIEW);
t->draw_handle_pixel = ED_region_draw_cb_activate(
@@ -1925,18 +1919,19 @@ void transformApply(bContext *C, TransInfo *t)
{
t->context = C;
- if ((t->redraw & TREDRAW_HARD) || (t->draw_handle_apply == NULL && (t->redraw & TREDRAW_SOFT))) {
+ if (t->redraw == TREDRAW_HARD) {
selectConstraint(t);
if (t->transform) {
t->transform(t, t->mval); /* calls recalcData() */
- viewRedrawForce(C, t);
}
- t->redraw = TREDRAW_NOTHING;
}
- else if (t->redraw & TREDRAW_SOFT) {
+
+ if (t->redraw & TREDRAW_SOFT) {
viewRedrawForce(C, t);
}
+ t->redraw = TREDRAW_NOTHING;
+
/* If auto confirm is on, break after one pass */
if (t->options & CTX_AUTOCONFIRM) {
t->state = TRANS_CONFIRM;
@@ -1945,16 +1940,6 @@ void transformApply(bContext *C, TransInfo *t)
t->context = NULL;
}
-static void drawTransformApply(const bContext *C, ARegion *UNUSED(region), void *arg)
-{
- TransInfo *t = arg;
-
- if (t->redraw & TREDRAW_SOFT) {
- t->redraw |= TREDRAW_HARD;
- transformApply((bContext *)C, t);
- }
-}
-
int transformEnd(bContext *C, TransInfo *t)
{
int exit_code = OPERATOR_RUNNING_MODAL;
diff --git a/source/blender/editors/transform/transform.h b/source/blender/editors/transform/transform.h
index 713cf487ac7..37478dfc187 100644
--- a/source/blender/editors/transform/transform.h
+++ b/source/blender/editors/transform/transform.h
@@ -188,8 +188,8 @@ typedef enum {
/** #TransInfo.redraw */
typedef enum {
TREDRAW_NOTHING = 0,
- TREDRAW_HARD = 1,
- TREDRAW_SOFT = 2,
+ TREDRAW_SOFT = (1 << 0),
+ TREDRAW_HARD = (1 << 1) | TREDRAW_SOFT,
} eRedrawFlag;
/** #TransInfo.helpline */
@@ -663,7 +663,6 @@ typedef struct TransInfo {
int mval[2];
/** use for 3d view. */
float zfac;
- void *draw_handle_apply;
void *draw_handle_view;
void *draw_handle_pixel;
void *draw_handle_cursor;
diff --git a/source/blender/editors/transform/transform_constraints.c b/source/blender/editors/transform/transform_constraints.c
index 81b35e4539b..0bb00032561 100644
--- a/source/blender/editors/transform/transform_constraints.c
+++ b/source/blender/editors/transform/transform_constraints.c
@@ -996,19 +996,10 @@ void selectConstraint(TransInfo *t)
void postSelectConstraint(TransInfo *t)
{
- if (!(t->con.mode & CON_SELECT)) {
- return;
- }
-
- t->con.mode &= ~CON_AXIS0;
- t->con.mode &= ~CON_AXIS1;
- t->con.mode &= ~CON_AXIS2;
t->con.mode &= ~CON_SELECT;
-
- setNearestAxis(t);
-
- startConstraint(t);
- t->redraw = TREDRAW_HARD;
+ if (!(t->con.mode & (CON_AXIS0 | CON_AXIS1 | CON_AXIS2))) {
+ t->con.mode &= ~CON_APPLY;
+ }
}
static void setNearestAxis2d(TransInfo *t)
diff --git a/source/blender/editors/transform/transform_convert_node.c b/source/blender/editors/transform/transform_convert_node.c
index 7a4b03b640c..d5d79bedbf4 100644
--- a/source/blender/editors/transform/transform_convert_node.c
+++ b/source/blender/editors/transform/transform_convert_node.c
@@ -129,6 +129,10 @@ void createTransNodeData(TransInfo *t)
}
}
+ if (tc->data_len == 0) {
+ return;
+ }
+
TransData *td = tc->data = MEM_callocN(tc->data_len * sizeof(TransData), "TransNode TransData");
TransData2D *td2d = tc->data_2d = MEM_callocN(tc->data_len * sizeof(TransData2D),
"TransNode TransData2D");
diff --git a/source/blender/editors/transform/transform_convert_object.c b/source/blender/editors/transform/transform_convert_object.c
index b599e282959..bd6c6bb120f 100644
--- a/source/blender/editors/transform/transform_convert_object.c
+++ b/source/blender/editors/transform/transform_convert_object.c
@@ -13,6 +13,7 @@
#include "BKE_animsys.h"
#include "BKE_context.h"
#include "BKE_layer.h"
+#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_object.h"
#include "BKE_pointcache.h"
@@ -481,6 +482,7 @@ static void clear_trans_object_base_flags(TransInfo *t)
void createTransObject(bContext *C, TransInfo *t)
{
+ Main *bmain = CTX_data_main(C);
TransData *td = NULL;
TransDataExtension *tx;
const bool is_prop_edit = (t->flag & T_PROP_EDIT) != 0;
@@ -527,7 +529,7 @@ void createTransObject(bContext *C, TransInfo *t)
}
/* select linked objects, but skip them later */
- if (ID_IS_LINKED(ob)) {
+ if (!BKE_id_is_editable(bmain, &ob->id)) {
td->flag |= TD_SKIP;
}
diff --git a/source/blender/editors/transform/transform_convert_object_texspace.c b/source/blender/editors/transform/transform_convert_object_texspace.c
index 763af1f3384..1f58ec80f02 100644
--- a/source/blender/editors/transform/transform_convert_object_texspace.c
+++ b/source/blender/editors/transform/transform_convert_object_texspace.c
@@ -63,7 +63,6 @@ void createTransTexspace(TransInfo *t)
}
td->flag = TD_SELECTED;
- copy_v3_v3(td->center, ob->obmat[3]);
td->ob = ob;
copy_m3_m4(td->mtx, ob->obmat);
@@ -77,6 +76,7 @@ void createTransTexspace(TransInfo *t)
}
copy_v3_v3(td->iloc, td->loc);
+ copy_v3_v3(td->center, td->loc);
copy_v3_v3(td->ext->isize, td->ext->size);
}
diff --git a/source/blender/editors/transform/transform_convert_sculpt.c b/source/blender/editors/transform/transform_convert_sculpt.c
index 0c6214668ba..5bf6bfa8644 100644
--- a/source/blender/editors/transform/transform_convert_sculpt.c
+++ b/source/blender/editors/transform/transform_convert_sculpt.c
@@ -10,6 +10,7 @@
#include "BLI_math.h"
#include "BKE_context.h"
+#include "BKE_lib_id.h"
#include "BKE_paint.h"
#include "BKE_report.h"
@@ -27,7 +28,7 @@ void createTransSculpt(bContext *C, TransInfo *t)
TransData *td;
Scene *scene = t->scene;
- if (ID_IS_LINKED(scene)) {
+ if (!BKE_id_is_editable(CTX_data_main(C), &scene->id)) {
BKE_report(t->reports, RPT_ERROR, "Linked data can't text-space transform");
return;
}
@@ -102,7 +103,7 @@ void recalcData_sculpt(TransInfo *t)
void special_aftertrans_update__sculpt(bContext *C, TransInfo *t)
{
Scene *scene = t->scene;
- if (ID_IS_LINKED(scene)) {
+ if (!BKE_id_is_editable(CTX_data_main(C), &scene->id)) {
/* `ED_sculpt_init_transform` was not called in this case. */
return;
}
diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c
index 3b9e2a982dc..975dbc2e986 100644
--- a/source/blender/editors/transform/transform_generics.c
+++ b/source/blender/editors/transform/transform_generics.c
@@ -718,9 +718,6 @@ void postTrans(bContext *C, TransInfo *t)
if (t->draw_handle_view) {
ED_region_draw_cb_exit(t->region->type, t->draw_handle_view);
}
- if (t->draw_handle_apply) {
- ED_region_draw_cb_exit(t->region->type, t->draw_handle_apply);
- }
if (t->draw_handle_pixel) {
ED_region_draw_cb_exit(t->region->type, t->draw_handle_pixel);
}
diff --git a/source/blender/editors/transform/transform_gizmo_3d.c b/source/blender/editors/transform/transform_gizmo_3d.c
index 955916ff437..aa8dad2b95f 100644
--- a/source/blender/editors/transform/transform_gizmo_3d.c
+++ b/source/blender/editors/transform/transform_gizmo_3d.c
@@ -939,7 +939,7 @@ int ED_transform_calc_gizmo_stats(const bContext *C,
for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
Object *ob_iter = objects[ob_index];
- const bool use_mat_local = params->use_local_axis && (ob_iter != ob);
+ const bool use_mat_local = (ob_iter != ob);
/* mislead counting bones... bah. We don't know the gizmo mode, could be mixed */
const int mode = TFM_ROTATION;
@@ -951,7 +951,7 @@ int ED_transform_calc_gizmo_stats(const bContext *C,
}
/* Use channels to get stats. */
- LISTBASE_FOREACH (bPoseChannel *, pchan, &ob->pose->chanbase) {
+ LISTBASE_FOREACH (bPoseChannel *, pchan, &ob_iter->pose->chanbase) {
if (!(pchan->bone->flag & BONE_TRANSFORM)) {
continue;
}
diff --git a/source/blender/editors/transform/transform_snap.c b/source/blender/editors/transform/transform_snap.c
index bf898b9053f..23619a2049a 100644
--- a/source/blender/editors/transform/transform_snap.c
+++ b/source/blender/editors/transform/transform_snap.c
@@ -579,89 +579,97 @@ static char snap_flag_from_spacetype(TransInfo *t)
static short snap_mode_from_spacetype(TransInfo *t)
{
ToolSettings *ts = t->settings;
- short r_snap_mode = SCE_SNAP_MODE_INCREMENT;
if (t->spacetype == SPACE_NODE) {
- r_snap_mode = ts->snap_node_mode;
+ return ts->snap_node_mode;
}
- else if (t->spacetype == SPACE_IMAGE) {
- r_snap_mode = ts->snap_uv_mode;
- if ((r_snap_mode & SCE_SNAP_MODE_INCREMENT) && (ts->snap_uv_flag & SCE_SNAP_ABS_GRID) &&
+
+ if (t->spacetype == SPACE_IMAGE) {
+ short snap_mode = ts->snap_uv_mode;
+ if ((snap_mode & SCE_SNAP_MODE_INCREMENT) && (ts->snap_uv_flag & SCE_SNAP_ABS_GRID) &&
(t->mode == TFM_TRANSLATION)) {
- r_snap_mode &= ~SCE_SNAP_MODE_INCREMENT;
- r_snap_mode |= SCE_SNAP_MODE_GRID;
+ snap_mode &= ~SCE_SNAP_MODE_INCREMENT;
+ snap_mode |= SCE_SNAP_MODE_GRID;
}
+ return snap_mode;
}
- else if (t->spacetype == SPACE_SEQ) {
- r_snap_mode = SEQ_tool_settings_snap_mode_get(t->scene);
+
+ if (t->spacetype == SPACE_SEQ) {
+ return SEQ_tool_settings_snap_mode_get(t->scene);
}
- 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)) ||
- ELEM(obedit_type, OB_MESH, OB_ARMATURE, OB_CURVES_LEGACY, OB_LATTICE, OB_MBALL, -1)) {
- r_snap_mode = ts->snap_mode;
- if ((r_snap_mode & SCE_SNAP_MODE_INCREMENT) && (ts->snap_flag & SCE_SNAP_ABS_GRID) &&
- (t->mode == TFM_TRANSLATION)) {
- /* Special case in which snap to increments is transformed to snap to grid. */
- r_snap_mode &= ~SCE_SNAP_MODE_INCREMENT;
- r_snap_mode |= SCE_SNAP_MODE_GRID;
- }
+
+ if (t->spacetype == SPACE_VIEW3D) {
+ if (t->options & (CTX_CAMERA | CTX_EDGE_DATA | CTX_PAINT_CURVE)) {
+ return SCE_SNAP_MODE_INCREMENT;
}
+
+ short snap_mode = ts->snap_mode;
+ if ((snap_mode & SCE_SNAP_MODE_INCREMENT) && (ts->snap_flag & SCE_SNAP_ABS_GRID) &&
+ (t->mode == TFM_TRANSLATION)) {
+ /* Special case in which snap to increments is transformed to snap to grid. */
+ snap_mode &= ~SCE_SNAP_MODE_INCREMENT;
+ snap_mode |= SCE_SNAP_MODE_GRID;
+ }
+ return snap_mode;
}
- else if (ELEM(t->spacetype, SPACE_ACTION, SPACE_NLA)) {
+
+ if (ELEM(t->spacetype, SPACE_ACTION, SPACE_NLA)) {
/* No incremental snapping. */
- r_snap_mode = 0;
+ return 0;
}
- return r_snap_mode;
+ return SCE_SNAP_MODE_INCREMENT;
}
static short snap_select_type_get(TransInfo *t)
{
- short r_snap_select = SNAP_ALL;
-
ViewLayer *view_layer = t->view_layer;
Base *base_act = view_layer->basact;
if (ELEM(t->spacetype, SPACE_VIEW3D, SPACE_IMAGE) && !(t->options & CTX_CAMERA)) {
- const int obedit_type = t->obedit_type;
if (t->options & (CTX_GPENCIL_STROKES | CTX_CURSOR | CTX_OBMODE_XFORM_OBDATA)) {
/* In "Edit Strokes" mode,
* snap tool can perform snap to selected or active objects (see T49632)
* TODO: perform self snap in gpencil_strokes.
*
* When we're moving the origins, allow snapping onto our own geometry (see T69132). */
+ return SNAP_ALL;
}
- else if ((obedit_type != -1) &&
- ELEM(obedit_type, OB_MESH, OB_ARMATURE, OB_CURVES_LEGACY, OB_LATTICE, OB_MBALL)) {
+
+ const int obedit_type = t->obedit_type;
+ if (obedit_type != -1) {
/* Edit mode */
- /* Temporary limited to edit mode meshes, armature, curves, metaballs. */
+ if (ELEM(obedit_type, OB_MESH, OB_ARMATURE, OB_CURVES_LEGACY, OB_LATTICE, OB_MBALL)) {
+ /* Temporary limited to edit mode meshes, armature, curves, lattice and metaballs. */
- if ((obedit_type == OB_MESH) && (t->flag & T_PROP_EDIT)) {
- /* Exclude editmesh if using proportional edit */
- r_snap_select = SNAP_NOT_ACTIVE;
- }
- else if (!t->tsnap.snap_self) {
- r_snap_select = SNAP_NOT_ACTIVE;
- }
- else {
- r_snap_select = SNAP_NOT_SELECTED;
+ if ((obedit_type == OB_MESH) && (t->flag & T_PROP_EDIT)) {
+ /* Exclude editmesh if using proportional edit */
+ return SNAP_NOT_EDITED;
+ }
+
+ if (!t->tsnap.snap_self) {
+ return SNAP_NOT_ACTIVE;
+ }
+
+ return SNAP_NOT_SELECTED;
}
+
+ return SNAP_ALL;
}
- else if ((obedit_type == -1) && base_act && base_act->object &&
- (base_act->object->mode & OB_MODE_PARTICLE_EDIT)) {
+
+ if (base_act && (base_act->object->mode & OB_MODE_PARTICLE_EDIT)) {
/* Particles edit mode. */
+ return SNAP_ALL;
}
- else if (obedit_type == -1) {
- /* Object or pose mode. */
- r_snap_select = SNAP_NOT_SELECTED;
- }
+
+ /* Object or pose mode. */
+ return SNAP_NOT_SELECTED;
}
- else if (ELEM(t->spacetype, SPACE_NODE, SPACE_SEQ)) {
- r_snap_select = SNAP_NOT_SELECTED;
+
+ if (ELEM(t->spacetype, SPACE_NODE, SPACE_SEQ)) {
+ return SNAP_NOT_SELECTED;
}
- return r_snap_select;
+ return SNAP_ALL;
}
static void initSnappingMode(TransInfo *t)
diff --git a/source/blender/editors/transform/transform_snap_object.c b/source/blender/editors/transform/transform_snap_object.cc
index 87053fe03d1..e879ca2b163 100644
--- a/source/blender/editors/transform/transform_snap_object.c
+++ b/source/blender/editors/transform/transform_snap_object.cc
@@ -4,7 +4,7 @@
* \ingroup edtransform
*/
-#include <stdlib.h>
+#include <cstdlib>
#include "MEM_guardedalloc.h"
@@ -55,11 +55,12 @@ enum eViewProj {
VIEW_PROJ_PERSP = -1,
};
-typedef struct SnapObjectData {
- enum {
- SNAP_MESH = 1,
- SNAP_EDIT_MESH,
- } type;
+struct SnapObjectData {
+ enum class Type {
+ Mesh,
+ EditMesh,
+ };
+ Type type;
BVHTree *bvhtree[2]; /* MESH: loose edges, loose verts
* EDIT_MESH: verts, edges. */
@@ -67,7 +68,7 @@ typedef struct SnapObjectData {
union {
struct {
- /* SNAP_MESH */
+ /* Type::Mesh */
BVHTreeFromMesh treedata_mesh;
const struct MPoly *poly;
uint has_looptris : 1;
@@ -75,13 +76,13 @@ typedef struct SnapObjectData {
uint has_loose_vert : 1;
};
struct {
- /* SNAP_EDIT_MESH */
+ /* Type::EditMesh */
BVHTreeFromEditMesh treedata_editmesh;
float min[3], max[3];
struct Mesh_Runtime *mesh_runtime;
};
};
-} SnapObjectData;
+};
struct SnapObjectContext {
Scene *scene;
@@ -129,29 +130,29 @@ struct SnapObjectContext {
* \{ */
/* Mesh used for snapping.
- * If NULL the BMesh should be used. */
-static Mesh *mesh_for_snap(Object *ob_eval, eSnapEditType edit_mode_type, bool *r_use_hide)
+ * If nullptr the BMesh should be used. */
+static const Mesh *mesh_for_snap(Object *ob_eval, eSnapEditType edit_mode_type, bool *r_use_hide)
{
- Mesh *me_eval = BKE_object_get_evaluated_mesh(ob_eval);
+ const Mesh *me_eval = BKE_object_get_evaluated_mesh(ob_eval);
bool use_hide = false;
if (BKE_object_is_in_editmode(ob_eval)) {
if (edit_mode_type == SNAP_GEOM_EDIT) {
- return NULL;
+ return nullptr;
}
- Mesh *editmesh_eval_final = BKE_object_get_editmesh_eval_final(ob_eval);
- Mesh *editmesh_eval_cage = BKE_object_get_editmesh_eval_cage(ob_eval);
+ const Mesh *editmesh_eval_final = BKE_object_get_editmesh_eval_final(ob_eval);
+ const Mesh *editmesh_eval_cage = BKE_object_get_editmesh_eval_cage(ob_eval);
if ((edit_mode_type == SNAP_GEOM_FINAL) && editmesh_eval_final) {
if (editmesh_eval_final->runtime.wrapper_type == ME_WRAPPER_TYPE_BMESH) {
- return NULL;
+ return nullptr;
}
me_eval = editmesh_eval_final;
use_hide = true;
}
else if ((edit_mode_type == SNAP_GEOM_CAGE) && editmesh_eval_cage) {
if (editmesh_eval_cage->runtime.wrapper_type == ME_WRAPPER_TYPE_BMESH) {
- return NULL;
+ return nullptr;
}
me_eval = editmesh_eval_cage;
use_hide = true;
@@ -185,24 +186,24 @@ static void bm_mesh_minmax(BMesh *bm, float r_min[3], float r_max[3])
static void snap_object_data_mesh_clear(SnapObjectData *sod)
{
- BLI_assert(sod->type == SNAP_MESH);
+ BLI_assert(sod->type == SnapObjectData::Type::Mesh);
for (int i = 0; i < ARRAY_SIZE(sod->bvhtree); i++) {
if (!sod->cached[i]) {
BLI_bvhtree_free(sod->bvhtree[i]);
}
- sod->bvhtree[i] = NULL;
+ sod->bvhtree[i] = nullptr;
}
free_bvhtree_from_mesh(&sod->treedata_mesh);
}
static void snap_object_data_editmesh_clear(SnapObjectData *sod)
{
- BLI_assert(sod->type == SNAP_EDIT_MESH);
+ BLI_assert(sod->type == SnapObjectData::Type::EditMesh);
for (int i = 0; i < ARRAY_SIZE(sod->bvhtree); i++) {
if (!sod->cached[i]) {
BLI_bvhtree_free(sod->bvhtree[i]);
}
- sod->bvhtree[i] = NULL;
+ sod->bvhtree[i] = nullptr;
}
free_bvhtree_from_editmesh(&sod->treedata_editmesh);
}
@@ -210,11 +211,11 @@ static void snap_object_data_editmesh_clear(SnapObjectData *sod)
static void snap_object_data_clear(SnapObjectData *sod)
{
switch (sod->type) {
- case SNAP_MESH: {
+ case SnapObjectData::Type::Mesh: {
snap_object_data_mesh_clear(sod);
break;
}
- case SNAP_EDIT_MESH: {
+ case SnapObjectData::Type::EditMesh: {
snap_object_data_editmesh_clear(sod);
break;
}
@@ -224,13 +225,15 @@ static void snap_object_data_clear(SnapObjectData *sod)
static SnapObjectData *snap_object_data_lookup(SnapObjectContext *sctx, Object *ob_eval)
{
- SnapObjectData *sod = BLI_ghash_lookup(sctx->cache.object_map, ob_eval);
- if (sod == NULL) {
- if (sctx->cache.data_to_object_map != NULL) {
- ob_eval = BLI_ghash_lookup(sctx->cache.data_to_object_map, ob_eval->data);
+ SnapObjectData *sod = static_cast<SnapObjectData *>(
+ BLI_ghash_lookup(sctx->cache.object_map, ob_eval));
+ if (sod == nullptr) {
+ if (sctx->cache.data_to_object_map != nullptr) {
+ ob_eval = static_cast<Object *>(
+ BLI_ghash_lookup(sctx->cache.data_to_object_map, ob_eval->data));
/* Could be NULl when mixing edit-mode and non edit-mode objects. */
- if (ob_eval != NULL) {
- sod = BLI_ghash_lookup(sctx->cache.object_map, ob_eval);
+ if (ob_eval != nullptr) {
+ sod = static_cast<SnapObjectData *>(BLI_ghash_lookup(sctx->cache.object_map, ob_eval));
}
}
}
@@ -247,9 +250,9 @@ static SnapObjectData *snap_object_data_mesh_get(SnapObjectContext *sctx,
bool init = false;
if (BLI_ghash_ensure_p(sctx->cache.object_map, ob_eval, &sod_p)) {
- sod = *sod_p;
+ sod = static_cast<SnapObjectData *>(*sod_p);
bool is_dirty = false;
- if (sod->type != SNAP_MESH) {
+ if (sod->type != SnapObjectData::Type::Mesh) {
is_dirty = true;
}
else if (sod->treedata_mesh.tree && sod->treedata_mesh.cached &&
@@ -290,21 +293,22 @@ static SnapObjectData *snap_object_data_mesh_get(SnapObjectContext *sctx,
}
}
else {
- sod = *sod_p = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(*sod));
+ *sod_p = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(*sod));
+ sod = static_cast<SnapObjectData *>(*sod_p);
init = true;
}
if (init) {
- sod->type = SNAP_MESH;
+ sod->type = SnapObjectData::Type::Mesh;
/* The BVHTree from looptris is always required. */
- BLI_assert(sod->treedata_mesh.tree == NULL);
+ BLI_assert(sod->treedata_mesh.tree == nullptr);
BKE_bvhtree_from_mesh_get(&sod->treedata_mesh,
me_eval,
use_hide ? BVHTREE_FROM_LOOPTRI_NO_HIDDEN : BVHTREE_FROM_LOOPTRI,
4);
- if (sod->treedata_mesh.tree == NULL) {
+ if (sod->treedata_mesh.tree == nullptr) {
sod->treedata_mesh.vert = me_eval->mvert;
sod->treedata_mesh.vert_normals = BKE_mesh_vertex_normals_ensure(me_eval);
sod->treedata_mesh.loop = me_eval->mloop;
@@ -312,10 +316,10 @@ static SnapObjectData *snap_object_data_mesh_get(SnapObjectContext *sctx,
BLI_assert(sod->has_looptris == false);
}
else {
- BLI_assert(sod->treedata_mesh.vert != NULL);
- BLI_assert(sod->treedata_mesh.vert_normals != NULL);
- BLI_assert(sod->treedata_mesh.loop != NULL);
- BLI_assert(sod->treedata_mesh.looptri != NULL);
+ BLI_assert(sod->treedata_mesh.vert != nullptr);
+ BLI_assert(sod->treedata_mesh.vert_normals != nullptr);
+ BLI_assert(sod->treedata_mesh.loop != nullptr);
+ BLI_assert(sod->treedata_mesh.looptri != nullptr);
sod->has_looptris = true;
}
@@ -357,12 +361,12 @@ static SnapObjectData *snap_object_data_editmesh_get(SnapObjectContext *sctx,
{
/* Use object-data as the key in ghash since the editmesh
* is used to create bvhtree and is the same for each linked object. */
- if (sctx->cache.data_to_object_map == NULL) {
+ if (sctx->cache.data_to_object_map == nullptr) {
sctx->cache.data_to_object_map = BLI_ghash_ptr_new(__func__);
}
void **ob_p;
if (BLI_ghash_ensure_p(sctx->cache.data_to_object_map, ob_eval->data, &ob_p)) {
- ob_eval = *ob_p;
+ ob_eval = static_cast<Object *>(*ob_p);
}
else {
*ob_p = ob_eval;
@@ -370,10 +374,10 @@ static SnapObjectData *snap_object_data_editmesh_get(SnapObjectContext *sctx,
}
if (BLI_ghash_ensure_p(sctx->cache.object_map, ob_eval, &sod_p)) {
- sod = *sod_p;
+ sod = static_cast<SnapObjectData *>(*sod_p);
bool is_dirty = false;
/* Check if the geometry has changed. */
- if (sod->type != SNAP_EDIT_MESH) {
+ if (sod->type != SnapObjectData::Type::EditMesh) {
is_dirty = true;
}
else if (sod->treedata_editmesh.em != em) {
@@ -413,12 +417,13 @@ static SnapObjectData *snap_object_data_editmesh_get(SnapObjectContext *sctx,
}
}
else {
- sod = *sod_p = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(*sod));
+ *sod_p = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(*sod));
+ sod = static_cast<SnapObjectData *>(*sod_p);
init = true;
}
if (init) {
- sod->type = SNAP_EDIT_MESH;
+ sod->type = SnapObjectData::Type::EditMesh;
sod->treedata_editmesh.em = em;
sod->mesh_runtime = snap_object_data_editmesh_runtime_get(ob_eval);
bm_mesh_minmax(em->bm, sod->min, sod->max);
@@ -433,12 +438,12 @@ static SnapObjectData *snap_object_data_editmesh_get(SnapObjectContext *sctx,
/** \name Iterator
* \{ */
-typedef void (*IterSnapObjsCallback)(SnapObjectContext *sctx,
- const struct SnapObjectParams *params,
- Object *ob_eval,
- float obmat[4][4],
- bool is_object_active,
- void *data);
+using IterSnapObjsCallback = void (*)(SnapObjectContext *sctx,
+ const struct SnapObjectParams *params,
+ Object *ob_eval,
+ float obmat[4][4],
+ bool is_object_active,
+ void *data);
static bool snap_object_is_snappable(const SnapObjectContext *sctx,
const eSnapSelect snap_select,
@@ -459,7 +464,11 @@ static bool snap_object_is_snappable(const SnapObjectContext *sctx,
}
if (snap_select == SNAP_NOT_ACTIVE) {
- return base_act == base;
+ return base_act != base;
+ }
+
+ if (snap_select == SNAP_NOT_EDITED) {
+ return base->object->mode != OB_MODE_EDIT;
}
if (snap_select == SNAP_NOT_SELECTED) {
@@ -490,14 +499,8 @@ static void iter_snap_objects(SnapObjectContext *sctx,
const eSnapSelect snap_select = params->snap_select;
Base *base_act = view_layer->basact;
- if (snap_select == SNAP_ONLY_ACTIVE) {
- Object *obj_eval = DEG_get_evaluated_object(sctx->runtime.depsgraph, base_act->object);
- sob_callback(sctx, params, obj_eval, obj_eval->obmat, true, data);
- return;
- }
-
const bool is_in_object_mode = !base_act || base_act->object->mode == OB_MODE_OBJECT;
- for (Base *base = view_layer->object_bases.first; base != NULL; base = base->next) {
+ LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) {
if (!snap_object_is_snappable(sctx, snap_select, base_act, base, is_in_object_mode)) {
continue;
}
@@ -506,7 +509,7 @@ static void iter_snap_objects(SnapObjectContext *sctx,
Object *obj_eval = DEG_get_evaluated_object(sctx->runtime.depsgraph, base->object);
if (obj_eval->transflag & OB_DUPLI || BKE_object_has_geometry_set_instances(obj_eval)) {
ListBase *lb = object_duplilist(sctx->runtime.depsgraph, sctx->scene, obj_eval);
- for (DupliObject *dupli_ob = lb->first; dupli_ob; dupli_ob = dupli_ob->next) {
+ LISTBASE_FOREACH (DupliObject *, dupli_ob, lb) {
BLI_assert(DEG_is_evaluated_object(dupli_ob->ob));
sob_callback(sctx, params, dupli_ob->ob, dupli_ob->mat, is_object_active, data);
}
@@ -554,7 +557,7 @@ static struct SnapObjectHitDepth *hit_depth_create(const float depth,
const float obmat[4][4],
uint ob_uuid)
{
- struct SnapObjectHitDepth *hit = MEM_mallocN(sizeof(*hit), __func__);
+ struct SnapObjectHitDepth *hit = MEM_new<SnapObjectHitDepth>(__func__);
hit->depth = depth;
copy_v3_v3(hit->co, co);
@@ -570,8 +573,8 @@ static struct SnapObjectHitDepth *hit_depth_create(const float depth,
static int hit_depth_cmp(const void *arg1, const void *arg2)
{
- const struct SnapObjectHitDepth *h1 = arg1;
- const struct SnapObjectHitDepth *h2 = arg2;
+ const struct SnapObjectHitDepth *h1 = static_cast<const struct SnapObjectHitDepth *>(arg1);
+ const struct SnapObjectHitDepth *h2 = static_cast<const struct SnapObjectHitDepth *>(arg2);
int val = 0;
if (h1->depth < h2->depth) {
@@ -586,7 +589,7 @@ static int hit_depth_cmp(const void *arg1, const void *arg2)
static void raycast_all_cb(void *userdata, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit)
{
- struct RayCastAll_Data *data = userdata;
+ struct RayCastAll_Data *data = static_cast<struct RayCastAll_Data *>(userdata);
data->raycast_callback(data->bvhdata, index, ray, hit);
if (hit->index != -1) {
/* Get all values in world-space. */
@@ -715,11 +718,11 @@ static bool raycastMesh(SnapObjectContext *sctx,
}
/* Test BoundBox */
- BoundBox *bb = BKE_object_boundbox_get(ob_eval);
+ const BoundBox *bb = BKE_object_boundbox_get(ob_eval);
if (bb) {
/* was BKE_boundbox_ray_hit_check, see: cf6ca226fa58 */
if (!isect_ray_aabb_v3_simple(
- ray_start_local, ray_normal_local, bb->vec[0], bb->vec[6], &len_diff, NULL)) {
+ ray_start_local, ray_normal_local, bb->vec[0], bb->vec[6], &len_diff, nullptr)) {
return retval;
}
}
@@ -739,14 +742,14 @@ static bool raycastMesh(SnapObjectContext *sctx,
BVHTreeFromMesh *treedata = &sod->treedata_mesh;
- if (treedata->tree == NULL) {
+ if (treedata->tree == nullptr) {
return retval;
}
float timat[3][3]; /* transpose inverse matrix for normals */
transpose_m3_m4(timat, imat);
- BLI_assert(treedata->raycast_callback != NULL);
+ BLI_assert(treedata->raycast_callback != nullptr);
if (r_hit_list) {
struct RayCastAll_Data data;
@@ -772,10 +775,9 @@ static bool raycastMesh(SnapObjectContext *sctx,
retval = data.retval;
}
else {
- BVHTreeRayHit hit = {
- .index = -1,
- .dist = local_depth,
- };
+ BVHTreeRayHit hit{};
+ hit.index = -1;
+ hit.dist = local_depth;
if (BLI_bvhtree_ray_cast(treedata->tree,
ray_start_local,
@@ -859,7 +861,7 @@ static bool raycastEditMesh(SnapObjectContext *sctx,
/* was BKE_boundbox_ray_hit_check, see: cf6ca226fa58 */
if (!isect_ray_aabb_v3_simple(
- ray_start_local, ray_normal_local, sod->min, sod->max, &len_diff, NULL)) {
+ ray_start_local, ray_normal_local, sod->min, sod->max, &len_diff, nullptr)) {
return retval;
}
@@ -877,7 +879,7 @@ static bool raycastEditMesh(SnapObjectContext *sctx,
BVHTreeFromEditMesh *treedata = &sod->treedata_editmesh;
- if (treedata->tree == NULL) {
+ if (treedata->tree == nullptr) {
/* Operators only update the editmesh looptris of the original mesh. */
BLI_assert(sod->treedata_editmesh.em ==
BKE_editmesh_from_object(DEG_get_original_object(ob_eval)));
@@ -894,8 +896,16 @@ static bool raycastEditMesh(SnapObjectContext *sctx,
sctx->callbacks.edit_mesh.test_face_fn,
sctx->callbacks.edit_mesh.user_data);
- bvhtree_from_editmesh_looptri_ex(
- treedata, em, elem_mask, looptri_num_active, 0.0f, 4, 6, 0, NULL, NULL);
+ bvhtree_from_editmesh_looptri_ex(treedata,
+ em,
+ elem_mask,
+ looptri_num_active,
+ 0.0f,
+ 4,
+ 6,
+ BVHTREE_FROM_EM_LOOPTRI,
+ nullptr,
+ nullptr);
MEM_freeN(elem_mask);
}
@@ -907,10 +917,10 @@ static bool raycastEditMesh(SnapObjectContext *sctx,
4,
BVHTREE_FROM_EM_LOOPTRI,
&sod->mesh_runtime->bvh_cache,
- sod->mesh_runtime->eval_mutex);
+ static_cast<ThreadMutex *>(sod->mesh_runtime->eval_mutex));
}
- if (treedata->tree == NULL) {
+ if (treedata->tree == nullptr) {
return retval;
}
}
@@ -943,10 +953,9 @@ static bool raycastEditMesh(SnapObjectContext *sctx,
retval = data.retval;
}
else {
- BVHTreeRayHit hit = {
- .index = -1,
- .dist = local_depth,
- };
+ BVHTreeRayHit hit{};
+ hit.index = -1;
+ hit.dist = local_depth;
if (BLI_bvhtree_ray_cast(treedata->tree,
ray_start_local,
@@ -1013,7 +1022,7 @@ static void raycast_obj_fn(SnapObjectContext *sctx,
bool is_object_active,
void *data)
{
- struct RaycastObjUserData *dt = data;
+ RaycastObjUserData *dt = static_cast<RaycastObjUserData *>(data);
const uint ob_index = dt->ob_index++;
bool use_occlusion_test = dt->use_occlusion_test;
/* read/write args */
@@ -1032,8 +1041,8 @@ static void raycast_obj_fn(SnapObjectContext *sctx,
case OB_MESH: {
const eSnapEditType edit_mode_type = params->edit_mode_type;
bool use_hide = false;
- Mesh *me_eval = mesh_for_snap(ob_eval, edit_mode_type, &use_hide);
- if (me_eval == NULL) {
+ const Mesh *me_eval = mesh_for_snap(ob_eval, edit_mode_type, &use_hide);
+ if (me_eval == nullptr) {
/* Operators only update the editmesh looptris of the original mesh. */
BMEditMesh *em_orig = BKE_editmesh_from_object(DEG_get_original_object(ob_eval));
retval = raycastEditMesh(sctx,
@@ -1154,20 +1163,19 @@ static bool raycastObjects(SnapObjectContext *sctx,
}
}
- struct RaycastObjUserData data = {
- .ray_start = ray_start,
- .ray_dir = ray_dir,
- .ob_index = 0,
- .ray_depth = ray_depth,
- .r_loc = r_loc,
- .r_no = r_no,
- .r_index = r_index,
- .r_ob = r_ob,
- .r_obmat = r_obmat,
- .r_hit_list = r_hit_list,
- .use_occlusion_test = params->use_occlusion_test,
- .ret = false,
- };
+ RaycastObjUserData data = {};
+ data.ray_start = ray_start;
+ data.ray_dir = ray_dir;
+ data.ob_index = 0;
+ data.ray_depth = ray_depth;
+ data.r_loc = r_loc;
+ data.r_no = r_no;
+ data.r_index = r_index;
+ data.r_ob = r_ob;
+ data.r_obmat = r_obmat;
+ data.r_hit_list = r_hit_list;
+ data.use_occlusion_test = params->use_occlusion_test;
+ data.ret = false;
iter_snap_objects(sctx, params, raycast_obj_fn, &data);
@@ -1211,24 +1219,24 @@ static bool snap_bound_box_check_dist(const float min[3],
struct Nearest2dUserData;
-typedef void (*Nearest2DGetVertCoCallback)(const int index,
- const struct Nearest2dUserData *data,
- const float **r_co);
-typedef void (*Nearest2DGetEdgeVertsCallback)(const int index,
+using Nearest2DGetVertCoCallback = void (*)(const int index,
+ const struct Nearest2dUserData *data,
+ const float **r_co);
+using Nearest2DGetEdgeVertsCallback = void (*)(const int index,
+ const struct Nearest2dUserData *data,
+ int r_v_index[2]);
+using Nearest2DGetTriVertsCallback = void (*)(const int index,
const struct Nearest2dUserData *data,
- int r_v_index[2]);
-typedef void (*Nearest2DGetTriVertsCallback)(const int index,
- const struct Nearest2dUserData *data,
- int r_v_index[3]);
+ int r_v_index[3]);
/* Equal the previous one */
-typedef void (*Nearest2DGetTriEdgesCallback)(const int index,
+using Nearest2DGetTriEdgesCallback = void (*)(const int index,
+ const struct Nearest2dUserData *data,
+ int r_e_index[3]);
+using Nearest2DCopyVertNoCallback = void (*)(const int index,
const struct Nearest2dUserData *data,
- int r_e_index[3]);
-typedef void (*Nearest2DCopyVertNoCallback)(const int index,
- const struct Nearest2dUserData *data,
- float r_no[3]);
+ float r_no[3]);
-typedef struct Nearest2dUserData {
+struct Nearest2dUserData {
Nearest2DGetVertCoCallback get_vert_co;
Nearest2DGetEdgeVertsCallback get_edge_verts_index;
Nearest2DGetTriVertsCallback get_tri_verts_index;
@@ -1250,7 +1258,7 @@ typedef struct Nearest2dUserData {
bool is_persp;
bool use_backface_culling;
-} Nearest2dUserData;
+};
static void cb_mvert_co_get(const int index, const Nearest2dUserData *data, const float **r_co)
{
@@ -1386,7 +1394,7 @@ static void cb_snap_vert(void *userdata,
const int clip_plane_len,
BVHTreeNearest *nearest)
{
- Nearest2dUserData *data = userdata;
+ Nearest2dUserData *data = static_cast<Nearest2dUserData *>(userdata);
const float *co;
data->get_vert_co(index, data, &co);
@@ -1410,7 +1418,7 @@ static void cb_snap_edge(void *userdata,
const int clip_plane_len,
BVHTreeNearest *nearest)
{
- struct Nearest2dUserData *data = userdata;
+ Nearest2dUserData *data = static_cast<Nearest2dUserData *>(userdata);
int vindex[2];
data->get_edge_verts_index(index, data, vindex);
@@ -1439,7 +1447,7 @@ static void cb_snap_edge_verts(void *userdata,
const int clip_plane_len,
BVHTreeNearest *nearest)
{
- struct Nearest2dUserData *data = userdata;
+ Nearest2dUserData *data = static_cast<Nearest2dUserData *>(userdata);
int vindex[2];
data->get_edge_verts_index(index, data, vindex);
@@ -1459,7 +1467,7 @@ static void cb_snap_tri_edges(void *userdata,
const int clip_plane_len,
BVHTreeNearest *nearest)
{
- Nearest2dUserData *data = userdata;
+ Nearest2dUserData *data = static_cast<Nearest2dUserData *>(userdata);
if (data->use_backface_culling) {
int vindex[3];
@@ -1494,7 +1502,7 @@ static void cb_snap_tri_verts(void *userdata,
const int clip_plane_len,
BVHTreeNearest *nearest)
{
- struct Nearest2dUserData *data = userdata;
+ Nearest2dUserData *data = static_cast<Nearest2dUserData *>(userdata);
int vindex[3];
data->get_tri_verts_index(index, data, vindex);
@@ -1523,7 +1531,7 @@ static void nearest2d_data_init(SnapObjectData *sod,
bool use_backface_culling,
Nearest2dUserData *r_nearest2d)
{
- if (sod->type == SNAP_MESH) {
+ if (sod->type == SnapObjectData::Type::Mesh) {
r_nearest2d->get_vert_co = cb_mvert_co_get;
r_nearest2d->get_edge_verts_index = cb_medge_verts_get;
r_nearest2d->copy_vert_no = cb_mvert_no_copy;
@@ -1537,12 +1545,12 @@ static void nearest2d_data_init(SnapObjectData *sod,
r_nearest2d->looptri = sod->treedata_mesh.looptri;
}
else {
- BLI_assert(sod->type == SNAP_EDIT_MESH);
+ BLI_assert(sod->type == SnapObjectData::Type::EditMesh);
r_nearest2d->get_vert_co = cb_bvert_co_get;
r_nearest2d->get_edge_verts_index = cb_bedge_verts_get;
r_nearest2d->copy_vert_no = cb_bvert_no_copy;
- r_nearest2d->get_tri_verts_index = NULL;
- r_nearest2d->get_tri_edges_index = NULL;
+ r_nearest2d->get_tri_verts_index = nullptr;
+ r_nearest2d->get_tri_edges_index = nullptr;
r_nearest2d->bm = sod->treedata_editmesh.em->bm;
}
@@ -1583,26 +1591,25 @@ static short snap_mesh_polygon(SnapObjectContext *sctx,
mul_v4_m4v4(clip_planes_local[i], tobmat, sctx->runtime.clip_plane[i]);
}
- BVHTreeNearest nearest = {
- .index = -1,
- .dist_sq = square_f(*dist_px),
- };
+ BVHTreeNearest nearest{};
+ nearest.index = -1;
+ nearest.dist_sq = square_f(*dist_px);
SnapObjectData *sod = snap_object_data_lookup(sctx, ob_eval);
- BLI_assert(sod != NULL);
+ BLI_assert(sod != nullptr);
Nearest2dUserData nearest2d;
nearest2d_data_init(
sod, sctx->runtime.view_proj == VIEW_PROJ_PERSP, params->use_backface_culling, &nearest2d);
- if (sod->type == SNAP_MESH) {
+ if (sod->type == SnapObjectData::Type::Mesh) {
BVHTreeFromMesh *treedata = &sod->treedata_mesh;
const MPoly *mp = &sod->poly[*r_index];
const MLoop *ml = &treedata->loop[mp->loopstart];
if (sctx->runtime.snap_to_flag & SCE_SNAP_MODE_EDGE) {
elem = SCE_SNAP_MODE_EDGE;
- BLI_assert(treedata->edge != NULL);
+ BLI_assert(treedata->edge != nullptr);
for (int i = mp->totloop; i--; ml++) {
cb_snap_edge(&nearest2d,
ml->e,
@@ -1625,7 +1632,7 @@ static short snap_mesh_polygon(SnapObjectContext *sctx,
}
}
else {
- BLI_assert(sod->type == SNAP_EDIT_MESH);
+ BLI_assert(sod->type == SnapObjectData::Type::EditMesh);
BMEditMesh *em = sod->treedata_editmesh.em;
BM_mesh_elem_table_ensure(em->bm, BM_FACE);
@@ -1702,7 +1709,7 @@ static short snap_mesh_edge_verts_mixed(SnapObjectContext *sctx,
}
SnapObjectData *sod = snap_object_data_lookup(sctx, ob_eval);
- BLI_assert(sod != NULL);
+ BLI_assert(sod != nullptr);
Nearest2dUserData nearest2d;
nearest2d_data_init(
@@ -1724,10 +1731,9 @@ static short snap_mesh_edge_verts_mixed(SnapObjectContext *sctx,
&neasrest_precalc, lpmat, sctx->runtime.win_size, sctx->runtime.mval);
}
- BVHTreeNearest nearest = {
- .index = -1,
- .dist_sq = square_f(original_dist_px),
- };
+ BVHTreeNearest nearest{};
+ nearest.index = -1;
+ nearest.dist_sq = square_f(original_dist_px);
float lambda;
if (!isect_ray_line_v3(neasrest_precalc.ray_origin,
@@ -1749,7 +1755,7 @@ static short snap_mesh_edge_verts_mixed(SnapObjectContext *sctx,
int v_id = lambda < 0.5f ? 0 : 1;
if (test_projected_vert_dist(&neasrest_precalc,
- NULL,
+ nullptr,
0,
nearest2d.is_persp,
v_pair[v_id],
@@ -1775,7 +1781,7 @@ static short snap_mesh_edge_verts_mixed(SnapObjectContext *sctx,
mid_v3_v3v3(vmid, v_pair[0], v_pair[1]);
if (test_projected_vert_dist(&neasrest_precalc,
- NULL,
+ nullptr,
0,
nearest2d.is_persp,
vmid,
@@ -1802,7 +1808,7 @@ static short snap_mesh_edge_verts_mixed(SnapObjectContext *sctx,
&neasrest_precalc, sctx->runtime.pmat, sctx->runtime.win_size, sctx->runtime.mval);
if (test_projected_vert_dist(&neasrest_precalc,
- NULL,
+ nullptr,
0,
nearest2d.is_persp,
v_near,
@@ -1855,12 +1861,12 @@ static short snapArmature(SnapObjectContext *sctx,
dist_squared_to_projected_aabb_precalc(
&neasrest_precalc, lpmat, sctx->runtime.win_size, sctx->runtime.mval);
- bArmature *arm = ob_eval->data;
- const bool is_editmode = arm->edbo != NULL;
+ bArmature *arm = static_cast<bArmature *>(ob_eval->data);
+ const bool is_editmode = arm->edbo != nullptr;
if (is_editmode == false) {
/* Test BoundBox */
- BoundBox *bb = BKE_armature_boundbox_get(ob_eval);
+ const BoundBox *bb = BKE_armature_boundbox_get(ob_eval);
if (bb && !snap_bound_box_check_dist(bb->vec[0],
bb->vec[6],
lpmat,
@@ -2015,7 +2021,7 @@ static short snapCurve(SnapObjectContext *sctx,
return 0;
}
- Curve *cu = ob_eval->data;
+ Curve *cu = static_cast<Curve *>(ob_eval->data);
float dist_px_sq = square_f(*dist_px);
float lpmat[4][4];
@@ -2060,7 +2066,7 @@ static short snapCurve(SnapObjectContext *sctx,
bool is_persp = sctx->runtime.view_proj == VIEW_PROJ_PERSP;
bool skip_selected = params->snap_select == SNAP_NOT_SELECTED;
- for (Nurb *nu = (use_obedit ? cu->editnurb->nurbs.first : cu->nurb.first); nu; nu = nu->next) {
+ LISTBASE_FOREACH (Nurb *, nu, (use_obedit ? &cu->editnurb->nurbs : &cu->nurb)) {
for (int u = 0; u < nu->pntsu; u++) {
if (sctx->runtime.snap_to_flag & SCE_SNAP_MODE_VERTEX) {
if (use_obedit) {
@@ -2243,7 +2249,7 @@ static short snapCamera(const SnapObjectContext *sctx,
MovieClip *clip = BKE_object_movieclip_get(scene, object, false);
MovieTracking *tracking;
- if (clip == NULL) {
+ if (clip == nullptr) {
return snap_object_center(sctx, object, obmat, dist_px, r_loc, r_no, r_index);
}
if (object->transflag & OB_DUPLI) {
@@ -2262,11 +2268,8 @@ static short snapCamera(const SnapObjectContext *sctx,
dist_squared_to_projected_aabb_precalc(
&neasrest_precalc, sctx->runtime.pmat, sctx->runtime.win_size, sctx->runtime.mval);
- MovieTrackingObject *tracking_object;
- for (tracking_object = tracking->objects.first; tracking_object;
- tracking_object = tracking_object->next) {
+ LISTBASE_FOREACH (MovieTrackingObject *, tracking_object, &tracking->objects) {
ListBase *tracksbase = BKE_tracking_object_get_tracks(tracking, tracking_object);
- MovieTrackingTrack *track;
float reconstructed_camera_mat[4][4], reconstructed_camera_imat[4][4];
float(*vertex_obmat)[4];
@@ -2277,7 +2280,7 @@ static short snapCamera(const SnapObjectContext *sctx,
invert_m4_m4(reconstructed_camera_imat, reconstructed_camera_mat);
}
- for (track = tracksbase->first; track; track = track->next) {
+ LISTBASE_FOREACH (MovieTrackingTrack *, track, tracksbase) {
float bundle_pos[3];
if ((track->flag & TRACK_HAS_BUNDLE) == 0) {
@@ -2322,7 +2325,7 @@ static short snapCamera(const SnapObjectContext *sctx,
static short snapMesh(SnapObjectContext *sctx,
const struct SnapObjectParams *params,
Object *ob_eval,
- Mesh *me_eval,
+ const Mesh *me_eval,
const float obmat[4][4],
bool use_hide,
/* read/write args */
@@ -2346,7 +2349,7 @@ static short snapMesh(SnapObjectContext *sctx,
float dist_px_sq = square_f(*dist_px);
/* Test BoundBox */
- BoundBox *bb = BKE_object_boundbox_get(ob_eval);
+ const BoundBox *bb = BKE_object_boundbox_get(ob_eval);
if (bb &&
!snap_bound_box_check_dist(
bb->vec[0], bb->vec[6], lpmat, sctx->runtime.win_size, sctx->runtime.mval, dist_px_sq)) {
@@ -2358,10 +2361,10 @@ static short snapMesh(SnapObjectContext *sctx,
BVHTreeFromMesh *treedata, treedata_tmp;
treedata = &sod->treedata_mesh;
- if (sod->has_loose_edge && sod->bvhtree[0] == NULL) {
+ if (sod->has_loose_edge && sod->bvhtree[0] == nullptr) {
sod->bvhtree[0] = BKE_bvhtree_from_mesh_get(
&treedata_tmp, me_eval, BVHTREE_FROM_LOOSEEDGES, 2);
- if (sod->bvhtree[0] == NULL) {
+ if (sod->bvhtree[0] == nullptr) {
sod->has_loose_edge = false;
}
sod->cached[0] = treedata_tmp.cached;
@@ -2374,10 +2377,10 @@ static short snapMesh(SnapObjectContext *sctx,
}
if (sctx->runtime.snap_to_flag & SCE_SNAP_MODE_VERTEX) {
- if (sod->has_loose_vert && sod->bvhtree[1] == NULL) {
+ if (sod->has_loose_vert && sod->bvhtree[1] == nullptr) {
sod->bvhtree[1] = BKE_bvhtree_from_mesh_get(
&treedata_tmp, me_eval, BVHTREE_FROM_LOOSEVERTS, 2);
- if (sod->bvhtree[1] == NULL) {
+ if (sod->bvhtree[1] == nullptr) {
sod->has_loose_vert = false;
}
sod->cached[1] = treedata_tmp.cached;
@@ -2398,10 +2401,10 @@ static short snapMesh(SnapObjectContext *sctx,
nearest2d_data_init(
sod, sctx->runtime.view_proj == VIEW_PROJ_PERSP, params->use_backface_culling, &nearest2d);
- BVHTreeNearest nearest = {
- .index = -1,
- .dist_sq = dist_px_sq,
- };
+ BVHTreeNearest nearest{};
+ nearest.index = -1;
+ nearest.dist_sq = dist_px_sq;
+
int last_index = nearest.index;
short elem = SCE_SNAP_MODE_VERTEX;
@@ -2551,10 +2554,11 @@ static short snapEditMesh(SnapObjectContext *sctx,
}
if (sctx->runtime.snap_to_flag & SCE_SNAP_MODE_VERTEX) {
- BVHTreeFromEditMesh treedata = {.tree = sod->bvhtree[0]};
+ BVHTreeFromEditMesh treedata{};
+ treedata.tree = sod->bvhtree[0];
- if (treedata.tree == NULL) {
- BLI_bitmap *verts_mask = NULL;
+ if (treedata.tree == nullptr) {
+ BLI_bitmap *verts_mask = nullptr;
int verts_num_active = -1;
if (sctx->callbacks.edit_mesh.test_vert_fn) {
verts_mask = BLI_BITMAP_NEW(em->bm->totvert, __func__);
@@ -2565,8 +2569,16 @@ static short snapEditMesh(SnapObjectContext *sctx,
(bool (*)(BMElem *, void *))sctx->callbacks.edit_mesh.test_vert_fn,
sctx->callbacks.edit_mesh.user_data);
- bvhtree_from_editmesh_verts_ex(
- &treedata, em, verts_mask, verts_num_active, 0.0f, 2, 6, 0, NULL, NULL);
+ bvhtree_from_editmesh_verts_ex(&treedata,
+ em,
+ verts_mask,
+ verts_num_active,
+ 0.0f,
+ 2,
+ 6,
+ BVHTREE_FROM_VERTS,
+ nullptr,
+ nullptr);
MEM_freeN(verts_mask);
}
else {
@@ -2583,10 +2595,11 @@ static short snapEditMesh(SnapObjectContext *sctx,
}
if (sctx->runtime.snap_to_flag & SCE_SNAP_MODE_EDGE) {
- BVHTreeFromEditMesh treedata = {.tree = sod->bvhtree[1]};
+ BVHTreeFromEditMesh treedata{};
+ treedata.tree = sod->bvhtree[1];
- if (treedata.tree == NULL) {
- BLI_bitmap *edges_mask = NULL;
+ if (treedata.tree == nullptr) {
+ BLI_bitmap *edges_mask = nullptr;
int edges_num_active = -1;
if (sctx->callbacks.edit_mesh.test_edge_fn) {
edges_mask = BLI_BITMAP_NEW(em->bm->totedge, __func__);
@@ -2597,8 +2610,16 @@ static short snapEditMesh(SnapObjectContext *sctx,
(bool (*)(BMElem *, void *))sctx->callbacks.edit_mesh.test_edge_fn,
sctx->callbacks.edit_mesh.user_data);
- bvhtree_from_editmesh_edges_ex(
- &treedata, em, edges_mask, edges_num_active, 0.0f, 2, 6, 0, NULL, NULL);
+ bvhtree_from_editmesh_edges_ex(&treedata,
+ em,
+ edges_mask,
+ edges_num_active,
+ 0.0f,
+ 2,
+ 6,
+ BVHTREE_FROM_VERTS,
+ nullptr,
+ nullptr);
MEM_freeN(edges_mask);
}
else {
@@ -2607,7 +2628,7 @@ static short snapEditMesh(SnapObjectContext *sctx,
2,
BVHTREE_FROM_EM_EDGES,
&sod->mesh_runtime->bvh_cache,
- sod->mesh_runtime->eval_mutex);
+ static_cast<ThreadMutex *>(sod->mesh_runtime->eval_mutex));
}
sod->bvhtree[1] = treedata.tree;
sod->cached[1] = treedata.cached;
@@ -2618,10 +2639,10 @@ static short snapEditMesh(SnapObjectContext *sctx,
nearest2d_data_init(
sod, sctx->runtime.view_proj == VIEW_PROJ_PERSP, params->use_backface_culling, &nearest2d);
- BVHTreeNearest nearest = {
- .index = -1,
- .dist_sq = dist_px_sq,
- };
+ BVHTreeNearest nearest{};
+ nearest.index = -1;
+ nearest.dist_sq = dist_px_sq;
+
short elem = SCE_SNAP_MODE_VERTEX;
float tobmat[4][4], clip_planes_local[MAX_CLIPPLANE_LEN][4];
@@ -2713,15 +2734,15 @@ static void snap_obj_fn(SnapObjectContext *sctx,
bool is_object_active,
void *data)
{
- struct SnapObjUserData *dt = data;
+ SnapObjUserData *dt = static_cast<SnapObjUserData *>(data);
short retval = 0;
switch (ob_eval->type) {
case OB_MESH: {
const eSnapEditType edit_mode_type = params->edit_mode_type;
bool use_hide;
- Mesh *me_eval = mesh_for_snap(ob_eval, edit_mode_type, &use_hide);
- if (me_eval == NULL) {
+ const Mesh *me_eval = mesh_for_snap(ob_eval, edit_mode_type, &use_hide);
+ if (me_eval == nullptr) {
/* Operators only update the editmesh looptris of the original mesh. */
BMEditMesh *em_orig = BKE_editmesh_from_object(DEG_get_original_object(ob_eval));
retval = snapEditMesh(
@@ -2762,7 +2783,7 @@ static void snap_obj_fn(SnapObjectContext *sctx,
break; /* Use ATTR_FALLTHROUGH if we want to snap to the generated mesh. */
case OB_SURF:
case OB_FONT: {
- Mesh *mesh_eval = BKE_object_get_evaluated_mesh(ob_eval);
+ const Mesh *mesh_eval = BKE_object_get_evaluated_mesh(ob_eval);
if (mesh_eval) {
retval |= snapMesh(sctx,
params,
@@ -2835,15 +2856,14 @@ static short snapObjectsRay(SnapObjectContext *sctx,
Object **r_ob,
float r_obmat[4][4])
{
- struct SnapObjUserData data = {
- .dist_px = dist_px,
- .r_loc = r_loc,
- .r_no = r_no,
- .r_ob = r_ob,
- .r_index = r_index,
- .r_obmat = r_obmat,
- .ret = 0,
- };
+ SnapObjUserData data = {};
+ data.dist_px = dist_px;
+ data.r_loc = r_loc;
+ data.r_no = r_no;
+ data.r_ob = r_ob;
+ data.r_index = r_index;
+ data.r_obmat = r_obmat;
+ data.ret = 0;
iter_snap_objects(sctx, params, snap_obj_fn, &data);
@@ -2858,7 +2878,7 @@ static short snapObjectsRay(SnapObjectContext *sctx,
SnapObjectContext *ED_transform_snap_object_context_create(Scene *scene, int flag)
{
- SnapObjectContext *sctx = MEM_callocN(sizeof(*sctx), __func__);
+ SnapObjectContext *sctx = MEM_cnew<SnapObjectContext>(__func__);
sctx->flag = flag;
@@ -2866,7 +2886,7 @@ SnapObjectContext *ED_transform_snap_object_context_create(Scene *scene, int fla
sctx->cache.object_map = BLI_ghash_ptr_new(__func__);
/* Initialize as needed (edit-mode only). */
- sctx->cache.data_to_object_map = NULL;
+ sctx->cache.data_to_object_map = nullptr;
sctx->cache.mem_arena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__);
return sctx;
@@ -2874,15 +2894,15 @@ SnapObjectContext *ED_transform_snap_object_context_create(Scene *scene, int fla
static void snap_object_data_free(void *sod_v)
{
- SnapObjectData *sod = sod_v;
+ SnapObjectData *sod = static_cast<SnapObjectData *>(sod_v);
snap_object_data_clear(sod);
}
void ED_transform_snap_object_context_destroy(SnapObjectContext *sctx)
{
- BLI_ghash_free(sctx->cache.object_map, NULL, snap_object_data_free);
- if (sctx->cache.data_to_object_map != NULL) {
- BLI_ghash_free(sctx->cache.data_to_object_map, NULL, NULL);
+ BLI_ghash_free(sctx->cache.object_map, nullptr, snap_object_data_free);
+ if (sctx->cache.data_to_object_map != nullptr) {
+ BLI_ghash_free(sctx->cache.data_to_object_map, nullptr, nullptr);
}
BLI_memarena_free(sctx->cache.mem_arena);
@@ -2919,8 +2939,17 @@ bool ED_transform_snap_object_project_ray_ex(SnapObjectContext *sctx,
sctx->runtime.depsgraph = depsgraph;
sctx->runtime.v3d = v3d;
- return raycastObjects(
- sctx, params, ray_start, ray_normal, ray_depth, r_loc, r_no, r_index, r_ob, r_obmat, NULL);
+ return raycastObjects(sctx,
+ params,
+ ray_start,
+ ray_normal,
+ ray_depth,
+ r_loc,
+ r_no,
+ r_index,
+ r_ob,
+ r_obmat,
+ nullptr);
}
bool ED_transform_snap_object_project_ray_all(SnapObjectContext *sctx,
@@ -2944,8 +2973,17 @@ bool ED_transform_snap_object_project_ray_all(SnapObjectContext *sctx,
float ray_depth_prev = ray_depth;
#endif
- bool retval = raycastObjects(
- sctx, params, ray_start, ray_normal, &ray_depth, NULL, NULL, NULL, NULL, NULL, r_hit_list);
+ bool retval = raycastObjects(sctx,
+ params,
+ ray_start,
+ ray_normal,
+ &ray_depth,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ r_hit_list);
/* meant to be readonly for 'all' hits, ensure it is */
#ifdef DEBUG
@@ -2988,9 +3026,9 @@ static bool transform_snap_context_project_ray_impl(SnapObjectContext *sctx,
ray_depth,
r_co,
r_no,
- NULL,
- NULL,
- NULL);
+ nullptr,
+ nullptr,
+ nullptr);
return ret;
}
@@ -3006,7 +3044,7 @@ bool ED_transform_snap_object_project_ray(SnapObjectContext *sctx,
float r_no[3])
{
float ray_depth_fallback;
- if (ray_depth == NULL) {
+ if (ray_depth == nullptr) {
ray_depth_fallback = BVH_RAYCAST_DIST_MAX;
ray_depth = &ray_depth_fallback;
}
@@ -3043,7 +3081,7 @@ static short transform_snap_context_project_view3d_mixed_impl(
short retval = 0;
bool has_hit = false;
- Object *ob_eval = NULL;
+ Object *ob_eval = nullptr;
float loc[3];
/* Not all snapping callbacks set the normal,
* initialize this since any hit copies both the `loc` and `no`. */
@@ -3051,14 +3089,14 @@ static short transform_snap_context_project_view3d_mixed_impl(
float obmat[4][4];
int index = -1;
- const RegionView3D *rv3d = region->regiondata;
+ const RegionView3D *rv3d = static_cast<RegionView3D *>(region->regiondata);
bool use_occlusion_test = params->use_occlusion_test && !XRAY_ENABLED(v3d);
if (snap_to_flag & SCE_SNAP_MODE_FACE || use_occlusion_test) {
float ray_start[3], ray_normal[3];
if (!ED_view3d_win_to_ray_clipped_ex(
- depsgraph, region, v3d, mval, NULL, ray_normal, ray_start, true)) {
+ depsgraph, region, v3d, mval, nullptr, ray_normal, ray_start, true)) {
return 0;
}
@@ -3074,7 +3112,7 @@ static short transform_snap_context_project_view3d_mixed_impl(
&index,
&ob_eval,
obmat,
- NULL);
+ nullptr);
if (has_hit) {
if (r_face_nor) {
@@ -3119,10 +3157,10 @@ static short transform_snap_context_project_view3d_mixed_impl(
}
planes_from_projmat(sctx->runtime.pmat,
- NULL,
- NULL,
- NULL,
- NULL,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
sctx->runtime.clip_plane[0],
sctx->runtime.clip_plane[1]);
@@ -3255,10 +3293,10 @@ short ED_transform_snap_object_project_view3d(SnapObjectContext *sctx,
dist_px,
r_loc,
r_no,
- NULL,
- NULL,
- NULL,
- NULL);
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr);
}
bool ED_transform_snap_object_project_all_view3d_ex(SnapObjectContext *sctx,
@@ -3274,7 +3312,7 @@ bool ED_transform_snap_object_project_all_view3d_ex(SnapObjectContext *sctx,
float ray_start[3], ray_normal[3];
if (!ED_view3d_win_to_ray_clipped_ex(
- depsgraph, region, v3d, mval, NULL, ray_normal, ray_start, true)) {
+ depsgraph, region, v3d, mval, nullptr, ray_normal, ray_start, true)) {
return false;
}
diff --git a/source/blender/editors/util/ed_transverts.c b/source/blender/editors/util/ed_transverts.c
index c1e093d5555..8d8f7733877 100644
--- a/source/blender/editors/util/ed_transverts.c
+++ b/source/blender/editors/util/ed_transverts.c
@@ -33,7 +33,7 @@
#include "ED_transverts.h" /* own include */
-/* copied from editobject.c, now uses (almost) proper depgraph */
+/* copied from editobject.c, now uses (almost) proper depsgraph. */
void ED_transverts_update_obedit(TransVertStore *tvs, Object *obedit)
{
const int mode = tvs->mode;
diff --git a/source/blender/editors/util/ed_util.c b/source/blender/editors/util/ed_util.c
index 32d405df841..f07364cd4d3 100644
--- a/source/blender/editors/util/ed_util.c
+++ b/source/blender/editors/util/ed_util.c
@@ -19,6 +19,7 @@
#include "BKE_collection.h"
#include "BKE_global.h"
+#include "BKE_lib_id.h"
#include "BKE_lib_remap.h"
#include "BKE_main.h"
#include "BKE_material.h"
@@ -124,8 +125,9 @@ void ED_editors_init(bContext *C)
if (obact == NULL || ob->type != obact->type) {
continue;
}
- /* Object mode is enforced for linked data (or their obdata). */
- if (ID_IS_LINKED(ob) || (ob_data != NULL && ID_IS_LINKED(ob_data))) {
+ /* Object mode is enforced for non-editable data (or their obdata). */
+ if (!BKE_id_is_editable(bmain, &ob->id) ||
+ (ob_data != NULL && !BKE_id_is_editable(bmain, ob_data))) {
continue;
}
diff --git a/source/blender/editors/util/ed_util_ops.cc b/source/blender/editors/util/ed_util_ops.cc
index 25deacbcdd1..ccc28353518 100644
--- a/source/blender/editors/util/ed_util_ops.cc
+++ b/source/blender/editors/util/ed_util_ops.cc
@@ -226,7 +226,8 @@ static int lib_id_fake_user_toggle_exec(bContext *C, wmOperator *op)
ID *id = (ID *)idptr.data;
- if (ID_IS_LINKED(id) || (ELEM(GS(id->name), ID_GR, ID_SCE, ID_SCR, ID_TXT, ID_OB, ID_WS))) {
+ if (!BKE_id_is_editable(CTX_data_main(C), id) ||
+ (ELEM(GS(id->name), ID_GR, ID_SCE, ID_SCR, ID_TXT, ID_OB, ID_WS))) {
BKE_report(op->reports, RPT_ERROR, "Data-block type does not support fake user");
return OPERATOR_CANCELLED;
}
diff --git a/source/blender/editors/util/select_utils.c b/source/blender/editors/util/select_utils.c
index 380c7ed0e43..53f9aca8e8d 100644
--- a/source/blender/editors/util/select_utils.c
+++ b/source/blender/editors/util/select_utils.c
@@ -10,6 +10,12 @@
#include "BLI_math.h"
#include "BLI_utildefines.h"
+#include "DNA_windowmanager_types.h"
+
+#include "RNA_access.h"
+
+#include "WM_types.h"
+
#include "ED_select_utils.h"
int ED_select_op_action(const eSelectOp sel_op, const bool is_select, const bool is_inside)
@@ -113,8 +119,12 @@ bool ED_select_similar_compare_float_tree(const KDTree_1d *tree,
return false;
}
-eSelectOp ED_select_op_from_booleans(const bool extend, const bool deselect, const bool toggle)
+eSelectOp ED_select_op_from_operator(wmOperator *op)
{
+ const bool extend = RNA_boolean_get(op->ptr, "extend");
+ const bool deselect = RNA_boolean_get(op->ptr, "deselect");
+ const bool toggle = RNA_boolean_get(op->ptr, "toggle");
+
if (extend) {
return SEL_OP_ADD;
}
@@ -126,3 +136,11 @@ eSelectOp ED_select_op_from_booleans(const bool extend, const bool deselect, con
}
return SEL_OP_SET;
}
+
+void ED_select_pick_params_from_operator(wmOperator *op, struct SelectPick_Params *params)
+{
+ memset(params, 0x0, sizeof(*params));
+ params->sel_op = ED_select_op_from_operator(op);
+ params->deselect_all = RNA_boolean_get(op->ptr, "deselect_all");
+ params->select_passthrough = RNA_boolean_get(op->ptr, "select_passthrough");
+}
diff --git a/source/blender/editors/uvedit/CMakeLists.txt b/source/blender/editors/uvedit/CMakeLists.txt
index f8a192e3254..761e7cd091e 100644
--- a/source/blender/editors/uvedit/CMakeLists.txt
+++ b/source/blender/editors/uvedit/CMakeLists.txt
@@ -7,6 +7,7 @@ set(INC
../../blentranslation
../../bmesh
../../depsgraph
+ ../../geometry
../../gpu
../../makesdna
../../makesrna
@@ -24,7 +25,6 @@ set(SRC
uvedit_draw.c
uvedit_islands.c
uvedit_ops.c
- uvedit_parametrizer.c
uvedit_path.c
uvedit_rip.c
uvedit_select.c
@@ -32,7 +32,6 @@ set(SRC
uvedit_unwrap_ops.c
uvedit_intern.h
- uvedit_parametrizer.h
)
set(LIB
diff --git a/source/blender/editors/uvedit/uvedit_islands.c b/source/blender/editors/uvedit/uvedit_islands.c
index 59992d23e2e..e1752ae5a29 100644
--- a/source/blender/editors/uvedit/uvedit_islands.c
+++ b/source/blender/editors/uvedit/uvedit_islands.c
@@ -5,7 +5,7 @@
*
* Utilities for manipulating UV islands.
*
- * \note This is similar to `uvedit_parametrizer.c`,
+ * \note This is similar to `GEO_uv_parametrizer.h`,
* however the data structures there don't support arbitrary topology
* such as an edge with 3 or more faces using it.
* This API uses #BMesh data structures and doesn't have limitations for manifold meshes.
diff --git a/source/blender/editors/uvedit/uvedit_parametrizer.h b/source/blender/editors/uvedit/uvedit_parametrizer.h
deleted file mode 100644
index f234fbe2ace..00000000000
--- a/source/blender/editors/uvedit/uvedit_parametrizer.h
+++ /dev/null
@@ -1,99 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-
-#pragma once
-
-/** \file
- * \ingroup eduv
- */
-
-#include "BLI_sys_types.h" /* for intptr_t support */
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-typedef void ParamHandle; /* handle to a set of charts */
-typedef intptr_t ParamKey; /* (hash) key for identifying verts and faces */
-typedef enum ParamBool {
- PARAM_TRUE = 1,
- PARAM_FALSE = 0,
-} ParamBool;
-
-/* Chart construction:
- * -------------------
- * - faces and seams may only be added between construct_{begin|end}
- * - the pointers to co and uv are stored, rather than being copied
- * - vertices are implicitly created
- * - in construct_end the mesh will be split up according to the seams
- * - the resulting charts must be:
- * - manifold, connected, open (at least one boundary loop)
- * - output will be written to the uv pointers
- */
-
-ParamHandle *param_construct_begin(void);
-
-void param_aspect_ratio(ParamHandle *handle, float aspx, float aspy);
-
-void param_face_add(ParamHandle *handle,
- ParamKey key,
- int nverts,
- ParamKey *vkeys,
- float *co[4],
- float *uv[4],
- ParamBool *pin,
- ParamBool *select);
-
-void param_edge_set_seam(ParamHandle *handle, ParamKey *vkeys);
-
-void param_construct_end(ParamHandle *handle,
- ParamBool fill,
- ParamBool topology_from_uvs,
- int *count_fail);
-void param_delete(ParamHandle *handle);
-
-/* Least Squares Conformal Maps:
- * -----------------------------
- * - charts with less than two pinned vertices are assigned 2 pins
- * - lscm is divided in three steps:
- * - begin: compute matrix and its factorization (expensive)
- * - solve using pinned coordinates (cheap)
- * - end: clean up
- * - uv coordinates are allowed to change within begin/end, for
- * quick re-solving
- */
-
-void param_lscm_begin(ParamHandle *handle, ParamBool live, ParamBool abf);
-void param_lscm_solve(ParamHandle *handle, int *count_changed, int *count_failed);
-void param_lscm_end(ParamHandle *handle);
-
-/* Stretch */
-
-void param_stretch_begin(ParamHandle *handle);
-void param_stretch_blend(ParamHandle *handle, float blend);
-void param_stretch_iter(ParamHandle *handle);
-void param_stretch_end(ParamHandle *handle);
-
-/* Area Smooth */
-
-void param_smooth_area(ParamHandle *handle);
-
-/* Packing */
-
-void param_pack(ParamHandle *handle, float margin, bool do_rotate, bool ignore_pinned);
-
-/* Average area for all charts */
-
-void param_average(ParamHandle *handle, bool ignore_pinned);
-
-/* Simple x,y scale */
-
-void param_scale(ParamHandle *handle, float x, float y);
-
-/* Flushing */
-
-void param_flush(ParamHandle *handle);
-void param_flush_restore(ParamHandle *handle);
-
-#ifdef __cplusplus
-}
-#endif
diff --git a/source/blender/editors/uvedit/uvedit_select.c b/source/blender/editors/uvedit/uvedit_select.c
index ed4aa6985c4..1287804d9ee 100644
--- a/source/blender/editors/uvedit/uvedit_select.c
+++ b/source/blender/editors/uvedit/uvedit_select.c
@@ -2052,7 +2052,7 @@ static int uv_select_more_less(bContext *C, const bool select)
}
/* If the current face is not selected and at least one neighboring face is
- * selected, then tag the current face to grow selection.*/
+ * selected, then tag the current face to grow selection. */
if (sel_state == (NEIGHBORING_FACE_IS_SEL | CURR_FACE_IS_UNSEL)) {
BM_elem_flag_enable(efa, BM_ELEM_TAG);
changed = true;
@@ -2622,13 +2622,9 @@ static int uv_select_exec(bContext *C, wmOperator *op)
float co[2];
RNA_float_get_array(op->ptr, "location", co);
- const struct SelectPick_Params params = {
- .sel_op = ED_select_op_from_booleans(RNA_boolean_get(op->ptr, "extend"),
- RNA_boolean_get(op->ptr, "deselect"),
- RNA_boolean_get(op->ptr, "toggle")),
- .deselect_all = RNA_boolean_get(op->ptr, "deselect_all"),
- .select_passthrough = RNA_boolean_get(op->ptr, "select_passthrough"),
- };
+
+ struct SelectPick_Params params = {0};
+ ED_select_pick_params_from_operator(op, &params);
const bool changed = uv_mouse_select(C, co, &params);
@@ -3382,7 +3378,8 @@ static void uv_select_flush_from_tag_loop(const Scene *scene, Object *obedit, co
* but dealing with sticky modes for vertex selections is best done in a separate function.
*
* \note Current behavior is selecting only; deselecting can be added but the behavior isn't
- * required anywhere.*/
+ * required anywhere.
+ */
static void uv_select_flush_from_loop_edge_flag(const Scene *scene, BMEditMesh *em)
{
const ToolSettings *ts = scene->toolsettings;
diff --git a/source/blender/editors/uvedit/uvedit_unwrap_ops.c b/source/blender/editors/uvedit/uvedit_unwrap_ops.c
index 63300656fda..609fa72d56b 100644
--- a/source/blender/editors/uvedit/uvedit_unwrap_ops.c
+++ b/source/blender/editors/uvedit/uvedit_unwrap_ops.c
@@ -46,6 +46,8 @@
#include "DEG_depsgraph.h"
+#include "GEO_uv_parametrizer.h"
+
#include "PIL_time.h"
#include "UI_interface.h"
@@ -64,7 +66,6 @@
#include "WM_types.h"
#include "uvedit_intern.h"
-#include "uvedit_parametrizer.h"
/* -------------------------------------------------------------------- */
/** \name Utility Functions
@@ -319,7 +320,7 @@ static void construct_param_handle_face_add(ParamHandle *handle,
select[i] = uvedit_uv_select_test(scene, l, cd_loop_uv_offset);
}
- param_face_add(handle, key, i, vkeys, co, uv, pin, select);
+ GEO_uv_parametrizer_face_add(handle, key, i, vkeys, co, uv, pin, select);
}
/* See: construct_param_handle_multi to handle multiple objects at once. */
@@ -338,7 +339,7 @@ static ParamHandle *construct_param_handle(const Scene *scene,
const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
- handle = param_construct_begin();
+ handle = GEO_uv_parametrizer_construct_begin();
if (options->correct_aspect) {
float aspx, aspy;
@@ -346,7 +347,7 @@ static ParamHandle *construct_param_handle(const Scene *scene,
ED_uvedit_get_aspect(ob, &aspx, &aspy);
if (aspx != aspy) {
- param_aspect_ratio(handle, aspx, aspy);
+ GEO_uv_parametrizer_aspect_ratio(handle, aspx, aspy);
}
}
@@ -385,15 +386,15 @@ static ParamHandle *construct_param_handle(const Scene *scene,
ParamKey vkeys[2];
vkeys[0] = (ParamKey)BM_elem_index_get(eed->v1);
vkeys[1] = (ParamKey)BM_elem_index_get(eed->v2);
- param_edge_set_seam(handle, vkeys);
+ GEO_uv_parametrizer_edge_set_seam(handle, vkeys);
}
}
}
- param_construct_end(handle,
- options->fill_holes,
- options->topology_from_uvs,
- result_info ? &result_info->count_failed : NULL);
+ GEO_uv_parametrizer_construct_end(handle,
+ options->fill_holes,
+ options->topology_from_uvs,
+ result_info ? &result_info->count_failed : NULL);
return handle;
}
@@ -414,7 +415,7 @@ static ParamHandle *construct_param_handle_multi(const Scene *scene,
BMIter iter, liter;
int i;
- handle = param_construct_begin();
+ handle = GEO_uv_parametrizer_construct_begin();
if (options->correct_aspect) {
Object *ob = objects[0];
@@ -422,7 +423,7 @@ static ParamHandle *construct_param_handle_multi(const Scene *scene,
ED_uvedit_get_aspect(ob, &aspx, &aspy);
if (aspx != aspy) {
- param_aspect_ratio(handle, aspx, aspy);
+ GEO_uv_parametrizer_aspect_ratio(handle, aspx, aspy);
}
}
@@ -474,14 +475,15 @@ static ParamHandle *construct_param_handle_multi(const Scene *scene,
ParamKey vkeys[2];
vkeys[0] = (ParamKey)BM_elem_index_get(eed->v1);
vkeys[1] = (ParamKey)BM_elem_index_get(eed->v2);
- param_edge_set_seam(handle, vkeys);
+ GEO_uv_parametrizer_edge_set_seam(handle, vkeys);
}
}
}
offset += bm->totface;
}
- param_construct_end(handle, options->fill_holes, options->topology_from_uvs, count_fail);
+ GEO_uv_parametrizer_construct_end(
+ handle, options->fill_holes, options->topology_from_uvs, count_fail);
return handle;
}
@@ -560,7 +562,7 @@ static ParamHandle *construct_param_handle_subsurfed(const Scene *scene,
const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
- handle = param_construct_begin();
+ handle = GEO_uv_parametrizer_construct_begin();
if (options->correct_aspect) {
float aspx, aspy;
@@ -568,7 +570,7 @@ static ParamHandle *construct_param_handle_subsurfed(const Scene *scene,
ED_uvedit_get_aspect(ob, &aspx, &aspy);
if (aspx != aspy) {
- param_aspect_ratio(handle, aspx, aspy);
+ GEO_uv_parametrizer_aspect_ratio(handle, aspx, aspy);
}
}
@@ -689,7 +691,7 @@ static ParamHandle *construct_param_handle_subsurfed(const Scene *scene,
&pin[3],
&select[3]);
- param_face_add(handle, key, 4, vkeys, co, uv, pin, select);
+ GEO_uv_parametrizer_face_add(handle, key, 4, vkeys, co, uv, pin, select);
}
/* these are calculated from original mesh too */
@@ -698,14 +700,14 @@ static ParamHandle *construct_param_handle_subsurfed(const Scene *scene,
ParamKey vkeys[2];
vkeys[0] = (ParamKey)edge->v1;
vkeys[1] = (ParamKey)edge->v2;
- param_edge_set_seam(handle, vkeys);
+ GEO_uv_parametrizer_edge_set_seam(handle, vkeys);
}
}
- param_construct_end(handle,
- options->fill_holes,
- options->topology_from_uvs,
- result_info ? &result_info->count_failed : NULL);
+ GEO_uv_parametrizer_construct_end(handle,
+ options->fill_holes,
+ options->topology_from_uvs,
+ result_info ? &result_info->count_failed : NULL);
/* cleanup */
MEM_freeN(faceMap);
@@ -764,9 +766,9 @@ static bool minimize_stretch_init(bContext *C, wmOperator *op)
ms->handle = construct_param_handle_multi(scene, objects, objects_len, &options, NULL);
ms->lasttime = PIL_check_seconds_timer();
- param_stretch_begin(ms->handle);
+ GEO_uv_parametrizer_stretch_begin(ms->handle);
if (ms->blend != 0.0f) {
- param_stretch_blend(ms->handle, ms->blend);
+ GEO_uv_parametrizer_stretch_blend(ms->handle, ms->blend);
}
op->customdata = ms;
@@ -782,8 +784,8 @@ static void minimize_stretch_iteration(bContext *C, wmOperator *op, bool interac
ToolSettings *ts = scene->toolsettings;
const bool synced_selection = (ts->uv_flag & UV_SYNC_SELECTION) != 0;
- param_stretch_blend(ms->handle, ms->blend);
- param_stretch_iter(ms->handle);
+ GEO_uv_parametrizer_stretch_blend(ms->handle, ms->blend);
+ GEO_uv_parametrizer_stretch_iter(ms->handle);
ms->i++;
RNA_int_set(op->ptr, "iterations", ms->i);
@@ -791,7 +793,7 @@ static void minimize_stretch_iteration(bContext *C, wmOperator *op, bool interac
if (interactive && (PIL_check_seconds_timer() - ms->lasttime > 0.5)) {
char str[UI_MAX_DRAW_STR];
- param_flush(ms->handle);
+ GEO_uv_parametrizer_flush(ms->handle);
if (area) {
BLI_snprintf(str, sizeof(str), TIP_("Minimize Stretch. Blend %.2f"), ms->blend);
@@ -831,14 +833,14 @@ static void minimize_stretch_exit(bContext *C, wmOperator *op, bool cancel)
}
if (cancel) {
- param_flush_restore(ms->handle);
+ GEO_uv_parametrizer_flush_restore(ms->handle);
}
else {
- param_flush(ms->handle);
+ GEO_uv_parametrizer_flush(ms->handle);
}
- param_stretch_end(ms->handle);
- param_delete(ms->handle);
+ GEO_uv_parametrizer_stretch_end(ms->handle);
+ GEO_uv_parametrizer_delete(ms->handle);
for (uint ob_index = 0; ob_index < ms->objects_len; ob_index++) {
Object *obedit = ms->objects_edit[ob_index];
@@ -1014,9 +1016,9 @@ static void uvedit_pack_islands(const Scene *scene, Object *ob, BMesh *bm)
ParamHandle *handle;
handle = construct_param_handle(scene, ob, bm, &options, NULL);
- param_pack(handle, scene->toolsettings->uvcalc_margin, rotate, ignore_pinned);
- param_flush(handle);
- param_delete(handle);
+ GEO_uv_parametrizer_pack(handle, scene->toolsettings->uvcalc_margin, rotate, ignore_pinned);
+ GEO_uv_parametrizer_flush(handle);
+ GEO_uv_parametrizer_delete(handle);
}
/**
@@ -1034,9 +1036,9 @@ static void uvedit_pack_islands_multi(const Scene *scene,
{
ParamHandle *handle;
handle = construct_param_handle_multi(scene, objects, objects_len, options, NULL);
- param_pack(handle, scene->toolsettings->uvcalc_margin, rotate, ignore_pinned);
- param_flush(handle);
- param_delete(handle);
+ GEO_uv_parametrizer_pack(handle, scene->toolsettings->uvcalc_margin, rotate, ignore_pinned);
+ GEO_uv_parametrizer_flush(handle);
+ GEO_uv_parametrizer_delete(handle);
for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
Object *obedit = objects[ob_index];
@@ -1167,9 +1169,9 @@ static int average_islands_scale_exec(bContext *C, wmOperator *UNUSED(op))
}
ParamHandle *handle = construct_param_handle_multi(scene, objects, objects_len, &options, NULL);
- param_average(handle, false);
- param_flush(handle);
- param_delete(handle);
+ GEO_uv_parametrizer_average(handle, false);
+ GEO_uv_parametrizer_flush(handle);
+ GEO_uv_parametrizer_delete(handle);
for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
Object *obedit = objects[ob_index];
@@ -1239,7 +1241,7 @@ void ED_uvedit_live_unwrap_begin(Scene *scene, Object *obedit)
handle = construct_param_handle(scene, obedit, em->bm, &options, NULL);
}
- param_lscm_begin(handle, PARAM_TRUE, abf);
+ GEO_uv_parametrizer_lscm_begin(handle, PARAM_TRUE, abf);
/* Create or increase size of g_live_unwrap.handles array */
if (g_live_unwrap.handles == NULL) {
@@ -1261,8 +1263,8 @@ void ED_uvedit_live_unwrap_re_solve(void)
{
if (g_live_unwrap.handles) {
for (int i = 0; i < g_live_unwrap.len; i++) {
- param_lscm_solve(g_live_unwrap.handles[i], NULL, NULL);
- param_flush(g_live_unwrap.handles[i]);
+ GEO_uv_parametrizer_lscm_solve(g_live_unwrap.handles[i], NULL, NULL);
+ GEO_uv_parametrizer_flush(g_live_unwrap.handles[i]);
}
}
}
@@ -1271,11 +1273,11 @@ void ED_uvedit_live_unwrap_end(short cancel)
{
if (g_live_unwrap.handles) {
for (int i = 0; i < g_live_unwrap.len; i++) {
- param_lscm_end(g_live_unwrap.handles[i]);
+ GEO_uv_parametrizer_lscm_end(g_live_unwrap.handles[i]);
if (cancel) {
- param_flush_restore(g_live_unwrap.handles[i]);
+ GEO_uv_parametrizer_flush_restore(g_live_unwrap.handles[i]);
}
- param_delete(g_live_unwrap.handles[i]);
+ GEO_uv_parametrizer_delete(g_live_unwrap.handles[i]);
}
MEM_freeN(g_live_unwrap.handles);
g_live_unwrap.handles = NULL;
@@ -1731,17 +1733,17 @@ static void uvedit_unwrap(const Scene *scene,
handle = construct_param_handle(scene, obedit, em->bm, options, result_info);
}
- param_lscm_begin(handle, PARAM_FALSE, scene->toolsettings->unwrapper == 0);
- param_lscm_solve(handle,
- result_info ? &result_info->count_changed : NULL,
- result_info ? &result_info->count_failed : NULL);
- param_lscm_end(handle);
+ GEO_uv_parametrizer_lscm_begin(handle, PARAM_FALSE, scene->toolsettings->unwrapper == 0);
+ GEO_uv_parametrizer_lscm_solve(handle,
+ result_info ? &result_info->count_changed : NULL,
+ result_info ? &result_info->count_failed : NULL);
+ GEO_uv_parametrizer_lscm_end(handle);
- param_average(handle, true);
+ GEO_uv_parametrizer_average(handle, true);
- param_flush(handle);
+ GEO_uv_parametrizer_flush(handle);
- param_delete(handle);
+ GEO_uv_parametrizer_delete(handle);
}
static void uvedit_unwrap_multi(const Scene *scene,
diff --git a/source/blender/freestyle/intern/python/BPy_Convert.cpp b/source/blender/freestyle/intern/python/BPy_Convert.cpp
index 55a33720465..02ed3f463c7 100644
--- a/source/blender/freestyle/intern/python/BPy_Convert.cpp
+++ b/source/blender/freestyle/intern/python/BPy_Convert.cpp
@@ -569,7 +569,7 @@ bool Vec3r_ptr_from_PyObject(PyObject *obj, Vec3r &vec)
bool Vec2f_ptr_from_Vector(PyObject *obj, Vec2f &vec)
{
- if (!VectorObject_Check(obj) || ((VectorObject *)obj)->size != 2) {
+ if (!VectorObject_Check(obj) || ((VectorObject *)obj)->vec_num != 2) {
return false;
}
if (BaseMath_ReadCallback((BaseMathObject *)obj) == -1) {
@@ -582,7 +582,7 @@ bool Vec2f_ptr_from_Vector(PyObject *obj, Vec2f &vec)
bool Vec3f_ptr_from_Vector(PyObject *obj, Vec3f &vec)
{
- if (!VectorObject_Check(obj) || ((VectorObject *)obj)->size != 3) {
+ if (!VectorObject_Check(obj) || ((VectorObject *)obj)->vec_num != 3) {
return false;
}
if (BaseMath_ReadCallback((BaseMathObject *)obj) == -1) {
@@ -596,7 +596,7 @@ bool Vec3f_ptr_from_Vector(PyObject *obj, Vec3f &vec)
bool Vec3r_ptr_from_Vector(PyObject *obj, Vec3r &vec)
{
- if (!VectorObject_Check(obj) || ((VectorObject *)obj)->size != 3) {
+ if (!VectorObject_Check(obj) || ((VectorObject *)obj)->vec_num != 3) {
return false;
}
if (BaseMath_ReadCallback((BaseMathObject *)obj) == -1) {
@@ -758,7 +758,7 @@ bool Vec3r_ptr_from_PyTuple(PyObject *obj, Vec3r &vec)
bool float_array_from_PyObject(PyObject *obj, float *v, int n)
{
- if (VectorObject_Check(obj) && ((VectorObject *)obj)->size == n) {
+ if (VectorObject_Check(obj) && ((VectorObject *)obj)->vec_num == n) {
if (BaseMath_ReadCallback((BaseMathObject *)obj) == -1) {
return false;
}
diff --git a/source/blender/functions/FN_multi_function_builder.hh b/source/blender/functions/FN_multi_function_builder.hh
index 7ba368d9a9d..2eaada5dea0 100644
--- a/source/blender/functions/FN_multi_function_builder.hh
+++ b/source/blender/functions/FN_multi_function_builder.hh
@@ -49,8 +49,11 @@ template<typename In1, typename Out1> class CustomMF_SI_SO : public MultiFunctio
return [=](IndexMask mask, const VArray<In1> &in1, MutableSpan<Out1> out1) {
/* Devirtualization results in a 2-3x speedup for some simple functions. */
devirtualize_varray(in1, [&](const auto &in1) {
- mask.foreach_index(
- [&](int i) { new (static_cast<void *>(&out1[i])) Out1(element_fn(in1[i])); });
+ mask.to_best_mask_type([&](const auto &mask) {
+ for (const int64_t i : mask) {
+ new (static_cast<void *>(&out1[i])) Out1(element_fn(in1[i]));
+ }
+ });
});
};
}
@@ -102,8 +105,11 @@ class CustomMF_SI_SI_SO : public MultiFunction {
MutableSpan<Out1> out1) {
/* Devirtualization results in a 2-3x speedup for some simple functions. */
devirtualize_varray2(in1, in2, [&](const auto &in1, const auto &in2) {
- mask.foreach_index(
- [&](int i) { new (static_cast<void *>(&out1[i])) Out1(element_fn(in1[i], in2[i])); });
+ mask.to_best_mask_type([&](const auto &mask) {
+ for (const int64_t i : mask) {
+ new (static_cast<void *>(&out1[i])) Out1(element_fn(in1[i], in2[i]));
+ }
+ });
});
};
}
@@ -160,9 +166,11 @@ class CustomMF_SI_SI_SI_SO : public MultiFunction {
const VArray<In2> &in2,
const VArray<In3> &in3,
MutableSpan<Out1> out1) {
- mask.foreach_index([&](int i) {
+ /* Virtual arrays are not devirtualized yet, to avoid generating lots of code without further
+ * consideration. */
+ for (const int64_t i : mask) {
new (static_cast<void *>(&out1[i])) Out1(element_fn(in1[i], in2[i], in3[i]));
- });
+ }
};
}
@@ -223,9 +231,11 @@ class CustomMF_SI_SI_SI_SI_SO : public MultiFunction {
const VArray<In3> &in3,
const VArray<In4> &in4,
MutableSpan<Out1> out1) {
- mask.foreach_index([&](int i) {
+ /* Virtual arrays are not devirtualized yet, to avoid generating lots of code without further
+ * consideration. */
+ for (const int64_t i : mask) {
new (static_cast<void *>(&out1[i])) Out1(element_fn(in1[i], in2[i], in3[i], in4[i]));
- });
+ }
};
}
@@ -268,7 +278,11 @@ template<typename Mut1> class CustomMF_SM : public MultiFunction {
template<typename ElementFuncT> static FunctionT create_function(ElementFuncT element_fn)
{
return [=](IndexMask mask, MutableSpan<Mut1> mut1) {
- mask.foreach_index([&](int i) { element_fn(mut1[i]); });
+ mask.to_best_mask_type([&](const auto &mask) {
+ for (const int64_t i : mask) {
+ element_fn(mut1[i]);
+ }
+ });
};
}
@@ -304,9 +318,11 @@ template<typename From, typename To> class CustomMF_Convert : public MultiFuncti
const VArray<From> &inputs = params.readonly_single_input<From>(0);
MutableSpan<To> outputs = params.uninitialized_single_output<To>(1);
- for (int64_t i : mask) {
- new (static_cast<void *>(&outputs[i])) To(inputs[i]);
- }
+ mask.to_best_mask_type([&](const auto &mask) {
+ for (int64_t i : mask) {
+ new (static_cast<void *>(&outputs[i])) To(inputs[i]);
+ }
+ });
}
};
@@ -366,7 +382,11 @@ template<typename T> class CustomMF_Constant : public MultiFunction {
void call(IndexMask mask, MFParams params, MFContext UNUSED(context)) const override
{
MutableSpan<T> output = params.uninitialized_single_output<T>(0);
- mask.foreach_index([&](int i) { new (&output[i]) T(value_); });
+ mask.to_best_mask_type([&](const auto &mask) {
+ for (const int64_t i : mask) {
+ new (&output[i]) T(value_);
+ }
+ });
}
uint64_t hash() const override
diff --git a/source/blender/functions/intern/field.cc b/source/blender/functions/intern/field.cc
index 9f742f11ce4..986d6ddc19e 100644
--- a/source/blender/functions/intern/field.cc
+++ b/source/blender/functions/intern/field.cc
@@ -489,7 +489,7 @@ void evaluate_constant_field(const GField &field, void *r_value)
{
if (field.node().depends_on_input()) {
const CPPType &type = field.cpp_type();
- type.copy_construct(type.default_value(), r_value);
+ type.value_initialize(r_value);
return;
}
diff --git a/source/blender/geometry/CMakeLists.txt b/source/blender/geometry/CMakeLists.txt
index 0aae19d2eda..8716d6c8f67 100644
--- a/source/blender/geometry/CMakeLists.txt
+++ b/source/blender/geometry/CMakeLists.txt
@@ -9,6 +9,7 @@ set(INC
../functions
../makesdna
../makesrna
+ ../../../intern/eigen
../../../intern/guardedalloc
${CMAKE_BINARY_DIR}/source/blender/makesdna/intern
)
@@ -18,11 +19,13 @@ set(SRC
intern/mesh_to_curve_convert.cc
intern/point_merge_by_distance.cc
intern/realize_instances.cc
+ intern/uv_parametrizer.c
GEO_mesh_merge_by_distance.hh
GEO_mesh_to_curve.hh
GEO_point_merge_by_distance.hh
GEO_realize_instances.hh
+ GEO_uv_parametrizer.h
)
set(LIB
diff --git a/source/blender/geometry/GEO_uv_parametrizer.h b/source/blender/geometry/GEO_uv_parametrizer.h
new file mode 100644
index 00000000000..e25889a0923
--- /dev/null
+++ b/source/blender/geometry/GEO_uv_parametrizer.h
@@ -0,0 +1,134 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#pragma once
+
+#include "BLI_sys_types.h" /* for intptr_t support */
+
+/** \file
+ * \ingroup geo
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef void ParamHandle; /* handle to a set of charts */
+typedef intptr_t ParamKey; /* (hash) key for identifying verts and faces */
+typedef enum ParamBool {
+ PARAM_TRUE = 1,
+ PARAM_FALSE = 0,
+} ParamBool;
+
+/* -------------------------------------------------------------------- */
+/** \name Chart Construction:
+ *
+ * Faces and seams may only be added between #GEO_uv_parametrizer_construct_begin and
+ * #GEO_uv_parametrizer_construct_end.
+ *
+ * The pointers to `co` and `uv` are stored, rather than being copied. Vertices are implicitly
+ * created.
+ *
+ * In #GEO_uv_parametrizer_construct_end the mesh will be split up according to the seams. The
+ * resulting charts must be manifold, connected and open (at least one boundary loop). The output
+ * will be written to the `uv` pointers.
+ *
+ * \{ */
+
+ParamHandle *GEO_uv_parametrizer_construct_begin(void);
+
+void GEO_uv_parametrizer_aspect_ratio(ParamHandle *handle, float aspx, float aspy);
+
+void GEO_uv_parametrizer_face_add(ParamHandle *handle,
+ ParamKey key,
+ int nverts,
+ ParamKey *vkeys,
+ float *co[4],
+ float *uv[4],
+ ParamBool *pin,
+ ParamBool *select);
+
+void GEO_uv_parametrizer_edge_set_seam(ParamHandle *handle, ParamKey *vkeys);
+
+void GEO_uv_parametrizer_construct_end(ParamHandle *handle,
+ ParamBool fill,
+ ParamBool topology_from_uvs,
+ int *count_fail);
+void GEO_uv_parametrizer_delete(ParamHandle *handle);
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Least Squares Conformal Maps:
+ *
+ * Charts with less than two pinned vertices are assigned two pins. LSCM is divided to three steps:
+ *
+ * 1. Begin: compute matrix and its factorization (expensive).
+ * 2. Solve using pinned coordinates (cheap).
+ * 3. End: clean up.
+ *
+ * UV coordinates are allowed to change within begin/end, for quick re-solving.
+ *
+ * \{ */
+
+void GEO_uv_parametrizer_lscm_begin(ParamHandle *handle, ParamBool live, ParamBool abf);
+void GEO_uv_parametrizer_lscm_solve(ParamHandle *handle, int *count_changed, int *count_failed);
+void GEO_uv_parametrizer_lscm_end(ParamHandle *handle);
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Stretch
+ * \{ */
+
+void GEO_uv_parametrizer_stretch_begin(ParamHandle *handle);
+void GEO_uv_parametrizer_stretch_blend(ParamHandle *handle, float blend);
+void GEO_uv_parametrizer_stretch_iter(ParamHandle *handle);
+void GEO_uv_parametrizer_stretch_end(ParamHandle *handle);
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Area Smooth
+ * \{ */
+
+void GEO_uv_parametrizer_smooth_area(ParamHandle *handle);
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Packing
+ * \{ */
+
+void GEO_uv_parametrizer_pack(ParamHandle *handle,
+ float margin,
+ bool do_rotate,
+ bool ignore_pinned);
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Average area for all charts
+ * \{ */
+
+void GEO_uv_parametrizer_average(ParamHandle *handle, bool ignore_pinned);
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Simple x,y scale
+ * \{ */
+
+void GEO_uv_parametrizer_scale(ParamHandle *handle, float x, float y);
+
+/* -------------------------------------------------------------------- */
+/** \name Flushing
+ * \{ */
+
+void GEO_uv_parametrizer_flush(ParamHandle *handle);
+void GEO_uv_parametrizer_flush_restore(ParamHandle *handle);
+
+/** \} */
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/editors/uvedit/uvedit_parametrizer.c b/source/blender/geometry/intern/uv_parametrizer.c
index 5ad326c19e5..7b63dcb5ff0 100644
--- a/source/blender/editors/uvedit/uvedit_parametrizer.c
+++ b/source/blender/geometry/intern/uv_parametrizer.c
@@ -16,7 +16,7 @@
#include "BLI_rand.h"
#include "BLI_utildefines.h"
-#include "uvedit_parametrizer.h"
+#include "GEO_uv_parametrizer.h"
#include <math.h>
#include <stdio.h>
@@ -622,14 +622,14 @@ static void p_chart_topological_sanity_check(PChart *chart)
PEdge *e;
for (v = chart->verts; v; v = v->nextlink) {
- param_test_equals_ptr("v->edge->vert", v, v->edge->vert);
+ GEO_uv_parametrizer_test_equals_ptr("v->edge->vert", v, v->edge->vert);
}
for (e = chart->edges; e; e = e->nextlink) {
if (e->pair) {
- param_test_equals_ptr("e->pair->pair", e, e->pair->pair);
- param_test_equals_ptr("pair->vert", e->vert, e->pair->next->vert);
- param_test_equals_ptr("pair->next->vert", e->next->vert, e->pair->vert);
+ GEO_uv_parametrizer_test_equals_ptr("e->pair->pair", e, e->pair->pair);
+ GEO_uv_parametrizer_test_equals_ptr("pair->vert", e->vert, e->pair->next->vert);
+ GEO_uv_parametrizer_test_equals_ptr("pair->next->vert", e->next->vert, e->pair->vert);
}
}
}
@@ -2119,7 +2119,7 @@ static void p_collapse_cost_vertex(PVert *vert, float *r_mincost, PEdge **r_mine
enext = p_wheel_edge_next(e);
if (enext == NULL) {
- /* the other boundary edge, where we only have the pair halfedge */
+ /* The other boundary edge, where we only have the pair half-edge. */
pair = e->next->next;
if (p_collapse_allowed(NULL, pair)) {
@@ -4359,7 +4359,7 @@ static void p_smooth(PChart *chart)
/* Exported */
-ParamHandle *param_construct_begin(void)
+ParamHandle *GEO_uv_parametrizer_construct_begin(void)
{
PHandle *handle = MEM_callocN(sizeof(*handle), "PHandle");
handle->construction_chart = p_chart_new(handle);
@@ -4378,7 +4378,7 @@ ParamHandle *param_construct_begin(void)
return (ParamHandle *)handle;
}
-void param_aspect_ratio(ParamHandle *handle, float aspx, float aspy)
+void GEO_uv_parametrizer_aspect_ratio(ParamHandle *handle, float aspx, float aspy)
{
PHandle *phandle = (PHandle *)handle;
@@ -4387,7 +4387,7 @@ void param_aspect_ratio(ParamHandle *handle, float aspx, float aspy)
phandle->do_aspect = true;
}
-void param_delete(ParamHandle *handle)
+void GEO_uv_parametrizer_delete(ParamHandle *handle)
{
PHandle *phandle = (PHandle *)handle;
int i;
@@ -4472,20 +4472,20 @@ static void p_add_ngon(ParamHandle *handle,
ParamBool tri_pin[3] = {pin[v0], pin[v1], pin[v2]};
ParamBool tri_select[3] = {select[v0], select[v1], select[v2]};
- param_face_add(handle, key, 3, tri_vkeys, tri_co, tri_uv, tri_pin, tri_select);
+ GEO_uv_parametrizer_face_add(handle, key, 3, tri_vkeys, tri_co, tri_uv, tri_pin, tri_select);
}
BLI_memarena_clear(arena);
}
-void param_face_add(ParamHandle *handle,
- ParamKey key,
- int nverts,
- ParamKey *vkeys,
- float *co[4],
- float *uv[4],
- ParamBool *pin,
- ParamBool *select)
+void GEO_uv_parametrizer_face_add(ParamHandle *handle,
+ ParamKey key,
+ int nverts,
+ ParamKey *vkeys,
+ float *co[4],
+ float *uv[4],
+ ParamBool *pin,
+ ParamBool *select)
{
PHandle *phandle = (PHandle *)handle;
@@ -4514,7 +4514,7 @@ void param_face_add(ParamHandle *handle,
}
}
-void param_edge_set_seam(ParamHandle *handle, ParamKey *vkeys)
+void GEO_uv_parametrizer_edge_set_seam(ParamHandle *handle, ParamKey *vkeys)
{
PHandle *phandle = (PHandle *)handle;
PEdge *e;
@@ -4527,10 +4527,10 @@ void param_edge_set_seam(ParamHandle *handle, ParamKey *vkeys)
}
}
-void param_construct_end(ParamHandle *handle,
- ParamBool fill,
- ParamBool topology_from_uvs,
- int *count_fail)
+void GEO_uv_parametrizer_construct_end(ParamHandle *handle,
+ ParamBool fill,
+ ParamBool topology_from_uvs,
+ int *count_fail)
{
PHandle *phandle = (PHandle *)handle;
PChart *chart = phandle->construction_chart;
@@ -4581,7 +4581,7 @@ void param_construct_end(ParamHandle *handle,
phandle->state = PHANDLE_STATE_CONSTRUCTED;
}
-void param_lscm_begin(ParamHandle *handle, ParamBool live, ParamBool abf)
+void GEO_uv_parametrizer_lscm_begin(ParamHandle *handle, ParamBool live, ParamBool abf)
{
PHandle *phandle = (PHandle *)handle;
PFace *f;
@@ -4598,7 +4598,7 @@ void param_lscm_begin(ParamHandle *handle, ParamBool live, ParamBool abf)
}
}
-void param_lscm_solve(ParamHandle *handle, int *count_changed, int *count_failed)
+void GEO_uv_parametrizer_lscm_solve(ParamHandle *handle, int *count_changed, int *count_failed)
{
PHandle *phandle = (PHandle *)handle;
PChart *chart;
@@ -4638,7 +4638,7 @@ void param_lscm_solve(ParamHandle *handle, int *count_changed, int *count_failed
}
}
-void param_lscm_end(ParamHandle *handle)
+void GEO_uv_parametrizer_lscm_end(ParamHandle *handle)
{
PHandle *phandle = (PHandle *)handle;
int i;
@@ -4655,7 +4655,7 @@ void param_lscm_end(ParamHandle *handle)
phandle->state = PHANDLE_STATE_CONSTRUCTED;
}
-void param_stretch_begin(ParamHandle *handle)
+void GEO_uv_parametrizer_stretch_begin(ParamHandle *handle)
{
PHandle *phandle = (PHandle *)handle;
PChart *chart;
@@ -4685,7 +4685,7 @@ void param_stretch_begin(ParamHandle *handle)
}
}
-void param_stretch_blend(ParamHandle *handle, float blend)
+void GEO_uv_parametrizer_stretch_blend(ParamHandle *handle, float blend)
{
PHandle *phandle = (PHandle *)handle;
@@ -4693,7 +4693,7 @@ void param_stretch_blend(ParamHandle *handle, float blend)
phandle->blend = blend;
}
-void param_stretch_iter(ParamHandle *handle)
+void GEO_uv_parametrizer_stretch_iter(ParamHandle *handle)
{
PHandle *phandle = (PHandle *)handle;
PChart *chart;
@@ -4707,7 +4707,7 @@ void param_stretch_iter(ParamHandle *handle)
}
}
-void param_stretch_end(ParamHandle *handle)
+void GEO_uv_parametrizer_stretch_end(ParamHandle *handle)
{
PHandle *phandle = (PHandle *)handle;
@@ -4718,7 +4718,7 @@ void param_stretch_end(ParamHandle *handle)
phandle->rng = NULL;
}
-void param_smooth_area(ParamHandle *handle)
+void GEO_uv_parametrizer_smooth_area(ParamHandle *handle)
{
PHandle *phandle = (PHandle *)handle;
int i;
@@ -4738,7 +4738,7 @@ void param_smooth_area(ParamHandle *handle)
}
/* don't pack, just rotate (used for better packing) */
-static void param_pack_rotate(ParamHandle *handle, bool ignore_pinned)
+static void GEO_uv_parametrizer_pack_rotate(ParamHandle *handle, bool ignore_pinned)
{
PChart *chart;
int i;
@@ -4756,7 +4756,10 @@ static void param_pack_rotate(ParamHandle *handle, bool ignore_pinned)
}
}
-void param_pack(ParamHandle *handle, float margin, bool do_rotate, bool ignore_pinned)
+void GEO_uv_parametrizer_pack(ParamHandle *handle,
+ float margin,
+ bool do_rotate,
+ bool ignore_pinned)
{
/* box packing variables */
BoxPack *boxarray, *box;
@@ -4775,11 +4778,11 @@ void param_pack(ParamHandle *handle, float margin, bool do_rotate, bool ignore_p
/* this could be its own function */
if (do_rotate) {
- param_pack_rotate(handle, ignore_pinned);
+ GEO_uv_parametrizer_pack_rotate(handle, ignore_pinned);
}
if (phandle->aspx != phandle->aspy) {
- param_scale(handle, 1.0f / phandle->aspx, 1.0f / phandle->aspy);
+ GEO_uv_parametrizer_scale(handle, 1.0f / phandle->aspx, 1.0f / phandle->aspy);
}
/* we may not use all these boxes */
@@ -4856,11 +4859,11 @@ void param_pack(ParamHandle *handle, float margin, bool do_rotate, bool ignore_p
MEM_freeN(boxarray);
if (phandle->aspx != phandle->aspy) {
- param_scale(handle, phandle->aspx, phandle->aspy);
+ GEO_uv_parametrizer_scale(handle, phandle->aspx, phandle->aspy);
}
}
-void param_average(ParamHandle *handle, bool ignore_pinned)
+void GEO_uv_parametrizer_average(ParamHandle *handle, bool ignore_pinned)
{
PChart *chart;
int i;
@@ -4927,7 +4930,7 @@ void param_average(ParamHandle *handle, bool ignore_pinned)
}
}
-void param_scale(ParamHandle *handle, float x, float y)
+void GEO_uv_parametrizer_scale(ParamHandle *handle, float x, float y)
{
PHandle *phandle = (PHandle *)handle;
PChart *chart;
@@ -4939,7 +4942,7 @@ void param_scale(ParamHandle *handle, float x, float y)
}
}
-void param_flush(ParamHandle *handle)
+void GEO_uv_parametrizer_flush(ParamHandle *handle)
{
PHandle *phandle = (PHandle *)handle;
PChart *chart;
@@ -4961,7 +4964,7 @@ void param_flush(ParamHandle *handle)
}
}
-void param_flush_restore(ParamHandle *handle)
+void GEO_uv_parametrizer_flush_restore(ParamHandle *handle)
{
PHandle *phandle = (PHandle *)handle;
PChart *chart;
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilarray.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilarray.c
index fba83579ab1..f3669673094 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpencilarray.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilarray.c
@@ -132,10 +132,10 @@ static void generate_geometry(GpencilModifierData *md,
/* Get bounbox for relative offset. */
float size[3] = {0.0f, 0.0f, 0.0f};
if (mmd->flag & GP_ARRAY_USE_RELATIVE) {
- BoundBox *bb = BKE_object_boundbox_get(ob);
+ BoundBox bb;
const float min[3] = {-1.0f, -1.0f, -1.0f}, max[3] = {1.0f, 1.0f, 1.0f};
- BKE_boundbox_init_from_minmax(bb, min, max);
- BKE_boundbox_calc_size_aabb(bb, size);
+ BKE_boundbox_init_from_minmax(&bb, min, max);
+ BKE_boundbox_calc_size_aabb(&bb, size);
mul_v3_fl(size, 2.0f);
/* Need a minimum size (for flat drawings). */
CLAMP3_MIN(size, 0.01f);
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilbuild.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilbuild.c
index 1a69a6a8a38..930ebb78b46 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpencilbuild.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilbuild.c
@@ -6,6 +6,7 @@
*/
#include <stdio.h>
+#include <stdlib.h>
#include "MEM_guardedalloc.h"
@@ -13,6 +14,7 @@
#include "BLI_blenlib.h"
#include "BLI_math.h"
+#include "BLI_sort.h"
#include "BLT_translation.h"
@@ -25,9 +27,12 @@
#include "DNA_screen_types.h"
#include "BKE_context.h"
+#include "BKE_deform.h"
#include "BKE_gpencil.h"
#include "BKE_gpencil_geom.h"
#include "BKE_gpencil_modifier.h"
+#include "BKE_lib_query.h"
+#include "BKE_modifier.h"
#include "BKE_screen.h"
#include "UI_interface.h"
@@ -99,17 +104,22 @@ static void gpf_clear_all_strokes(bGPDframe *gpf)
* NOTE: This won't be called if all points are present/removed
*/
static void reduce_stroke_points(bGPdata *gpd,
+ bGPDframe *gpf,
bGPDstroke *gps,
- const int num_points,
+ const int points_num,
const eBuildGpencil_Transition transition)
{
- bGPDspoint *new_points = MEM_callocN(sizeof(bGPDspoint) * num_points, __func__);
+ if (points_num == 0) {
+ clear_stroke(gpf, gps);
+ return;
+ }
+ bGPDspoint *new_points = MEM_callocN(sizeof(bGPDspoint) * points_num, __func__);
MDeformVert *new_dvert = NULL;
- if ((gps->dvert != NULL) && (num_points > 0)) {
- new_dvert = MEM_callocN(sizeof(MDeformVert) * num_points, __func__);
+ if ((gps->dvert != NULL) && (points_num > 0)) {
+ new_dvert = MEM_callocN(sizeof(MDeformVert) * points_num, __func__);
}
- /* Which end should points be removed from */
+ /* Which end should points be removed from. */
switch (transition) {
case GP_BUILD_TRANSITION_GROW: /* Show in forward order =
* Remove ungrown-points from end of stroke. */
@@ -117,12 +127,12 @@ static void reduce_stroke_points(bGPdata *gpd,
* Remove dead-points from end of stroke. */
{
/* copy over point data */
- memcpy(new_points, gps->points, sizeof(bGPDspoint) * num_points);
- if ((gps->dvert != NULL) && (num_points > 0)) {
- memcpy(new_dvert, gps->dvert, sizeof(MDeformVert) * num_points);
+ memcpy(new_points, gps->points, sizeof(bGPDspoint) * points_num);
+ if ((gps->dvert != NULL) && (points_num > 0)) {
+ memcpy(new_dvert, gps->dvert, sizeof(MDeformVert) * points_num);
/* free unused point weights */
- for (int i = num_points; i < gps->totpoints; i++) {
+ for (int i = points_num; i < gps->totpoints; i++) {
MDeformVert *dvert = &gps->dvert[i];
BKE_gpencil_free_point_weights(dvert);
}
@@ -131,16 +141,16 @@ static void reduce_stroke_points(bGPdata *gpd,
}
/* Hide in forward order = Remove points from start of stroke */
- case GP_BUILD_TRANSITION_FADE: {
- /* num_points is the number of points left after reducing.
+ case GP_BUILD_TRANSITION_VANISH: {
+ /* points_num is the number of points left after reducing.
* We need to know how many to remove
*/
- const int offset = gps->totpoints - num_points;
+ const int offset = gps->totpoints - points_num;
/* copy over point data */
- memcpy(new_points, gps->points + offset, sizeof(bGPDspoint) * num_points);
- if ((gps->dvert != NULL) && (num_points > 0)) {
- memcpy(new_dvert, gps->dvert + offset, sizeof(MDeformVert) * num_points);
+ memcpy(new_points, gps->points + offset, sizeof(bGPDspoint) * points_num);
+ if ((gps->dvert != NULL) && (points_num > 0)) {
+ memcpy(new_dvert, gps->dvert + offset, sizeof(MDeformVert) * points_num);
/* free unused weights */
for (int i = 0; i < offset; i++) {
@@ -161,12 +171,63 @@ static void reduce_stroke_points(bGPdata *gpd,
MEM_SAFE_FREE(gps->dvert);
gps->points = new_points;
gps->dvert = new_dvert;
- gps->totpoints = num_points;
+ gps->totpoints = points_num;
/* Calc geometry data. */
BKE_gpencil_stroke_geometry_update(gpd, gps);
}
+static void fade_stroke_points(bGPDstroke *gps,
+ const int starting_index,
+ const int ending_index,
+ const float starting_weight,
+ const float ending_weight,
+ const int target_def_nr,
+ const eBuildGpencil_Transition transition,
+ const float thickness_strength,
+ const float opacity_strength)
+{
+ MDeformVert *dvert;
+
+ int range = ending_index - starting_index;
+ if (!range) {
+ range = 1;
+ }
+
+ /* Which end should points be removed from */
+ switch (transition) {
+ /* Because starting_weight and ending_weight are set in correct order before calling this
+ * function, those three modes can use the same interpolation code. */
+ case GP_BUILD_TRANSITION_GROW:
+ case GP_BUILD_TRANSITION_SHRINK:
+ case GP_BUILD_TRANSITION_VANISH: {
+ for (int i = starting_index; i <= ending_index; i++) {
+ float weight = interpf(
+ ending_weight, starting_weight, (float)(i - starting_index) / range);
+ if (target_def_nr >= 0) {
+ dvert = &gps->dvert[i];
+ MDeformWeight *dw = BKE_defvert_ensure_index(dvert, target_def_nr);
+ if (dw) {
+ dw->weight = weight;
+ CLAMP(dw->weight, 0.0f, 1.0f);
+ }
+ }
+ if (thickness_strength > 1e-5) {
+ gps->points[i].pressure *= interpf(weight, 1.0f, thickness_strength);
+ }
+ if (opacity_strength > 1e-5) {
+ gps->points[i].strength *= interpf(weight, 1.0f, opacity_strength);
+ }
+ }
+ break;
+ }
+
+ default:
+ printf("ERROR: Unknown transition %d in %s()\n", (int)transition, __func__);
+ break;
+ }
+}
+
/* --------------------------------------------- */
/* Stroke Data Table Entry - This represents one stroke being generated */
@@ -178,11 +239,26 @@ typedef struct tStrokeBuildDetails {
/* Number of points - Cache for more convenient access */
int totpoints;
+
+ /* Distance to control object, used to sort the strokes if set. */
+ float distance;
} tStrokeBuildDetails;
+static int cmp_stroke_build_details(const void *ps1, const void *ps2)
+{
+ tStrokeBuildDetails *p1 = (tStrokeBuildDetails *)ps1;
+ tStrokeBuildDetails *p2 = (tStrokeBuildDetails *)ps2;
+ return p1->distance > p2->distance ? 1 : (p1->distance == p2->distance ? 0 : -1);
+}
+
/* Sequential and additive - Show strokes one after the other. */
-static void build_sequential(
- BuildGpencilModifierData *mmd, bGPdata *gpd, bGPDframe *gpf, float fac, bool additive)
+static void build_sequential(Object *ob,
+ BuildGpencilModifierData *mmd,
+ bGPdata *gpd,
+ bGPDframe *gpf,
+ const int target_def_nr,
+ float fac,
+ bool additive)
{
size_t tot_strokes = BLI_listbase_count(&gpf->strokes);
size_t start_stroke;
@@ -222,6 +298,26 @@ static void build_sequential(
cell->totpoints = gps->totpoints;
totpoints += cell->totpoints;
+
+ /* Compute distance to control object if set, and build according to that order. */
+ if (mmd->object) {
+ float sv1[3], sv2[3];
+ mul_v3_m4v3(sv1, ob->obmat, &gps->points[0].x);
+ mul_v3_m4v3(sv2, ob->obmat, &gps->points[gps->totpoints - 1].x);
+ float dist_l = len_v3v3(sv1, mmd->object->loc);
+ float dist_r = len_v3v3(sv2, mmd->object->loc);
+ if (dist_r < dist_l) {
+ BKE_gpencil_stroke_flip(gps);
+ cell->distance = dist_r;
+ }
+ else {
+ cell->distance = dist_l;
+ }
+ }
+ }
+
+ if (mmd->object) {
+ qsort(table, tot_strokes, sizeof(tStrokeBuildDetails), cmp_stroke_build_details);
}
/* 2.2) Second pass - Compute the overall indices for points */
@@ -240,6 +336,17 @@ static void build_sequential(
/* 3) Determine the global indices for points that should be visible */
size_t first_visible = 0;
size_t last_visible = 0;
+ /* Need signed numbers because the representation of fading offset would exceed the beginning and
+ * the end of offsets. */
+ int fade_start = 0;
+ int fade_end = 0;
+
+ bool fading_enabled = (mmd->flag & GP_BUILD_USE_FADING);
+
+ float set_fade_fac = fading_enabled ? mmd->fade_fac : 0.0f;
+ float use_fac = interpf(1 + set_fade_fac, 0, fac);
+ float use_fade_fac = use_fac - set_fade_fac;
+ CLAMP(use_fade_fac, 0.0f, 1.0f);
switch (mmd->transition) {
/* Show in forward order
@@ -247,7 +354,9 @@ static void build_sequential(
*/
case GP_BUILD_TRANSITION_GROW:
first_visible = 0; /* always visible */
- last_visible = (size_t)roundf(totpoints * fac);
+ last_visible = (size_t)roundf(totpoints * use_fac);
+ fade_start = (int)roundf(totpoints * use_fade_fac);
+ fade_end = last_visible;
break;
/* Hide in reverse order
@@ -255,15 +364,19 @@ static void build_sequential(
*/
case GP_BUILD_TRANSITION_SHRINK:
first_visible = 0; /* always visible (until last point removed) */
- last_visible = (size_t)(totpoints * (1.0f - fac));
+ last_visible = (size_t)(totpoints * (1.0f + set_fade_fac - use_fac));
+ fade_start = (int)roundf(totpoints * (1.0f - use_fade_fac - set_fade_fac));
+ fade_end = last_visible;
break;
/* Hide in forward order
* - As fac increases, the early points start getting hidden
*/
- case GP_BUILD_TRANSITION_FADE:
- first_visible = (size_t)(totpoints * fac);
+ case GP_BUILD_TRANSITION_VANISH:
+ first_visible = (size_t)(totpoints * use_fade_fac);
last_visible = totpoints; /* i.e. visible until the end, unless first overlaps this */
+ fade_start = first_visible;
+ fade_end = (int)roundf(totpoints * use_fac);
break;
}
@@ -277,19 +390,43 @@ static void build_sequential(
clear_stroke(gpf, cell->gps);
}
else {
+ if (fade_start != fade_end && (int)cell->start_idx < fade_end &&
+ (int)cell->end_idx > fade_start) {
+ int start_index = fade_start - cell->start_idx;
+ int end_index = cell->totpoints + fade_end - cell->end_idx - 1;
+ CLAMP(start_index, 0, cell->totpoints - 1);
+ CLAMP(end_index, 0, cell->totpoints - 1);
+ float start_weight = ratiof(fade_start, fade_end, cell->start_idx + start_index);
+ float end_weight = ratiof(fade_start, fade_end, cell->start_idx + end_index);
+ if (mmd->transition != GP_BUILD_TRANSITION_VANISH) {
+ start_weight = 1.0f - start_weight;
+ end_weight = 1.0f - end_weight;
+ }
+ fade_stroke_points(cell->gps,
+ start_index,
+ end_index,
+ start_weight,
+ end_weight,
+ target_def_nr,
+ mmd->transition,
+ mmd->fade_thickness_strength,
+ mmd->fade_opacity_strength);
+ /* Calc geometry data. */
+ BKE_gpencil_stroke_geometry_update(gpd, cell->gps);
+ }
/* Some proportion of stroke is visible */
if ((first_visible <= cell->start_idx) && (last_visible >= cell->end_idx)) {
/* Do nothing - whole stroke is visible */
}
else if (first_visible > cell->start_idx) {
/* Starts partway through this stroke */
- int num_points = cell->end_idx - first_visible;
- reduce_stroke_points(gpd, cell->gps, num_points, mmd->transition);
+ int points_num = cell->end_idx - first_visible;
+ reduce_stroke_points(gpd, gpf, cell->gps, points_num, mmd->transition);
}
else {
/* Ends partway through this stroke */
- int num_points = last_visible - cell->start_idx;
- reduce_stroke_points(gpd, cell->gps, num_points, mmd->transition);
+ int points_num = last_visible - cell->start_idx;
+ reduce_stroke_points(gpd, gpf, cell->gps, points_num, mmd->transition);
}
}
}
@@ -304,6 +441,7 @@ static void build_sequential(
static void build_concurrent(BuildGpencilModifierData *mmd,
bGPdata *gpd,
bGPDframe *gpf,
+ const int target_def_nr,
float fac)
{
bGPDstroke *gps, *gps_next;
@@ -323,6 +461,12 @@ static void build_concurrent(BuildGpencilModifierData *mmd,
return;
}
+ bool fading_enabled = (mmd->flag & GP_BUILD_USE_FADING);
+ float set_fade_fac = fading_enabled ? mmd->fade_fac : 0.0f;
+ float use_fac = interpf(1 + set_fade_fac, 0, fac);
+ use_fac = reverse ? use_fac - set_fade_fac : use_fac;
+ int fade_points = set_fade_fac * max_points;
+
/* 2) For each stroke, determine how it should be handled */
for (gps = gpf->strokes.first; gps; gps = gps_next) {
gps_next = gps->next;
@@ -333,31 +477,19 @@ static void build_concurrent(BuildGpencilModifierData *mmd,
const float relative_len = (float)gps->totpoints / (float)max_points;
/* Determine how many points should be left in the stroke */
- int num_points = 0;
+ int points_num = 0;
switch (mmd->time_alignment) {
case GP_BUILD_TIMEALIGN_START: /* all start on frame 1 */
{
- /* Build effect occurs over when fac = 0, to fac = relative_len */
- if (fac <= relative_len) {
- /* Scale fac to fit relative_len */
- const float scaled_fac = fac / MAX2(relative_len, PSEUDOINVERSE_EPSILON);
+ /* Scale fac to fit relative_len */
+ const float scaled_fac = use_fac / MAX2(relative_len, PSEUDOINVERSE_EPSILON);
- if (reverse) {
- num_points = (int)roundf((1.0f - scaled_fac) * gps->totpoints);
- }
- else {
- num_points = (int)roundf(scaled_fac * gps->totpoints);
- }
+ if (reverse) {
+ points_num = (int)roundf((1.0f - scaled_fac) * gps->totpoints);
}
else {
- /* Build effect has ended */
- if (reverse) {
- num_points = 0;
- }
- else {
- num_points = gps->totpoints;
- }
+ points_num = (int)roundf(scaled_fac * gps->totpoints);
}
break;
@@ -368,24 +500,13 @@ static void build_concurrent(BuildGpencilModifierData *mmd,
*/
const float start_fac = 1.0f - relative_len;
- if (fac >= start_fac) {
- const float scaled_fac = (fac - start_fac) / MAX2(relative_len, PSEUDOINVERSE_EPSILON);
+ const float scaled_fac = (use_fac - start_fac) / MAX2(relative_len, PSEUDOINVERSE_EPSILON);
- if (reverse) {
- num_points = (int)roundf((1.0f - scaled_fac) * gps->totpoints);
- }
- else {
- num_points = (int)roundf(scaled_fac * gps->totpoints);
- }
+ if (reverse) {
+ points_num = (int)roundf((1.0f - scaled_fac) * gps->totpoints);
}
else {
- /* Build effect hasn't started */
- if (reverse) {
- num_points = gps->totpoints;
- }
- else {
- num_points = 0;
- }
+ points_num = (int)roundf(scaled_fac * gps->totpoints);
}
break;
@@ -393,21 +514,54 @@ static void build_concurrent(BuildGpencilModifierData *mmd,
}
/* Modify the stroke geometry */
- if (num_points <= 0) {
+ if (points_num <= 0) {
/* Nothing Left - Delete the stroke */
clear_stroke(gpf, gps);
}
- else if (num_points < gps->totpoints) {
- /* Remove some points */
- reduce_stroke_points(gpd, gps, num_points, mmd->transition);
+ else {
+ int more_points = points_num - gps->totpoints;
+ CLAMP(more_points, 0, fade_points + 1);
+ float max_weight = (float)(points_num + more_points) / fade_points;
+ CLAMP(max_weight, 0.0f, 1.0f);
+ int starting_index = mmd->transition == GP_BUILD_TRANSITION_VANISH ?
+ gps->totpoints - points_num - more_points :
+ points_num - 1 - fade_points + more_points;
+ int ending_index = mmd->transition == GP_BUILD_TRANSITION_VANISH ?
+ gps->totpoints - points_num + fade_points - more_points :
+ points_num - 1 + more_points;
+ float starting_weight = mmd->transition == GP_BUILD_TRANSITION_VANISH ?
+ ((float)more_points / fade_points) :
+ max_weight;
+ float ending_weight = mmd->transition == GP_BUILD_TRANSITION_VANISH ?
+ max_weight :
+ ((float)more_points / fade_points);
+ CLAMP(starting_index, 0, gps->totpoints - 1);
+ CLAMP(ending_index, 0, gps->totpoints - 1);
+ fade_stroke_points(gps,
+ starting_index,
+ ending_index,
+ starting_weight,
+ ending_weight,
+ target_def_nr,
+ mmd->transition,
+ mmd->fade_thickness_strength,
+ mmd->fade_opacity_strength);
+ if (points_num < gps->totpoints) {
+ /* Remove some points */
+ reduce_stroke_points(gpd, gpf, gps, points_num, mmd->transition);
+ }
}
}
}
/* --------------------------------------------- */
-static void generate_geometry(
- GpencilModifierData *md, Depsgraph *depsgraph, bGPdata *gpd, bGPDlayer *gpl, bGPDframe *gpf)
+static void generate_geometry(GpencilModifierData *md,
+ Depsgraph *depsgraph,
+ Object *ob,
+ bGPdata *gpd,
+ bGPDlayer *gpl,
+ bGPDframe *gpf)
{
BuildGpencilModifierData *mmd = (BuildGpencilModifierData *)md;
if (mmd->mode == GP_BUILD_MODE_ADDITIVE) {
@@ -450,6 +604,25 @@ static void generate_geometry(
}
}
+ int target_def_nr = -1;
+ if (mmd->flag & GP_BUILD_USE_FADING) {
+ /* If there are weight output, initialize it with a default weight of 1. */
+ target_def_nr = BKE_object_defgroup_name_index(ob, mmd->target_vgname);
+ if (target_def_nr >= 0) {
+ LISTBASE_FOREACH (bGPDstroke *, fgps, &gpf->strokes) {
+ BKE_gpencil_dvert_ensure(fgps);
+ /* Assign a initial weight of 1, and only process those who needs additional fading. */
+ for (int j = 0; j < fgps->totpoints; j++) {
+ MDeformVert *dvert = &fgps->dvert[j];
+ MDeformWeight *dw = BKE_defvert_ensure_index(dvert, target_def_nr);
+ if (dw) {
+ dw->weight = 1.0f;
+ }
+ }
+ }
+ }
+ }
+
/* Early exit if outside of the frame range for this modifier
* (e.g. to have one forward, and one backwards modifier)
*/
@@ -517,15 +690,15 @@ static void generate_geometry(
/* Time management mode */
switch (mmd->mode) {
case GP_BUILD_MODE_SEQUENTIAL:
- build_sequential(mmd, gpd, gpf, fac, false);
+ build_sequential(ob, mmd, gpd, gpf, target_def_nr, fac, false);
break;
case GP_BUILD_MODE_CONCURRENT:
- build_concurrent(mmd, gpd, gpf, fac);
+ build_concurrent(mmd, gpd, gpf, target_def_nr, fac);
break;
case GP_BUILD_MODE_ADDITIVE:
- build_sequential(mmd, gpd, gpf, fac, true);
+ build_sequential(ob, mmd, gpd, gpf, target_def_nr, fac, true);
break;
default:
@@ -547,7 +720,7 @@ static void generateStrokes(GpencilModifierData *md, Depsgraph *depsgraph, Objec
if (gpf == NULL) {
continue;
}
- generate_geometry(md, depsgraph, gpd, gpl, gpf);
+ generate_geometry(md, depsgraph, ob, gpd, gpl, gpf);
}
}
@@ -583,7 +756,7 @@ static void panel_draw(const bContext *UNUSED(C), Panel *panel)
uiItemS(layout);
- row = uiLayoutRowWithHeading(layout, true, IFACE_("Use Factor"));
+ row = uiLayoutRowWithHeading(layout, true, IFACE_("Factor"));
uiLayoutSetPropDecorate(row, false);
uiItemR(row, ptr, "use_percentage", 0, "", ICON_NONE);
sub = uiLayoutRow(row, true);
@@ -591,6 +764,12 @@ static void panel_draw(const bContext *UNUSED(C), Panel *panel)
uiItemR(sub, ptr, "percentage_factor", 0, "", ICON_NONE);
uiItemDecoratorR(row, ptr, "percentage_factor", 0);
+ uiItemS(layout);
+
+ if (ELEM(mode, GP_BUILD_MODE_SEQUENTIAL, GP_BUILD_MODE_ADDITIVE)) {
+ uiItemR(layout, ptr, "object", 0, NULL, ICON_NONE);
+ }
+
/* Check for incompatible time modifier. */
Object *ob = ob_ptr.data;
GpencilModifierData *md = ptr->data;
@@ -624,6 +803,40 @@ static void frame_range_panel_draw(const bContext *UNUSED(C), Panel *panel)
uiItemR(col, ptr, "frame_end", 0, IFACE_("End"), ICON_NONE);
}
+static void fading_header_draw(const bContext *UNUSED(C), Panel *panel)
+{
+ uiLayout *layout = panel->layout;
+
+ PointerRNA *ptr = gpencil_modifier_panel_get_property_pointers(panel, NULL);
+
+ uiItemR(layout, ptr, "use_fading", 0, IFACE_("Fade"), ICON_NONE);
+}
+
+static void fading_panel_draw(const bContext *UNUSED(C), Panel *panel)
+{
+ uiLayout *col;
+ uiLayout *layout = panel->layout;
+
+ PointerRNA ob_ptr;
+ PointerRNA *ptr = gpencil_modifier_panel_get_property_pointers(panel, &ob_ptr);
+
+ uiLayoutSetPropSep(layout, true);
+
+ uiItemR(layout, ptr, "fade_factor", 0, IFACE_("Factor"), ICON_NONE);
+
+ col = uiLayoutColumn(layout, true);
+ uiItemR(col, ptr, "fade_thickness_strength", 0, IFACE_("Thickness"), ICON_NONE);
+ uiItemR(col, ptr, "fade_opacity_strength", 0, IFACE_("Opacity"), ICON_NONE);
+
+ uiItemPointerR(layout,
+ ptr,
+ "target_vertex_group",
+ &ob_ptr,
+ "vertex_groups",
+ IFACE_("Weight Output"),
+ ICON_NONE);
+}
+
static void mask_panel_draw(const bContext *UNUSED(C), Panel *panel)
{
gpencil_modifier_masking_panel_draw(panel, false, false);
@@ -636,9 +849,30 @@ static void panelRegister(ARegionType *region_type)
gpencil_modifier_subpanel_register(
region_type, "frame_range", "", frame_range_header_draw, frame_range_panel_draw, panel_type);
gpencil_modifier_subpanel_register(
+ region_type, "fading", "", fading_header_draw, fading_panel_draw, panel_type);
+ gpencil_modifier_subpanel_register(
region_type, "_mask", "Influence", NULL, mask_panel_draw, panel_type);
}
+static void foreachIDLink(GpencilModifierData *md, Object *ob, IDWalkFunc walk, void *userData)
+{
+ BuildGpencilModifierData *mmd = (BuildGpencilModifierData *)md;
+
+ walk(userData, ob, (ID **)&mmd->object, IDWALK_CB_NOP);
+}
+
+static void updateDepsgraph(GpencilModifierData *md,
+ const ModifierUpdateDepsgraphContext *ctx,
+ const int UNUSED(mode))
+{
+ BuildGpencilModifierData *lmd = (BuildGpencilModifierData *)md;
+ if (lmd->object != NULL) {
+ DEG_add_object_relation(ctx->node, lmd->object, DEG_OB_COMP_GEOMETRY, "Build Modifier");
+ DEG_add_object_relation(ctx->node, lmd->object, DEG_OB_COMP_TRANSFORM, "Build Modifier");
+ }
+ DEG_add_object_relation(ctx->node, ctx->object, DEG_OB_COMP_TRANSFORM, "Build Modifier");
+}
+
/* ******************************************** */
GpencilModifierTypeInfo modifierType_Gpencil_Build = {
@@ -658,9 +892,9 @@ GpencilModifierTypeInfo modifierType_Gpencil_Build = {
/* initData */ initData,
/* freeData */ NULL,
/* isDisabled */ NULL,
- /* updateDepsgraph */ NULL,
+ /* updateDepsgraph */ updateDepsgraph,
/* dependsOnTime */ dependsOnTime,
- /* foreachIDLink */ NULL,
+ /* foreachIDLink */ foreachIDLink,
/* foreachTexLink */ NULL,
/* panelRegister */ panelRegister,
};
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilsmooth.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilsmooth.c
index eb51a247d87..1992ebd1508 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpencilsmooth.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilsmooth.c
@@ -178,7 +178,7 @@ static void panel_draw(const bContext *UNUSED(C), Panel *panel)
col = uiLayoutColumn(layout, false);
uiLayoutSetActive(col, RNA_boolean_get(ptr, "use_edit_position"));
- uiItemR(col, ptr, "keep_shape", 0, NULL, ICON_NONE);
+ uiItemR(col, ptr, "use_keep_shape", 0, NULL, ICON_NONE);
gpencil_modifier_panel_end(layout, ptr);
}
diff --git a/source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.c b/source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.c
index c96321b67aa..08737c19eef 100644
--- a/source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.c
+++ b/source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.c
@@ -1783,7 +1783,7 @@ static void lineart_geometry_object_load(LineartObjectInfo *obi, LineartRenderBu
BM_mesh_elem_hflag_disable_all(bm, BM_FACE | BM_EDGE, BM_ELEM_TAG, false);
BM_mesh_triangulate(
- bm, MOD_TRIANGULATE_QUAD_FIXED, MOD_TRIANGULATE_NGON_BEAUTY, 4, false, NULL, NULL, NULL);
+ bm, MOD_TRIANGULATE_QUAD_BEAUTY, MOD_TRIANGULATE_NGON_BEAUTY, 4, false, NULL, NULL, NULL);
BM_mesh_normals_update(bm);
BM_mesh_elem_table_ensure(bm, BM_VERT | BM_EDGE | BM_FACE);
BM_mesh_elem_index_ensure(bm, BM_VERT | BM_EDGE | BM_FACE);
@@ -2095,7 +2095,7 @@ static bool lineart_geometry_check_visible(double (*model_view_proj)[4],
double shift_y,
Object *use_ob)
{
- BoundBox *bb = BKE_object_boundbox_get(use_ob);
+ const BoundBox *bb = BKE_object_boundbox_get(use_ob);
if (!bb) {
/* For lights and empty stuff there will be no bbox. */
return false;
diff --git a/source/blender/gpu/CMakeLists.txt b/source/blender/gpu/CMakeLists.txt
index 1840b5447e3..3e12426acdc 100644
--- a/source/blender/gpu/CMakeLists.txt
+++ b/source/blender/gpu/CMakeLists.txt
@@ -414,6 +414,8 @@ list(APPEND INC ${CMAKE_CURRENT_BINARY_DIR})
set(SRC_SHADER_CREATE_INFOS
../draw/engines/gpencil/shaders/infos/gpencil_info.hh
../draw/engines/gpencil/shaders/infos/gpencil_vfx_info.hh
+ ../draw/engines/overlay/shaders/infos/armature_info.hh
+ ../draw/engines/overlay/shaders/infos/edit_mode_info.hh
../draw/engines/workbench/shaders/infos/workbench_composite_info.hh
../draw/engines/workbench/shaders/infos/workbench_effect_antialiasing_info.hh
../draw/engines/workbench/shaders/infos/workbench_effect_cavity_info.hh
@@ -503,16 +505,32 @@ endif()
if(WITH_GPU_SHADER_BUILDER)
- add_executable(shader_builder
- intern/gpu_shader_builder.cc
- intern/gpu_shader_builder_stubs.cc
- ${shader_create_info_list_file}
- )
+ # TODO(@fclem) Fix this mess.
+ if(APPLE)
+ add_executable(shader_builder
+ intern/gpu_shader_builder.cc
+ ${shader_create_info_list_file}
+ )
+
+ setup_platform_linker_flags(shader_builder)
+
+ target_link_libraries(shader_builder PUBLIC
+ bf_blenkernel
+ buildinfoobj
+ )
+ else()
+ add_executable(shader_builder
+ intern/gpu_shader_builder.cc
+ intern/gpu_shader_builder_stubs.cc
+ ${shader_create_info_list_file}
+ )
+
+ target_link_libraries(shader_builder PUBLIC
+ bf_blenkernel
+ ${PLATFORM_LINKLIBS}
+ )
+ endif()
- target_link_libraries(shader_builder PUBLIC
- bf_blenkernel
- ${PLATFORM_LINKLIBS}
- )
target_include_directories(shader_builder PRIVATE ${INC} ${CMAKE_CURRENT_BINARY_DIR})
set(SRC_BAKED_CREATE_INFOS_FILE ${CMAKE_CURRENT_BINARY_DIR}/shader_baked.hh)
diff --git a/source/blender/gpu/GPU_primitive.h b/source/blender/gpu/GPU_primitive.h
index 66759cf22d7..4860b037bfb 100644
--- a/source/blender/gpu/GPU_primitive.h
+++ b/source/blender/gpu/GPU_primitive.h
@@ -20,10 +20,12 @@ typedef enum {
GPU_PRIM_LINES,
GPU_PRIM_TRIS,
GPU_PRIM_LINE_STRIP,
- GPU_PRIM_LINE_LOOP, /* GL has this, Vulkan does not */
+ GPU_PRIM_LINE_LOOP, /* GL has this, Vulkan and Metal do not */
GPU_PRIM_TRI_STRIP,
- GPU_PRIM_TRI_FAN,
+ GPU_PRIM_TRI_FAN, /* Metal API does not support this. */
+ /* Metal API does not support ADJ primitive types but
+ * handled via the geometry-shader-alternative path. */
GPU_PRIM_LINES_ADJ,
GPU_PRIM_TRIS_ADJ,
GPU_PRIM_LINE_STRIP_ADJ,
diff --git a/source/blender/gpu/intern/gpu_batch_presets.c b/source/blender/gpu/intern/gpu_batch_presets.c
index c1c884ed028..ab5e23a846c 100644
--- a/source/blender/gpu/intern/gpu_batch_presets.c
+++ b/source/blender/gpu/intern/gpu_batch_presets.c
@@ -19,6 +19,7 @@
#include "GPU_batch.h"
#include "GPU_batch_presets.h" /* own include */
#include "GPU_batch_utils.h"
+#include "GPU_context.h"
/* -------------------------------------------------------------------- */
/** \name Local Structures
@@ -320,11 +321,12 @@ GPUBatch *GPU_batch_preset_quad(void)
GPUVertBuf *vbo = GPU_vertbuf_create_with_format(preset_2d_format());
GPU_vertbuf_data_alloc(vbo, 4);
- float pos_data[4][2] = {{0.0f, 0.0f}, {0.0f, 1.0f}, {1.0f, 1.0f}, {1.0f, 0.0f}};
+ float pos_data[4][2] = {{0.0f, 0.0f}, {0.0f, 1.0f}, {1.0f, 0.0f}, {1.0f, 1.0f}};
GPU_vertbuf_attr_fill(vbo, g_presets_2d.attr_id.pos, pos_data);
/* Don't fill the color. */
- g_presets_2d.batch.quad = GPU_batch_create_ex(GPU_PRIM_TRI_FAN, vbo, NULL, GPU_BATCH_OWNS_VBO);
+ g_presets_2d.batch.quad = GPU_batch_create_ex(
+ GPU_PRIM_TRI_STRIP, vbo, NULL, GPU_BATCH_OWNS_VBO);
gpu_batch_presets_register(g_presets_2d.batch.quad);
}
diff --git a/source/blender/gpu/intern/gpu_shader_create_info.cc b/source/blender/gpu/intern/gpu_shader_create_info.cc
index aef1984687d..0dd82d4ea44 100644
--- a/source/blender/gpu/intern/gpu_shader_create_info.cc
+++ b/source/blender/gpu/intern/gpu_shader_create_info.cc
@@ -65,6 +65,9 @@ void ShaderCreateInfo::finalize()
if (info.early_fragment_test_) {
early_fragment_test_ = true;
}
+ if (info.depth_write_ != DepthWrite::ANY) {
+ depth_write_ = info.depth_write_;
+ }
validate(info);
@@ -102,8 +105,6 @@ void ShaderCreateInfo::finalize()
assert_no_overlap(compute_source_.is_empty(), "Compute source already existing");
compute_source_ = info.compute_source_;
}
-
- do_static_compilation_ = do_static_compilation_ || info.do_static_compilation_;
}
if (auto_resource_location_) {
@@ -264,9 +265,14 @@ bool gpu_shader_create_info_compile_all()
{
using namespace blender::gpu;
int success = 0;
+ int skipped = 0;
int total = 0;
for (ShaderCreateInfo *info : g_create_infos->values()) {
if (info->do_static_compilation_) {
+ if (GPU_compute_shader_support() == false && info->compute_source_ != nullptr) {
+ skipped++;
+ continue;
+ }
total++;
GPUShader *shader = GPU_shader_create_from_info(
reinterpret_cast<const GPUShaderCreateInfo *>(info));
@@ -322,12 +328,11 @@ bool gpu_shader_create_info_compile_all()
GPU_shader_free(shader);
}
}
- printf("===============================\n");
- printf("Shader Test compilation result: \n");
- printf("%d Total\n", total);
- printf("%d Passed\n", success);
- printf("%d Failed\n", total - success);
- printf("===============================\n");
+ printf("Shader Test compilation result: %d / %d passed", success, total);
+ if (skipped > 0) {
+ printf(" (skipped %d for compatibility reasons)", skipped);
+ }
+ printf("\n");
return success == total;
}
diff --git a/source/blender/gpu/intern/gpu_shader_create_info.hh b/source/blender/gpu/intern/gpu_shader_create_info.hh
index 9984295457c..51008993353 100644
--- a/source/blender/gpu/intern/gpu_shader_create_info.hh
+++ b/source/blender/gpu/intern/gpu_shader_create_info.hh
@@ -130,6 +130,17 @@ enum class BuiltinBits {
};
ENUM_OPERATORS(BuiltinBits, BuiltinBits::WORK_GROUP_SIZE);
+/**
+ * Follow convention described in:
+ * https://www.khronos.org/registry/OpenGL/extensions/ARB/ARB_conservative_depth.txt
+ */
+enum class DepthWrite {
+ ANY = 0,
+ GREATER,
+ LESS,
+ UNCHANGED,
+};
+
/* Samplers & images. */
enum class ImageType {
/** Color samplers/image. */
@@ -273,6 +284,8 @@ struct ShaderCreateInfo {
bool auto_resource_location_ = false;
/** If true, force depth and stencil tests to always happen before fragment shader invocation. */
bool early_fragment_test_ = false;
+ /** Allow optimization when fragment shader writes to `gl_FragDepth`. */
+ DepthWrite depth_write_ = DepthWrite::ANY;
/**
* Maximum length of all the resource names including each null terminator.
* Only for names used by gpu::ShaderInterface.
@@ -695,6 +708,13 @@ struct ShaderCreateInfo {
return *(Self *)this;
}
+ /* Defines how the fragment shader will write to gl_FragDepth. */
+ Self &depth_write(DepthWrite value)
+ {
+ depth_write_ = value;
+ return *(Self *)this;
+ }
+
Self &auto_resource_location(bool value)
{
auto_resource_location_ = value;
diff --git a/source/blender/gpu/intern/gpu_viewport.c b/source/blender/gpu/intern/gpu_viewport.c
index 7bffafd7f9d..a0efe12f523 100644
--- a/source/blender/gpu/intern/gpu_viewport.c
+++ b/source/blender/gpu/intern/gpu_viewport.c
@@ -197,7 +197,7 @@ void GPU_viewport_bind_from_offscreen(GPUViewport *viewport,
/* XR surfaces will already check for texture size changes and free if necessary (see
* #wm_xr_session_surface_offscreen_ensure()), so don't free here as it has a significant
* performance impact (leads to texture re-creation in #gpu_viewport_textures_create() every VR
- * drawing iteration).*/
+ * drawing iteration). */
if (!is_xr_surface) {
gpu_viewport_textures_free(viewport);
}
diff --git a/source/blender/gpu/metal/mtl_backend.mm b/source/blender/gpu/metal/mtl_backend.mm
index e1da371bd0b..00d73ba5d71 100644
--- a/source/blender/gpu/metal/mtl_backend.mm
+++ b/source/blender/gpu/metal/mtl_backend.mm
@@ -363,7 +363,7 @@ void MTLBackend::capabilities_init(MTLContext *ctx)
MTLBackend::capabilities.supports_family_mac2);
GCaps.compute_shader_support = false; /* TODO(Metal): Add compute support. */
GCaps.shader_storage_buffer_objects_support =
- false; /* TODO(Metal): implement Storage Buffer support.*/
+ false; /* TODO(Metal): implement Storage Buffer support. */
/* Maximum buffer bindings: 31. Consider required slot for uniforms/UBOs/Vertex attributes.
* Can use argument buffers if a higher limit is required. */
diff --git a/source/blender/gpu/opengl/gl_backend.cc b/source/blender/gpu/opengl/gl_backend.cc
index 2c9cbdb99d8..610fd5d980f 100644
--- a/source/blender/gpu/opengl/gl_backend.cc
+++ b/source/blender/gpu/opengl/gl_backend.cc
@@ -479,7 +479,14 @@ void GLBackend::capabilities_init()
glGetIntegerv(GL_MAX_ELEMENTS_INDICES, &GCaps.max_batch_indices);
glGetIntegerv(GL_MAX_ELEMENTS_VERTICES, &GCaps.max_batch_vertices);
glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &GCaps.max_vertex_attribs);
- glGetIntegerv(GL_MAX_VARYING_FLOATS, &GCaps.max_varying_floats);
+ if (GPU_type_matches(GPU_DEVICE_APPLE, GPU_OS_MAC, GPU_DRIVER_OFFICIAL)) {
+ /* Due to a bug, querying GL_MAX_VARYING_FLOATS is emitting GL_INVALID_ENUM.
+ * Force use minimum required value. */
+ GCaps.max_varying_floats = 32;
+ }
+ else {
+ glGetIntegerv(GL_MAX_VARYING_FLOATS, &GCaps.max_varying_floats);
+ }
glGetIntegerv(GL_NUM_EXTENSIONS, &GCaps.extensions_len);
GCaps.extension_get = gl_extension_get;
@@ -502,9 +509,11 @@ void GLBackend::capabilities_init()
glGetIntegerv(GL_MAX_3D_TEXTURE_SIZE, &GLContext::max_texture_3d_size);
glGetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE, &GLContext::max_cubemap_size);
glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_BLOCKS, &GLContext::max_ubo_binds);
- glGetIntegerv(GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS, &GLContext::max_ssbo_binds);
glGetIntegerv(GL_MAX_UNIFORM_BLOCK_SIZE, &GLContext::max_ubo_size);
- glGetIntegerv(GL_MAX_SHADER_STORAGE_BLOCK_SIZE, &GLContext::max_ssbo_size);
+ if (GCaps.shader_storage_buffer_objects_support) {
+ glGetIntegerv(GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS, &GLContext::max_ssbo_binds);
+ glGetIntegerv(GL_MAX_SHADER_STORAGE_BLOCK_SIZE, &GLContext::max_ssbo_size);
+ }
GLContext::base_instance_support = GLEW_ARB_base_instance;
GLContext::clear_texture_support = GLEW_ARB_clear_texture;
GLContext::copy_image_support = GLEW_ARB_copy_image;
diff --git a/source/blender/gpu/opengl/gl_shader.cc b/source/blender/gpu/opengl/gl_shader.cc
index 5a55a2e8020..5938444ce49 100644
--- a/source/blender/gpu/opengl/gl_shader.cc
+++ b/source/blender/gpu/opengl/gl_shader.cc
@@ -217,6 +217,20 @@ static const char *to_string(const PrimitiveOut &layout)
}
}
+static const char *to_string(const DepthWrite &value)
+{
+ switch (value) {
+ case DepthWrite::ANY:
+ return "depth_any";
+ case DepthWrite::GREATER:
+ return "depth_greater";
+ case DepthWrite::LESS:
+ return "depth_less";
+ default:
+ return "depth_unchanged";
+ }
+}
+
static void print_image_type(std::ostream &os,
const ImageType &type,
const ShaderCreateInfo::Resource::BindType bind_type)
@@ -585,6 +599,9 @@ std::string GLShader::fragment_interface_declare(const ShaderCreateInfo &info) c
if (info.early_fragment_test_) {
ss << "layout(early_fragment_tests) in;\n";
}
+ if (GLEW_VERSION_4_2 || GLEW_ARB_conservative_depth) {
+ ss << "layout(" << to_string(info.depth_write_) << ") out float gl_FragDepth;\n";
+ }
ss << "\n/* Outputs. */\n";
for (const ShaderCreateInfo::FragOut &output : info.fragment_outputs_) {
ss << "layout(location = " << output.index;
@@ -868,7 +885,7 @@ GLuint GLShader::create_shader_stage(GLenum gl_stage, MutableSpan<const char *>
{
GLuint shader = glCreateShader(gl_stage);
if (shader == 0) {
- fprintf(stderr, "GLShader: Error: Could not create shader object.");
+ fprintf(stderr, "GLShader: Error: Could not create shader object.\n");
return 0;
}
diff --git a/source/blender/gpu/opengl/gl_shader_log.cc b/source/blender/gpu/opengl/gl_shader_log.cc
index 1d922916e4c..64567174d17 100644
--- a/source/blender/gpu/opengl/gl_shader_log.cc
+++ b/source/blender/gpu/opengl/gl_shader_log.cc
@@ -39,7 +39,8 @@ char *GLLogParser::parse_line(char *log_line, GPULogItem &log_item)
if ((log_item.cursor.row != -1) && (log_item.cursor.column != -1)) {
if (GPU_type_matches(GPU_DEVICE_NVIDIA, GPU_OS_ANY, GPU_DRIVER_OFFICIAL) ||
- GPU_type_matches(GPU_DEVICE_INTEL, GPU_OS_MAC, GPU_DRIVER_OFFICIAL)) {
+ GPU_type_matches(GPU_DEVICE_INTEL, GPU_OS_MAC, GPU_DRIVER_OFFICIAL) ||
+ GPU_type_matches(GPU_DEVICE_APPLE, GPU_OS_MAC, GPU_DRIVER_OFFICIAL)) {
/* 0:line */
log_item.cursor.row = log_item.cursor.column;
log_item.cursor.column = -1;
diff --git a/source/blender/gpu/shaders/gpu_shader_2D_image_rect_vert.glsl b/source/blender/gpu/shaders/gpu_shader_2D_image_rect_vert.glsl
index 903c602c5d6..11bb311740c 100644
--- a/source/blender/gpu/shaders/gpu_shader_2D_image_rect_vert.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_2D_image_rect_vert.glsl
@@ -16,14 +16,6 @@ void main()
vec2 uv;
vec2 co;
-#ifdef GPU_METAL
-/* Metal API does not support Triangle fan primitive topology.
- * When this shader is called using Triangle-Strip, vertex ID's
- * are in a different order. */
-# define GPU_PRIM_TRI_STRIP
-#endif
-
-#ifdef GPU_PRIM_TRI_STRIP
if (gl_VertexID == 0) {
co = rect_geom.xw;
uv = rect_icon.xw;
@@ -40,24 +32,6 @@ void main()
co = rect_geom.zy;
uv = rect_icon.zy;
}
-#else
- if (gl_VertexID == 0) {
- co = rect_geom.xy;
- uv = rect_icon.xy;
- }
- else if (gl_VertexID == 1) {
- co = rect_geom.xw;
- uv = rect_icon.xw;
- }
- else if (gl_VertexID == 2) {
- co = rect_geom.zw;
- uv = rect_icon.zw;
- }
- else {
- co = rect_geom.zy;
- uv = rect_icon.zy;
- }
-#endif
gl_Position = ModelViewProjectionMatrix * vec4(co, 0.0f, 1.0f);
texCoord_interp = uv;
diff --git a/source/blender/gpu/shaders/gpu_shader_cfg_world_clip_lib.glsl b/source/blender/gpu/shaders/gpu_shader_cfg_world_clip_lib.glsl
index cdc716db7a4..3edf0e31799 100644
--- a/source/blender/gpu/shaders/gpu_shader_cfg_world_clip_lib.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_cfg_world_clip_lib.glsl
@@ -7,13 +7,13 @@ uniform vec4 WorldClipPlanes[6];
# define _world_clip_planes_calc_clip_distance(wpos, _clipplanes) \
{ \
- vec4 pos = vec4(wpos, 1.0); \
- gl_ClipDistance[0] = dot(_clipplanes[0], pos); \
- gl_ClipDistance[1] = dot(_clipplanes[1], pos); \
- gl_ClipDistance[2] = dot(_clipplanes[2], pos); \
- gl_ClipDistance[3] = dot(_clipplanes[3], pos); \
- gl_ClipDistance[4] = dot(_clipplanes[4], pos); \
- gl_ClipDistance[5] = dot(_clipplanes[5], pos); \
+ vec4 _pos = vec4(wpos, 1.0); \
+ gl_ClipDistance[0] = dot(_clipplanes[0], _pos); \
+ gl_ClipDistance[1] = dot(_clipplanes[1], _pos); \
+ gl_ClipDistance[2] = dot(_clipplanes[2], _pos); \
+ gl_ClipDistance[3] = dot(_clipplanes[3], _pos); \
+ gl_ClipDistance[4] = dot(_clipplanes[4], _pos); \
+ gl_ClipDistance[5] = dot(_clipplanes[5], _pos); \
}
/* When all shaders are builtin shaders are migrated this could be applied directly. */
diff --git a/source/blender/gpu/shaders/gpu_shader_colorspace_lib.glsl b/source/blender/gpu/shaders/gpu_shader_colorspace_lib.glsl
index 7d69cba5017..abd4592dc9d 100644
--- a/source/blender/gpu/shaders/gpu_shader_colorspace_lib.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_colorspace_lib.glsl
@@ -6,13 +6,13 @@
uniform bool srgbTarget = false;
#endif
-vec4 blender_srgb_to_framebuffer_space(vec4 col)
+vec4 blender_srgb_to_framebuffer_space(vec4 in_color)
{
if (srgbTarget) {
- vec3 c = max(col.rgb, vec3(0.0));
+ vec3 c = max(in_color.rgb, vec3(0.0));
vec3 c1 = c * (1.0 / 12.92);
vec3 c2 = pow((c + 0.055) * (1.0 / 1.055), vec3(2.4));
- col.rgb = mix(c1, c2, step(vec3(0.04045), c));
+ in_color.rgb = mix(c1, c2, step(vec3(0.04045), c));
}
- return col;
+ return in_color;
}
diff --git a/source/blender/gpu/shaders/gpu_shader_point_varying_color_frag.glsl b/source/blender/gpu/shaders/gpu_shader_point_varying_color_frag.glsl
index 23e9f9bc20f..bc108462007 100644
--- a/source/blender/gpu/shaders/gpu_shader_point_varying_color_frag.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_point_varying_color_frag.glsl
@@ -1,10 +1,10 @@
#ifndef USE_GPU_SHADER_CREATE_INFO
in vec4 finalColor;
out vec4 fragColor;
-#endif
-#if defined(VERT)
+# if defined(VERT)
in float vertexCrease;
+# endif
#endif
void main()
diff --git a/source/blender/gpu/shaders/opengl/glsl_shader_defines.glsl b/source/blender/gpu/shaders/opengl/glsl_shader_defines.glsl
index a5fce2e71c3..0515a737e6e 100644
--- a/source/blender/gpu/shaders/opengl/glsl_shader_defines.glsl
+++ b/source/blender/gpu/shaders/opengl/glsl_shader_defines.glsl
@@ -1,3 +1,13 @@
+
+/* Texture format tokens -- Type explictness required by other Graphics APIs. */
+#define depth2D sampler2D
+#define depth2DArray sampler2DArray
+#define depth2DMS sampler2DMS
+#define depth2DMSArray sampler2DMSArray
+#define depthCube samplerCube
+#define depthCubeArray samplerCubeArray
+#define depth2DArrayShadow sampler2DArrayShadow
+
/* Backend Functions. */
#define select(A, B, mask) mix(A, B, mask)
diff --git a/source/blender/io/alembic/exporter/abc_writer_abstract.cc b/source/blender/io/alembic/exporter/abc_writer_abstract.cc
index c277e5e2710..6c50583ad62 100644
--- a/source/blender/io/alembic/exporter/abc_writer_abstract.cc
+++ b/source/blender/io/alembic/exporter/abc_writer_abstract.cc
@@ -98,7 +98,7 @@ const Imath::Box3d &ABCAbstractWriter::bounding_box() const
void ABCAbstractWriter::update_bounding_box(Object *object)
{
- BoundBox *bb = BKE_object_boundbox_get(object);
+ const BoundBox *bb = BKE_object_boundbox_get(object);
if (!bb) {
if (object->type != OB_CAMERA) {
diff --git a/source/blender/io/alembic/exporter/abc_writer_curves.cc b/source/blender/io/alembic/exporter/abc_writer_curves.cc
index 95f296c2cf7..07bce8fcf7a 100644
--- a/source/blender/io/alembic/exporter/abc_writer_curves.cc
+++ b/source/blender/io/alembic/exporter/abc_writer_curves.cc
@@ -73,6 +73,7 @@ void ABCCurveWriter::do_write(HierarchyContext &context)
Nurb *nurbs = static_cast<Nurb *>(curve->nurb.first);
for (; nurbs; nurbs = nurbs->next) {
+ const size_t current_point_count = verts.size();
if (nurbs->bp) {
curve_basis = Alembic::AbcGeom::kNoBasis;
curve_type = Alembic::AbcGeom::kVariableOrder;
@@ -142,7 +143,7 @@ void ABCCurveWriter::do_write(HierarchyContext &context)
}
orders.push_back(nurbs->orderu);
- vert_counts.push_back(verts.size());
+ vert_counts.push_back(verts.size() - current_point_count);
}
Alembic::AbcGeom::OFloatGeomParam::Sample width_sample;
diff --git a/source/blender/io/gpencil/intern/gpencil_io_export_pdf.cc b/source/blender/io/gpencil/intern/gpencil_io_export_pdf.cc
index 205ab788e6d..700d91791a8 100644
--- a/source/blender/io/gpencil/intern/gpencil_io_export_pdf.cc
+++ b/source/blender/io/gpencil/intern/gpencil_io_export_pdf.cc
@@ -222,7 +222,7 @@ void GpencilExporterPDF::export_stroke_to_polyline(bGPDlayer *gpl,
/* Get the thickness in pixels using a simple 1 point stroke. */
bGPDstroke *gps_temp = BKE_gpencil_stroke_duplicate(gps, false, false);
gps_temp->totpoints = 1;
- gps_temp->points = MEM_cnew<bGPDspoint>("gp_stroke_points");
+ gps_temp->points = MEM_new<bGPDspoint>("gp_stroke_points");
const bGPDspoint *pt_src = &gps->points[0];
bGPDspoint *pt_dst = &gps_temp->points[0];
copy_v3_v3(&pt_dst->x, &pt_src->x);
diff --git a/source/blender/io/gpencil/intern/gpencil_io_export_svg.cc b/source/blender/io/gpencil/intern/gpencil_io_export_svg.cc
index 5d33a2806bd..2601ad05ea7 100644
--- a/source/blender/io/gpencil/intern/gpencil_io_export_svg.cc
+++ b/source/blender/io/gpencil/intern/gpencil_io_export_svg.cc
@@ -292,7 +292,7 @@ void GpencilExporterSVG::export_stroke_to_polyline(bGPDlayer *gpl,
/* Get the thickness in pixels using a simple 1 point stroke. */
bGPDstroke *gps_temp = BKE_gpencil_stroke_duplicate(gps, false, false);
gps_temp->totpoints = 1;
- gps_temp->points = MEM_cnew<bGPDspoint>("gp_stroke_points");
+ gps_temp->points = MEM_new<bGPDspoint>("gp_stroke_points");
bGPDspoint *pt_src = &gps->points[0];
bGPDspoint *pt_dst = &gps_temp->points[0];
copy_v3_v3(&pt_dst->x, &pt_src->x);
diff --git a/source/blender/io/usd/intern/usd_writer_material.cc b/source/blender/io/usd/intern/usd_writer_material.cc
index b548a666ef7..1bfc0e50f69 100644
--- a/source/blender/io/usd/intern/usd_writer_material.cc
+++ b/source/blender/io/usd/intern/usd_writer_material.cc
@@ -255,8 +255,8 @@ void create_input(pxr::UsdShadeShader &shader, const InputSpec &spec, const void
/* Find the UVMAP node input to the given texture image node and convert it
* to a USD primvar reader shader. If no UVMAP node is found, create a primvar
- * reader for the given default uv set. The primvar reader will be attached to
- * the 'st' input of the given USD texture shader. */
+ * reader for the given default uv set. The primvar reader will be attached to
+ * the 'st' input of the given USD texture shader. */
static void create_uvmap_shader(const USDExporterContext &usd_export_context,
bNode *tex_node,
pxr::UsdShadeMaterial &usd_material,
@@ -359,7 +359,7 @@ static void export_in_memory_texture(Image *ima,
BLI_split_file_part(image_abs_path, file_name, FILE_MAX);
}
else {
- /* Use the image name for the file name. */
+ /* Use the image name for the file name. */
strcpy(file_name, ima->id.name + 2);
}
@@ -452,7 +452,7 @@ static bNode *traverse_channel(bNodeSocket *input, const short target_type)
}
/* Returns the first occurrence of a principled BSDF or a diffuse BSDF node found in the given
- * material's node tree. Returns null if no instance of either type was found.*/
+ * material's node tree. Returns null if no instance of either type was found. */
static bNode *find_bsdf_node(Material *material)
{
LISTBASE_FOREACH (bNode *, node, &material->nodetree->nodes) {
diff --git a/source/blender/io/wavefront_obj/CMakeLists.txt b/source/blender/io/wavefront_obj/CMakeLists.txt
index 8045d51e0da..cc375577b52 100644
--- a/source/blender/io/wavefront_obj/CMakeLists.txt
+++ b/source/blender/io/wavefront_obj/CMakeLists.txt
@@ -13,6 +13,7 @@ set(INC
../../makesrna
../../nodes
../../windowmanager
+ ../../../../extern/fmtlib/include
../../../../intern/guardedalloc
)
diff --git a/source/blender/io/wavefront_obj/exporter/obj_export_file_writer.cc b/source/blender/io/wavefront_obj/exporter/obj_export_file_writer.cc
index acfdaa29b52..f78ef334d4d 100644
--- a/source/blender/io/wavefront_obj/exporter/obj_export_file_writer.cc
+++ b/source/blender/io/wavefront_obj/exporter/obj_export_file_writer.cc
@@ -525,24 +525,21 @@ void MTLWriter::write_texture_map(
const MTLMaterial &mtl_material,
const Map<const eMTLSyntaxElement, tex_map_XX>::Item &texture_map)
{
- std::string translation;
- std::string scale;
- std::string map_bump_strength;
- /* Optional strings should have their own leading spaces. */
+ std::string options;
+ /* Option strings should have their own leading spaces. */
if (texture_map.value.translation != float3{0.0f, 0.0f, 0.0f}) {
- translation.append(" -s ").append(float3_to_string(texture_map.value.translation));
+ options.append(" -o ").append(float3_to_string(texture_map.value.translation));
}
if (texture_map.value.scale != float3{1.0f, 1.0f, 1.0f}) {
- scale.append(" -o ").append(float3_to_string(texture_map.value.scale));
+ options.append(" -s ").append(float3_to_string(texture_map.value.scale));
}
if (texture_map.key == eMTLSyntaxElement::map_Bump && mtl_material.map_Bump_strength > 0.0001f) {
- map_bump_strength.append(" -bm ").append(std::to_string(mtl_material.map_Bump_strength));
+ options.append(" -bm ").append(std::to_string(mtl_material.map_Bump_strength));
}
#define SYNTAX_DISPATCH(eMTLSyntaxElement) \
if (texture_map.key == eMTLSyntaxElement) { \
- fmt_handler_.write<eMTLSyntaxElement>(translation + scale + map_bump_strength, \
- texture_map.value.image_path); \
+ fmt_handler_.write<eMTLSyntaxElement>(options, texture_map.value.image_path); \
return; \
}
diff --git a/source/blender/io/wavefront_obj/exporter/obj_export_io.hh b/source/blender/io/wavefront_obj/exporter/obj_export_io.hh
index 3bee93b36a5..0d7c089ec14 100644
--- a/source/blender/io/wavefront_obj/exporter/obj_export_io.hh
+++ b/source/blender/io/wavefront_obj/exporter/obj_export_io.hh
@@ -8,7 +8,6 @@
#include <cstdio>
#include <string>
-#include <system_error>
#include <type_traits>
#include <vector>
@@ -17,6 +16,11 @@
#include "BLI_string_ref.hh"
#include "BLI_utility_mixins.hh"
+/* SEP macro from BLI path utils clashes with SEP symbol in fmt headers. */
+#undef SEP
+#define FMT_HEADER_ONLY
+#include <fmt/format.h>
+
namespace blender::io::obj {
enum class eFileType {
@@ -124,40 +128,40 @@ constexpr FormattingSyntax syntax_elem_to_formatting(const eOBJSyntaxElement key
{
switch (key) {
case eOBJSyntaxElement::vertex_coords: {
- return {"v %f %f %f\n", 3, is_type_float<T...>};
+ return {"v {:.6f} {:.6f} {:.6f}\n", 3, is_type_float<T...>};
}
case eOBJSyntaxElement::uv_vertex_coords: {
- return {"vt %f %f\n", 2, is_type_float<T...>};
+ return {"vt {:.6f} {:.6f}\n", 2, is_type_float<T...>};
}
case eOBJSyntaxElement::normal: {
- return {"vn %.4f %.4f %.4f\n", 3, is_type_float<T...>};
+ return {"vn {:.4f} {:.4f} {:.4f}\n", 3, is_type_float<T...>};
}
case eOBJSyntaxElement::poly_element_begin: {
return {"f", 0, is_type_string_related<T...>};
}
case eOBJSyntaxElement::vertex_uv_normal_indices: {
- return {" %d/%d/%d", 3, is_type_integral<T...>};
+ return {" {}/{}/{}", 3, is_type_integral<T...>};
}
case eOBJSyntaxElement::vertex_normal_indices: {
- return {" %d//%d", 2, is_type_integral<T...>};
+ return {" {}//{}", 2, is_type_integral<T...>};
}
case eOBJSyntaxElement::vertex_uv_indices: {
- return {" %d/%d", 2, is_type_integral<T...>};
+ return {" {}/{}", 2, is_type_integral<T...>};
}
case eOBJSyntaxElement::vertex_indices: {
- return {" %d", 1, is_type_integral<T...>};
+ return {" {}", 1, is_type_integral<T...>};
}
case eOBJSyntaxElement::poly_usemtl: {
- return {"usemtl %s\n", 1, is_type_string_related<T...>};
+ return {"usemtl {}\n", 1, is_type_string_related<T...>};
}
case eOBJSyntaxElement::edge: {
- return {"l %d %d\n", 2, is_type_integral<T...>};
+ return {"l {} {}\n", 2, is_type_integral<T...>};
}
case eOBJSyntaxElement::cstype: {
return {"cstype bspline\n", 0, is_type_string_related<T...>};
}
case eOBJSyntaxElement::nurbs_degree: {
- return {"deg %d\n", 1, is_type_integral<T...>};
+ return {"deg {}\n", 1, is_type_integral<T...>};
}
case eOBJSyntaxElement::curve_element_begin: {
return {"curv 0.0 1.0", 0, is_type_string_related<T...>};
@@ -166,7 +170,7 @@ constexpr FormattingSyntax syntax_elem_to_formatting(const eOBJSyntaxElement key
return {"parm u 0.0", 0, is_type_string_related<T...>};
}
case eOBJSyntaxElement::nurbs_parameters: {
- return {" %f", 1, is_type_float<T...>};
+ return {" {:.6f}", 1, is_type_float<T...>};
}
case eOBJSyntaxElement::nurbs_parameter_end: {
return {" 1.0\n", 0, is_type_string_related<T...>};
@@ -184,19 +188,19 @@ constexpr FormattingSyntax syntax_elem_to_formatting(const eOBJSyntaxElement key
return {"\n", 0, is_type_string_related<T...>};
}
case eOBJSyntaxElement::mtllib: {
- return {"mtllib %s\n", 1, is_type_string_related<T...>};
+ return {"mtllib {}\n", 1, is_type_string_related<T...>};
}
case eOBJSyntaxElement::smooth_group: {
- return {"s %d\n", 1, is_type_integral<T...>};
+ return {"s {}\n", 1, is_type_integral<T...>};
}
case eOBJSyntaxElement::object_group: {
- return {"g %s\n", 1, is_type_string_related<T...>};
+ return {"g {}\n", 1, is_type_string_related<T...>};
}
case eOBJSyntaxElement::object_name: {
- return {"o %s\n", 1, is_type_string_related<T...>};
+ return {"o {}\n", 1, is_type_string_related<T...>};
}
case eOBJSyntaxElement::string: {
- return {"%s", 1, is_type_string_related<T...>};
+ return {"{}", 1, is_type_string_related<T...>};
}
}
}
@@ -206,56 +210,56 @@ constexpr FormattingSyntax syntax_elem_to_formatting(const eMTLSyntaxElement key
{
switch (key) {
case eMTLSyntaxElement::newmtl: {
- return {"newmtl %s\n", 1, is_type_string_related<T...>};
+ return {"newmtl {}\n", 1, is_type_string_related<T...>};
}
case eMTLSyntaxElement::Ni: {
- return {"Ni %.6f\n", 1, is_type_float<T...>};
+ return {"Ni {:.6f}\n", 1, is_type_float<T...>};
}
case eMTLSyntaxElement::d: {
- return {"d %.6f\n", 1, is_type_float<T...>};
+ return {"d {:.6f}\n", 1, is_type_float<T...>};
}
case eMTLSyntaxElement::Ns: {
- return {"Ns %.6f\n", 1, is_type_float<T...>};
+ return {"Ns {:.6f}\n", 1, is_type_float<T...>};
}
case eMTLSyntaxElement::illum: {
- return {"illum %d\n", 1, is_type_integral<T...>};
+ return {"illum {}\n", 1, is_type_integral<T...>};
}
case eMTLSyntaxElement::Ka: {
- return {"Ka %.6f %.6f %.6f\n", 3, is_type_float<T...>};
+ return {"Ka {:.6f} {:.6f} {:.6f}\n", 3, is_type_float<T...>};
}
case eMTLSyntaxElement::Kd: {
- return {"Kd %.6f %.6f %.6f\n", 3, is_type_float<T...>};
+ return {"Kd {:.6f} {:.6f} {:.6f}\n", 3, is_type_float<T...>};
}
case eMTLSyntaxElement::Ks: {
- return {"Ks %.6f %.6f %.6f\n", 3, is_type_float<T...>};
+ return {"Ks {:.6f} {:.6f} {:.6f}\n", 3, is_type_float<T...>};
}
case eMTLSyntaxElement::Ke: {
- return {"Ke %.6f %.6f %.6f\n", 3, is_type_float<T...>};
+ return {"Ke {:.6f} {:.6f} {:.6f}\n", 3, is_type_float<T...>};
}
- /* Keep only one space between options since filepaths may have leading spaces too. */
+ /* Note: first texture map related argument, if present, will have its own leading space. */
case eMTLSyntaxElement::map_Kd: {
- return {"map_Kd %s %s\n", 2, is_type_string_related<T...>};
+ return {"map_Kd{} {}\n", 2, is_type_string_related<T...>};
}
case eMTLSyntaxElement::map_Ks: {
- return {"map_Ks %s %s\n", 2, is_type_string_related<T...>};
+ return {"map_Ks{} {}\n", 2, is_type_string_related<T...>};
}
case eMTLSyntaxElement::map_Ns: {
- return {"map_Ns %s %s\n", 2, is_type_string_related<T...>};
+ return {"map_Ns{} {}\n", 2, is_type_string_related<T...>};
}
case eMTLSyntaxElement::map_d: {
- return {"map_d %s %s\n", 2, is_type_string_related<T...>};
+ return {"map_d{} {}\n", 2, is_type_string_related<T...>};
}
case eMTLSyntaxElement::map_refl: {
- return {"map_refl %s %s\n", 2, is_type_string_related<T...>};
+ return {"map_refl{} {}\n", 2, is_type_string_related<T...>};
}
case eMTLSyntaxElement::map_Ke: {
- return {"map_Ke %s %s\n", 2, is_type_string_related<T...>};
+ return {"map_Ke{} {}\n", 2, is_type_string_related<T...>};
}
case eMTLSyntaxElement::map_Bump: {
- return {"map_Bump %s %s\n", 2, is_type_string_related<T...>};
+ return {"map_Bump{} {}\n", 2, is_type_string_related<T...>};
}
case eMTLSyntaxElement::string: {
- return {"%s", 1, is_type_string_related<T...>};
+ return {"{}", 1, is_type_string_related<T...>};
}
}
}
@@ -270,9 +274,7 @@ constexpr FormattingSyntax syntax_elem_to_formatting(const eMTLSyntaxElement key
* Call write_fo_file once in a while to write the memory buffer(s)
* into the given file.
*/
-template<eFileType filetype,
- size_t buffer_chunk_size = 64 * 1024,
- size_t write_local_buffer_size = 1024>
+template<eFileType filetype, size_t buffer_chunk_size = 64 * 1024>
class FormatHandler : NonCopyable, NonMovable {
private:
typedef std::vector<char> VectorChar;
@@ -299,7 +301,7 @@ class FormatHandler : NonCopyable, NonMovable {
return blocks_.size();
}
- void append_from(FormatHandler<filetype, buffer_chunk_size, write_local_buffer_size> &v)
+ void append_from(FormatHandler<filetype, buffer_chunk_size> &v)
{
blocks_.insert(blocks_.end(),
std::make_move_iterator(v.blocks_.begin()),
@@ -328,33 +330,6 @@ class FormatHandler : NonCopyable, NonMovable {
}
private:
- /* Remove this after upgrading to C++20. */
- template<typename T> using remove_cvref_t = std::remove_cv_t<std::remove_reference_t<T>>;
-
- /**
- * Make #std::string etc., usable for `fprintf` family. int float etc. are not affected.
- * \return: `const char *` or the original argument if the argument is
- * not related to #std::string.
- */
- template<typename T> constexpr auto convert_to_primitive(T &&arg) const
- {
- if constexpr (std::is_same_v<remove_cvref_t<T>, std::string> ||
- std::is_same_v<remove_cvref_t<T>, blender::StringRefNull>) {
- return arg.c_str();
- }
- else if constexpr (std::is_same_v<remove_cvref_t<T>, blender::StringRef>) {
- BLI_STATIC_ASSERT(
- (always_false<T>::value),
- "Null-terminated string not present. Please use blender::StringRefNull instead.");
- /* Another trick to cause a compile-time error: returning nothing to #std::printf. */
- return;
- }
- else {
- /* For int, float etc. */
- return std::forward<T>(arg);
- }
- }
-
/* Ensure the last block contains at least this amount of free space.
* If not, add a new block with max of block size & the amount of space needed. */
void ensure_space(size_t at_least)
@@ -365,38 +340,15 @@ class FormatHandler : NonCopyable, NonMovable {
}
}
- template<typename... T> constexpr void write_impl(const char *fmt, T &&...args)
+ template<typename... T> void write_impl(const char *fmt, T &&...args)
{
- if constexpr (sizeof...(T) == 0) {
- /* No arguments: just emit the format string. */
- size_t len = strlen(fmt);
- ensure_space(len);
- VectorChar &bb = blocks_.back();
- bb.insert(bb.end(), fmt, fmt + len);
- }
- else {
- /* Format into a local buffer. */
- char buf[write_local_buffer_size];
- int needed = std::snprintf(
- buf, write_local_buffer_size, fmt, convert_to_primitive(std::forward<T>(args))...);
- if (needed < 0)
- throw std::system_error(
- errno, std::system_category(), "Failed to format obj export string into a buffer");
- ensure_space(needed + 1); /* Ensure space for zero terminator. */
- VectorChar &bb = blocks_.back();
- if (needed < write_local_buffer_size) {
- /* String formatted successfully into the local buffer, copy it. */
- bb.insert(bb.end(), buf, buf + needed);
- }
- else {
- /* Would need more space than the local buffer: insert said space and format again into
- * that. */
- size_t bbEnd = bb.size();
- bb.insert(bb.end(), needed, ' ');
- std::snprintf(
- bb.data() + bbEnd, needed + 1, fmt, convert_to_primitive(std::forward<T>(args))...);
- }
- }
+ /* Format into a local buffer. */
+ fmt::memory_buffer buf;
+ fmt::format_to(fmt::appender(buf), fmt, std::forward<T>(args)...);
+ size_t len = buf.size();
+ ensure_space(len);
+ VectorChar &bb = blocks_.back();
+ bb.insert(bb.end(), buf.begin(), buf.end());
}
};
diff --git a/source/blender/io/wavefront_obj/exporter/obj_export_mtl.cc b/source/blender/io/wavefront_obj/exporter/obj_export_mtl.cc
index b8814b1bdd3..c48d5a5f7f0 100644
--- a/source/blender/io/wavefront_obj/exporter/obj_export_mtl.cc
+++ b/source/blender/io/wavefront_obj/exporter/obj_export_mtl.cc
@@ -287,14 +287,15 @@ static void store_image_textures(const nodes::NodeRef *bsdf_node,
/* Find sockets linked to "Color" socket in normal map node. */
linked_sockets_to_dest_id(normal_map_node, *node_tree, "Color", linked_sockets);
}
- else if (texture_map.key == eMTLSyntaxElement::map_Ke) {
- float emission_strength = 0.0f;
- copy_property_from_node(SOCK_FLOAT, bnode, "Emission Strength", {&emission_strength, 1});
- if (emission_strength == 0.0f) {
- continue;
- }
- }
else {
+ /* Skip emission map if emission strength is zero. */
+ if (texture_map.key == eMTLSyntaxElement::map_Ke) {
+ float emission_strength = 0.0f;
+ copy_property_from_node(SOCK_FLOAT, bnode, "Emission Strength", {&emission_strength, 1});
+ if (emission_strength == 0.0f) {
+ continue;
+ }
+ }
/* Find sockets linked to the destination socket of interest, in P-BSDF node. */
linked_sockets_to_dest_id(
bnode, *node_tree, texture_map.value.dest_socket_id, linked_sockets);
diff --git a/source/blender/io/wavefront_obj/tests/obj_exporter_tests.cc b/source/blender/io/wavefront_obj/tests/obj_exporter_tests.cc
index b8fecfb25f3..a3512595fa7 100644
--- a/source/blender/io/wavefront_obj/tests/obj_exporter_tests.cc
+++ b/source/blender/io/wavefront_obj/tests/obj_exporter_tests.cc
@@ -241,7 +241,7 @@ TEST(obj_exporter_writer, mtllib)
TEST(obj_exporter_writer, format_handler_buffer_chunking)
{
/* Use a tiny buffer chunk size, so that the test below ends up creating several blocks. */
- FormatHandler<eFileType::OBJ, 16, 8> h;
+ FormatHandler<eFileType::OBJ, 16> h;
h.write<eOBJSyntaxElement::object_name>("abc");
h.write<eOBJSyntaxElement::object_name>("abcd");
h.write<eOBJSyntaxElement::object_name>("abcde");
@@ -486,6 +486,19 @@ TEST_F(obj_exporter_regression_test, cubes_positioned)
_export.params);
}
+/* Note: texture paths in the resulting mtl file currently are always
+ * as they are stored in the source .blend file; not relative to where
+ * the export is done. When that is properly fixed, the expected .mtl
+ * file should be updated. */
+TEST_F(obj_exporter_regression_test, cubes_with_textures)
+{
+ OBJExportParamsDefault _export;
+ compare_obj_export_to_golden("io_tests/blend_geometry/cubes_with_textures.blend",
+ "io_tests/obj/cubes_with_textures.obj",
+ "io_tests/obj/cubes_with_textures.mtl",
+ _export.params);
+}
+
TEST_F(obj_exporter_regression_test, suzanne_all_data)
{
OBJExportParamsDefault _export;
diff --git a/source/blender/makesdna/DNA_ID.h b/source/blender/makesdna/DNA_ID.h
index c3132eeab3d..3ebf085443a 100644
--- a/source/blender/makesdna/DNA_ID.h
+++ b/source/blender/makesdna/DNA_ID.h
@@ -319,6 +319,11 @@ enum {
* because it was created as an single override, outside of any hierarchy consideration).
*/
IDOVERRIDE_LIBRARY_FLAG_NO_HIERARCHY = 1 << 0,
+ /**
+ * The override ID is required for the system to work (because of ID dependencies), but is not
+ * seen as editable by the user.
+ */
+ IDOVERRIDE_LIBRARY_FLAG_SYSTEM_DEFINED = 1 << 1,
};
/* watch it: Sequence has identical beginning. */
diff --git a/source/blender/makesdna/DNA_brush_types.h b/source/blender/makesdna/DNA_brush_types.h
index 564f34b1f72..1382efca409 100644
--- a/source/blender/makesdna/DNA_brush_types.h
+++ b/source/blender/makesdna/DNA_brush_types.h
@@ -138,7 +138,7 @@ typedef struct BrushGpencilSettings {
} BrushGpencilSettings;
typedef struct BrushCurvesSculptSettings {
- /* Number of curves added by the add brush. */
+ /** Number of curves added by the add brush. */
int add_amount;
} BrushCurvesSculptSettings;
diff --git a/source/blender/makesdna/DNA_defs.h b/source/blender/makesdna/DNA_defs.h
index bfeb809b369..bbce4839506 100644
--- a/source/blender/makesdna/DNA_defs.h
+++ b/source/blender/makesdna/DNA_defs.h
@@ -86,6 +86,9 @@ template<class T> class ShallowDataConstRef {
const T &ref_;
};
+template<class T> class ShallowZeroInitializeTag {
+};
+
} // namespace blender::dna::internal
# define DNA_DEFINE_CXX_METHODS(class_name) \
@@ -108,6 +111,18 @@ template<class T> class ShallowDataConstRef {
_DNA_internal_memcpy(this, ref.get_pointer(), sizeof(class_name)); \
} \
return *this; \
+ } \
+ /* Create object which memory is filled with zeros. */ \
+ class_name(const blender::dna::internal::ShallowZeroInitializeTag<class_name> /*tag*/) \
+ : class_name() \
+ { \
+ _DNA_internal_memzero(this, sizeof(class_name)); \
+ } \
+ class_name &operator=( \
+ const blender::dna::internal::ShallowZeroInitializeTag<class_name> /*tag*/) \
+ { \
+ _DNA_internal_memzero(this, sizeof(class_name)); \
+ return *this; \
}
namespace blender::dna {
@@ -126,18 +141,12 @@ template<class T>
return internal::ShallowDataConstRef(other);
}
-/* Fill underlying memory used by DNA object with zeroes. */
-template<class T> inline void zero_memory(T &object)
-{
- /* TODO(sergey): Consider adding static assert for T being a trivial type. */
- _DNA_internal_memzero(&object, sizeof(T));
-}
-
-/* Copy memory from one DNA object to another. */
-template<class T> inline void copy_memory(T &dst, const T &src)
+/* DNA object initializer which leads to an object which underlying memory is filled with zeroes.
+ */
+template<class T>
+[[nodiscard]] inline internal::ShallowZeroInitializeTag<T> shallow_zero_initialize()
{
- /* TODO(sergey): Consider adding static assert for T being a trivial type. */
- _DNA_internal_memcpy(&dst, &src, sizeof(T));
+ return internal::ShallowZeroInitializeTag<T>();
}
} // namespace blender::dna
diff --git a/source/blender/makesdna/DNA_gpencil_modifier_types.h b/source/blender/makesdna/DNA_gpencil_modifier_types.h
index 7568dc5ff9a..6603ed1a078 100644
--- a/source/blender/makesdna/DNA_gpencil_modifier_types.h
+++ b/source/blender/makesdna/DNA_gpencil_modifier_types.h
@@ -392,9 +392,20 @@ typedef struct BuildGpencilModifierData {
* For the "Concurrent" mode, when should "shorter" strips start/end.
*/
short time_alignment;
+
+ /** Build origin control object. */
+ struct Object *object;
+
/** Factor of the stroke (used instead of frame evaluation. */
float percentage_fac;
- char _pad[4];
+
+ /** Weight fading at the end of the stroke. */
+ float fade_fac;
+ /** Target vertexgroup name, MAX_VGROUP_NAME. */
+ char target_vgname[64];
+ /** Fading strength of opacity and thickness */
+ float fade_opacity_strength;
+ float fade_thickness_strength;
} BuildGpencilModifierData;
typedef enum eBuildGpencil_Mode {
@@ -412,7 +423,7 @@ typedef enum eBuildGpencil_Transition {
/* Hide in reverse order */
GP_BUILD_TRANSITION_SHRINK = 1,
/* Hide in forward order */
- GP_BUILD_TRANSITION_FADE = 2,
+ GP_BUILD_TRANSITION_VANISH = 2,
} eBuildGpencil_Transition;
typedef enum eBuildGpencil_TimeAlignment {
@@ -435,6 +446,7 @@ typedef enum eBuildGpencil_Flag {
/* Use a percentage instead of frame number to evaluate strokes. */
GP_BUILD_PERCENTAGE = (1 << 4),
+ GP_BUILD_USE_FADING = (1 << 5),
} eBuildGpencil_Flag;
typedef struct LatticeGpencilModifierData {
diff --git a/source/blender/makesdna/DNA_gpencil_types.h b/source/blender/makesdna/DNA_gpencil_types.h
index 8a30a7e8c99..4a1b639122a 100644
--- a/source/blender/makesdna/DNA_gpencil_types.h
+++ b/source/blender/makesdna/DNA_gpencil_types.h
@@ -48,6 +48,8 @@ typedef struct bGPDcontrolpoint {
} bGPDcontrolpoint;
typedef struct bGPDspoint_Runtime {
+ DNA_DEFINE_CXX_METHODS(bGPDspoint_Runtime)
+
/** Original point (used to dereference evaluated data) */
struct bGPDspoint *pt_orig;
/** Original index array position */
@@ -61,6 +63,8 @@ typedef struct bGPDspoint_Runtime {
* This assumes that the bottom-left corner is (0,0)
*/
typedef struct bGPDspoint {
+ DNA_DEFINE_CXX_METHODS(bGPDspoint)
+
/** Co-ordinates of point (usually 2d, but can be 3d as well). */
float x, y, z;
/** Pressure of input device (from 0 to 1) at this point. */
@@ -120,6 +124,8 @@ typedef struct bGPDtriangle {
/* color of palettes */
typedef struct bGPDpalettecolor {
+ DNA_DEFINE_CXX_METHODS(bGPDpalettecolor)
+
struct bGPDpalettecolor *next, *prev;
/** Color name. Must be unique. */
char info[64];
@@ -148,6 +154,8 @@ typedef enum eGPDpalettecolor_Flag {
/* palette of colors */
typedef struct bGPDpalette {
+ DNA_DEFINE_CXX_METHODS(bGPDpalette)
+
struct bGPDpalette *next, *prev;
/** Pointer to individual colors. */
@@ -203,6 +211,8 @@ typedef enum eGPDcurve_point_Flag {
/* Curve for Bezier Editing. */
typedef struct bGPDcurve {
+ DNA_DEFINE_CXX_METHODS(bGPDcurve)
+
/** Array of BezTriple. */
bGPDcurve_point *curve_points;
/** Total number of curve points. */
@@ -225,6 +235,8 @@ typedef enum bGPDcurve_Flag {
/* Runtime temp data for bGPDstroke */
typedef struct bGPDstroke_Runtime {
+ DNA_DEFINE_CXX_METHODS(bGPDstroke_Runtime)
+
/** temporary layer name only used during copy/paste to put the stroke in the original layer */
char tmp_layerinfo[128];
@@ -248,6 +260,8 @@ typedef struct bGPDstroke_Runtime {
* drawn by the user in one 'mouse-down'->'mouse-up' operation
*/
typedef struct bGPDstroke {
+ DNA_DEFINE_CXX_METHODS(bGPDstroke)
+
struct bGPDstroke *next, *prev;
/** Array of data-points for stroke. */
@@ -369,6 +383,8 @@ typedef enum eGPDstroke_Arrowstyle {
/* Runtime temp data for bGPDframe */
typedef struct bGPDframe_Runtime {
+ DNA_DEFINE_CXX_METHODS(bGPDframe_Runtime)
+
/** Index of this frame in the listbase of frames. */
int frameid;
/** Onion offset from active frame. 0 if not onion. INT_MAX to bypass frame. */
@@ -382,6 +398,8 @@ typedef struct bGPDframe_Runtime {
* -> Acts as storage for the 'image' formed by strokes
*/
typedef struct bGPDframe {
+ DNA_DEFINE_CXX_METHODS(bGPDframe)
+
struct bGPDframe *next, *prev;
/** List of the simplified 'strokes' that make up the frame's data. */
@@ -416,6 +434,8 @@ typedef enum eGPDframe_Flag {
/* List of masking layers. */
typedef struct bGPDlayer_Mask {
+ DNA_DEFINE_CXX_METHODS(bGPDlayer_Mask)
+
struct bGPDlayer_Mask *next, *prev;
char name[128];
short flag;
@@ -434,6 +454,8 @@ typedef enum ebGPDlayer_Mask_Flag {
/* Runtime temp data for bGPDlayer */
typedef struct bGPDlayer_Runtime {
+ DNA_DEFINE_CXX_METHODS(bGPDlayer_Runtime)
+
/** Id for dynamic icon used to show annotation color preview for layer. */
int icon_id;
char _pad[4];
@@ -443,6 +465,8 @@ typedef struct bGPDlayer_Runtime {
/* Grease-Pencil Annotations - 'Layer' */
typedef struct bGPDlayer {
+ DNA_DEFINE_CXX_METHODS(bGPDlayer)
+
struct bGPDlayer *next, *prev;
/** List of annotations to display for frames (bGPDframe list). */
@@ -580,6 +604,8 @@ typedef enum eGPLayerBlendModes {
/* Runtime temp data for bGPdata */
typedef struct bGPdata_Runtime {
+ DNA_DEFINE_CXX_METHODS(bGPdata_Runtime)
+
/** Stroke buffer. */
void *sbuffer;
/** Temp batches cleared after drawing. */
@@ -642,6 +668,8 @@ typedef struct bGPgrid {
/* Grease-Pencil Annotations - 'DataBlock' */
typedef struct bGPdata {
+ DNA_DEFINE_CXX_METHODS(bGPdata)
+
/** Grease Pencil data is a data-block. */
ID id;
/** Animation data - for animating draw settings. */
diff --git a/source/blender/makesdna/DNA_layer_types.h b/source/blender/makesdna/DNA_layer_types.h
index 7b6fe3773f8..d5f7e25bb80 100644
--- a/source/blender/makesdna/DNA_layer_types.h
+++ b/source/blender/makesdna/DNA_layer_types.h
@@ -124,6 +124,21 @@ typedef struct ViewLayerAOV {
* matches `eViewLayerAOVType` */
int type;
} ViewLayerAOV;
+
+/* Lightgroup Renderpass definition. */
+typedef struct ViewLayerLightgroup {
+ struct ViewLayerLightgroup *next, *prev;
+
+ /* Name of the Lightgroup */
+ char name[64];
+} ViewLayerLightgroup;
+
+/* Lightgroup membership information. */
+typedef struct LightgroupMembership {
+ /* Name of the Lightgroup */
+ char name[64];
+} LightgroupMembership;
+
typedef struct ViewLayer {
struct ViewLayer *next, *prev;
/** MAX_NAME. */
@@ -164,6 +179,10 @@ typedef struct ViewLayer {
ListBase aovs;
ViewLayerAOV *active_aov;
+ /* List containing the 'ViewLayerLightgroup`s */
+ ListBase lightgroups;
+ ViewLayerLightgroup *active_lightgroup;
+
/* Runtime data */
/** ViewLayerEngineData. */
ListBase drawdata;
diff --git a/source/blender/makesdna/DNA_modifier_defaults.h b/source/blender/makesdna/DNA_modifier_defaults.h
index 299ac4e2fbe..77730ce254c 100644
--- a/source/blender/makesdna/DNA_modifier_defaults.h
+++ b/source/blender/makesdna/DNA_modifier_defaults.h
@@ -309,7 +309,7 @@
.falloff = 0.0f, \
.curfalloff = NULL, \
.indexar = NULL, \
- .totindex = 0, \
+ .indexar_num = 0, \
.force = 1.0f, \
.name = "", \
}
@@ -317,7 +317,7 @@
#define _DNA_DEFAULT_LaplacianDeformModifierData \
{ \
.anchor_grp_name = "", \
- .total_verts = 0, \
+ .verts_num = 0, \
.repeat = 1, \
.vertexco = NULL, \
.cache_system = NULL, \
@@ -381,13 +381,13 @@
.bindinfluences = NULL, \
.bindoffsets = NULL, \
.bindcagecos = NULL, \
- .totvert = 0, \
- .totcagevert = 0, \
+ .verts_num = 0, \
+ .cage_verts_num = 0, \
.dyngrid = NULL, \
.dyninfluences = NULL, \
.dynverts = NULL, \
.dyngridsize = 0, \
- .totinfluence = 0, \
+ .influences_num = 0, \
.dyncellmin = {0.0f, 0.0f, 0.0f}, \
.dyncellwidth = 0.0f, \
.bindmat = _DNA_DEFAULT_UNIT_M4, \
@@ -621,7 +621,7 @@
.mesh = NULL, \
.bvhtree = NULL, \
.cfra = 0, \
- .numverts = 0, \
+ .verts_num = 0, \
}
#define _DNA_DEFAULT_SurfaceDeformModifierData \
@@ -630,9 +630,9 @@
.target = NULL, \
.verts = NULL, \
.falloff = 4.0f, \
- .num_mesh_verts = 0, \
- .num_bind_verts = 0, \
- .numpoly = 0, \
+ .mesh_verts_num = 0, \
+ .bind_verts_num = 0, \
+ .polys_num = 0, \
.flags = 0, \
.mat = _DNA_DEFAULT_UNIT_M4, \
.strength = 1.0f, \
@@ -650,7 +650,7 @@
#define _DNA_DEFAULT_UVProjectModifierData \
{ \
.projectors = {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}, \
- .num_projectors = 1, \
+ .projectors_num = 1, \
.aspectx = 1.0f, \
.aspecty = 1.0f, \
.scalex = 1.0f, \
diff --git a/source/blender/makesdna/DNA_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h
index 807a615f7f9..11825de4b33 100644
--- a/source/blender/makesdna/DNA_modifier_types.h
+++ b/source/blender/makesdna/DNA_modifier_types.h
@@ -617,7 +617,7 @@ typedef struct UVProjectModifierData {
*/
struct Object *projectors[10];
char _pad2[4];
- int num_projectors;
+ int projectors_num;
float aspectx, aspecty;
float scalex, scaley;
/** MAX_CUSTOMDATA_LAYER_NAME. */
@@ -812,7 +812,7 @@ typedef struct HookModifierData {
/** If NULL, it's using vertexgroup. */
int *indexar;
- int totindex;
+ int indexar_num;
float force;
/** Optional vertexgroup name, MAX_VGROUP_NAME. */
char name[64];
@@ -895,7 +895,7 @@ typedef struct SurfaceModifierData {
/** Bounding volume hierarchy of the mesh faces. */
struct BVHTreeFromMesh *bvhtree;
- int cfra, numverts;
+ int cfra, verts_num;
} SurfaceModifierData;
typedef struct BooleanModifierData {
@@ -945,7 +945,7 @@ typedef struct MDefInfluence {
typedef struct MDefCell {
int offset;
- int totinfluence;
+ int influences_num;
} MDefCell;
typedef struct MeshDeformModifierData {
@@ -967,7 +967,7 @@ typedef struct MeshDeformModifierData {
/** Coordinates that cage was bound with. */
float *bindcagecos;
/** Total vertices in mesh and cage. */
- int totvert, totcagevert;
+ int verts_num, cage_verts_num;
/* result of dynamic binding */
/** Grid with dynamic binding cell points. */
@@ -979,7 +979,7 @@ typedef struct MeshDeformModifierData {
/** Size of the dynamic bind grid. */
int dyngridsize;
/** Total number of vertex influences. */
- int totinfluence;
+ int influences_num;
/** Offset of the dynamic bind grid. */
float dyncellmin[3];
/** Width of dynamic bind cell. */
@@ -998,7 +998,7 @@ typedef struct MeshDeformModifierData {
struct MeshDeformModifierData *mmd,
struct Mesh *cagemesh,
float *vertexcos,
- int totvert,
+ int verts_num,
float cagemat[4][4]);
} MeshDeformModifierData;
@@ -2018,7 +2018,7 @@ typedef struct LaplacianDeformModifierData {
ModifierData modifier;
/** MAX_VGROUP_NAME. */
char anchor_grp_name[64];
- int total_verts, repeat;
+ int verts_num, repeat;
float *vertexco;
/** Runtime only. */
void *cache_system;
@@ -2201,7 +2201,7 @@ enum {
typedef struct SDefBind {
unsigned int *vert_inds;
- unsigned int numverts;
+ unsigned int verts_num;
int mode;
float *vert_weights;
float normal_dist;
@@ -2210,7 +2210,7 @@ typedef struct SDefBind {
typedef struct SDefVert {
SDefBind *binds;
- unsigned int numbinds;
+ unsigned int binds_num;
unsigned int vertex_idx;
} SDefVert;
@@ -2223,7 +2223,7 @@ typedef struct SurfaceDeformModifierData {
/** Vertex bind data. */
SDefVert *verts;
float falloff;
- unsigned int num_mesh_verts, num_bind_verts, numpoly;
+ unsigned int mesh_verts_num, bind_verts_num, polys_num;
int flags;
float mat[4][4];
float strength;
diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h
index 99d7e15fa7a..73539bea8ee 100644
--- a/source/blender/makesdna/DNA_node_types.h
+++ b/source/blender/makesdna/DNA_node_types.h
@@ -1189,7 +1189,7 @@ typedef struct NodeCryptomatte {
/** Legacy attributes */
/* Number of input sockets. */
- int num_inputs;
+ int inputs_num;
char _pad[4];
NodeCryptomatte_Runtime runtime;
diff --git a/source/blender/makesdna/DNA_object_types.h b/source/blender/makesdna/DNA_object_types.h
index c3708e25ee7..54627e711ff 100644
--- a/source/blender/makesdna/DNA_object_types.h
+++ b/source/blender/makesdna/DNA_object_types.h
@@ -31,6 +31,7 @@ struct Curve;
struct FluidsimSettings;
struct GeometrySet;
struct Ipo;
+struct LightgroupMembership;
struct Material;
struct Mesh;
struct Object;
@@ -93,7 +94,7 @@ typedef struct BoundBox {
/** #BoundBox.flag */
enum {
- BOUNDBOX_DISABLED = (1 << 0),
+ /* BOUNDBOX_DISABLED = (1 << 0), */ /* UNUSED */
BOUNDBOX_DIRTY = (1 << 1),
};
@@ -203,7 +204,7 @@ typedef struct Object_Runtime {
float (*crazyspace_deform_imats)[3][3];
float (*crazyspace_deform_cos)[3];
- int crazyspace_num_verts;
+ int crazyspace_verts_num;
int _pad3[3];
} Object_Runtime;
@@ -434,8 +435,10 @@ typedef struct Object {
ObjectLineArt lineart;
+ /** Lightgroup membership information. */
+ struct LightgroupMembership *lightgroup;
+
/** Runtime evaluation data (keep last). */
- void *_pad9;
Object_Runtime runtime;
} Object;
diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h
index e6b2f2769b8..ed049bb6a9d 100644
--- a/source/blender/makesdna/DNA_scene_types.h
+++ b/source/blender/makesdna/DNA_scene_types.h
@@ -1113,7 +1113,7 @@ typedef struct GP_Sculpt_Settings {
/** Threshold for intersections */
float isect_threshold;
char _pad[4];
- /** Multiframe edit falloff effect by frame. */
+ /** Multi-frame edit falloff effect by frame. */
struct CurveMapping *cur_falloff;
/** Curve used for primitive tools. */
struct CurveMapping *cur_primitive;
@@ -1990,7 +1990,7 @@ enum {
/* sequencer seq_prev_type seq_rend_type */
-/** #RenderData.engine (scene.c) */
+/** #RenderData.engine (scene.cc) */
extern const char *RE_engine_id_BLENDER_EEVEE;
extern const char *RE_engine_id_BLENDER_WORKBENCH;
extern const char *RE_engine_id_CYCLES;
@@ -2017,7 +2017,10 @@ extern const char *RE_engine_id_CYCLES;
((v3d == NULL) || (((1 << (base)->object->type) & (v3d)->object_type_exclude_select) == 0)) && \
(((base)->flag & BASE_SELECTABLE) != 0))
#define BASE_SELECTED(v3d, base) (BASE_VISIBLE(v3d, base) && (((base)->flag & BASE_SELECTED) != 0))
-#define BASE_EDITABLE(v3d, base) (BASE_VISIBLE(v3d, base) && !ID_IS_LINKED((base)->object))
+#define BASE_EDITABLE(v3d, base) \
+ (BASE_VISIBLE(v3d, base) && !ID_IS_LINKED((base)->object) && \
+ (!ID_IS_OVERRIDE_LIBRARY_REAL((base)->object) || \
+ ((base)->object->id.override_library->flag & IDOVERRIDE_LIBRARY_FLAG_SYSTEM_DEFINED) == 0))
#define BASE_SELECTED_EDITABLE(v3d, base) \
(BASE_EDITABLE(v3d, base) && (((base)->flag & BASE_SELECTED) != 0))
diff --git a/source/blender/makesdna/DNA_screen_types.h b/source/blender/makesdna/DNA_screen_types.h
index d32757cc868..c1eee109630 100644
--- a/source/blender/makesdna/DNA_screen_types.h
+++ b/source/blender/makesdna/DNA_screen_types.h
@@ -540,7 +540,7 @@ enum {
AREA_FLAG_STACKED_FULLSCREEN = (1 << 7),
/** Update action zones (even if the mouse is not intersecting them). */
AREA_FLAG_ACTIONZONES_UPDATE = (1 << 8),
- /** For offscreen areas. */
+ /** For off-screen areas. */
AREA_FLAG_OFFSCREEN = (1 << 9),
};
diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h
index f538917143b..e9bf3126c97 100644
--- a/source/blender/makesdna/DNA_space_types.h
+++ b/source/blender/makesdna/DNA_space_types.h
@@ -280,8 +280,12 @@ typedef struct SpaceOutliner {
char search_string[64];
struct TreeStoreElem search_tse;
- short flag, outlinevis, storeflag;
+ short flag;
+ short outlinevis;
+ short lib_override_view_mode;
+ short storeflag;
char search_flags;
+ char _pad[6];
/** Selection syncing flag (#WM_OUTLINER_SYNC_SELECT_FROM_OBJECT and similar flags). */
char sync_select_dirty;
@@ -388,6 +392,14 @@ typedef enum eSpaceOutliner_Mode {
SO_OVERRIDES_LIBRARY = 16,
} eSpaceOutliner_Mode;
+/** #SpaceOutliner.outlinevis */
+typedef enum eSpaceOutliner_LibOverrideViewMode {
+ /* View all overrides with RNA buttons to edit the overridden values. */
+ SO_LIB_OVERRIDE_VIEW_PROPERTIES = 0,
+ /* View entire override hierarchies (relationships between overriden data-blocks). */
+ SO_LIB_OVERRIDE_VIEW_HIERARCHIES = 1,
+} eSpaceOutliner_LibOverrideViewMode;
+
/** #SpaceOutliner.storeflag */
typedef enum eSpaceOutliner_StoreFlag {
/* cleanup tree */
@@ -989,12 +1001,6 @@ typedef enum eFileSelectType {
FILE_SPECIAL = 9,
} eFileSelectType;
-/** File-selector op property -> action. */
-typedef enum eFileSel_Action {
- FILE_OPENFILE = 0,
- FILE_SAVE = 1,
-} eFileSel_Action;
-
/**
* #FileSelectParams.flag / `sfile->params->flag`.
* \note short flag, also used as 16 lower bits of flags in link/append code
diff --git a/source/blender/makesdna/DNA_world_types.h b/source/blender/makesdna/DNA_world_types.h
index 497b99eb04d..88f2e0c9407 100644
--- a/source/blender/makesdna/DNA_world_types.h
+++ b/source/blender/makesdna/DNA_world_types.h
@@ -16,6 +16,7 @@ extern "C" {
struct AnimData;
struct Ipo;
+struct LightgroupMembership;
struct bNodeTree;
#ifndef MAX_MTEX
@@ -70,6 +71,9 @@ typedef struct World {
/* nodes */
struct bNodeTree *nodetree;
+ /* Lightgroup membership information. */
+ struct LightgroupMembership *lightgroup;
+
/** Runtime. */
ListBase gpumaterial;
} World;
diff --git a/source/blender/makesdna/intern/dna_rename_defs.h b/source/blender/makesdna/intern/dna_rename_defs.h
index b2896c80db3..86649357433 100644
--- a/source/blender/makesdna/intern/dna_rename_defs.h
+++ b/source/blender/makesdna/intern/dna_rename_defs.h
@@ -74,31 +74,45 @@ DNA_STRUCT_RENAME_ELEM(FluidDomainSettings, guiding_parent, guide_parent)
DNA_STRUCT_RENAME_ELEM(FluidDomainSettings, guiding_source, guide_source)
DNA_STRUCT_RENAME_ELEM(FluidDomainSettings, guiding_vel_factor, guide_vel_factor)
DNA_STRUCT_RENAME_ELEM(FluidEffectorSettings, guiding_mode, guide_mode)
+DNA_STRUCT_RENAME_ELEM(HookModifierData, totindex, indexar_num)
DNA_STRUCT_RENAME_ELEM(Image, name, filepath)
+DNA_STRUCT_RENAME_ELEM(LaplacianDeformModifierData, total_verts, verts_num)
DNA_STRUCT_RENAME_ELEM(Library, name, filepath)
DNA_STRUCT_RENAME_ELEM(LineartGpencilModifierData, line_types, edge_types)
DNA_STRUCT_RENAME_ELEM(LineartGpencilModifierData, transparency_flags, mask_switches)
DNA_STRUCT_RENAME_ELEM(LineartGpencilModifierData, transparency_mask, material_mask_bits)
+DNA_STRUCT_RENAME_ELEM(MDefCell, totinfluence, influences_num)
DNA_STRUCT_RENAME_ELEM(MaskLayer, restrictflag, visibility_flag)
DNA_STRUCT_RENAME_ELEM(MaterialLineArt, transparency_mask, material_mask_bits)
+DNA_STRUCT_RENAME_ELEM(MeshDeformModifierData, totcagevert, cage_verts_num)
+DNA_STRUCT_RENAME_ELEM(MeshDeformModifierData, totinfluence, influences_num)
+DNA_STRUCT_RENAME_ELEM(MeshDeformModifierData, totvert, verts_num)
DNA_STRUCT_RENAME_ELEM(MovieClip, name, filepath)
+DNA_STRUCT_RENAME_ELEM(NodeCryptomatte, num_inputs, inputs_num)
DNA_STRUCT_RENAME_ELEM(Object, col, color)
DNA_STRUCT_RENAME_ELEM(Object, dup_group, instance_collection)
DNA_STRUCT_RENAME_ELEM(Object, dupfacesca, instance_faces_scale)
DNA_STRUCT_RENAME_ELEM(Object, restrictflag, visibility_flag)
DNA_STRUCT_RENAME_ELEM(Object, size, scale)
+DNA_STRUCT_RENAME_ELEM(Object_Runtime, crazyspace_num_verts, crazyspace_verts_num)
DNA_STRUCT_RENAME_ELEM(ParticleSettings, child_nbr, child_percent)
DNA_STRUCT_RENAME_ELEM(ParticleSettings, dup_group, instance_collection)
DNA_STRUCT_RENAME_ELEM(ParticleSettings, dup_ob, instance_object)
DNA_STRUCT_RENAME_ELEM(ParticleSettings, dupliweights, instance_weights)
DNA_STRUCT_RENAME_ELEM(ParticleSettings, ren_child_nbr, child_render_percent)
-DNA_STRUCT_RENAME_ELEM(RigidBodyWorld, steps_per_second, substeps_per_frame)
DNA_STRUCT_RENAME_ELEM(RenderData, bake_filter, bake_margin)
+DNA_STRUCT_RENAME_ELEM(RigidBodyWorld, steps_per_second, substeps_per_frame)
+DNA_STRUCT_RENAME_ELEM(SDefBind, numverts, verts_num)
+DNA_STRUCT_RENAME_ELEM(SDefVert, numbinds, binds_num)
DNA_STRUCT_RENAME_ELEM(SpaceSeq, overlay_type, overlay_frame_type)
-DNA_STRUCT_RENAME_ELEM(SurfaceDeformModifierData, numverts, num_bind_verts)
+DNA_STRUCT_RENAME_ELEM(SurfaceDeformModifierData, num_mesh_verts, mesh_verts_num)
+DNA_STRUCT_RENAME_ELEM(SurfaceDeformModifierData, numpoly, polys_num)
+DNA_STRUCT_RENAME_ELEM(SurfaceDeformModifierData, numverts, bind_verts_num)
+DNA_STRUCT_RENAME_ELEM(SurfaceModifierData, numverts, verts_num)
DNA_STRUCT_RENAME_ELEM(Text, name, filepath)
DNA_STRUCT_RENAME_ELEM(ThemeSpace, scrubbing_background, time_scrub_background)
DNA_STRUCT_RENAME_ELEM(ThemeSpace, show_back_grad, background_type)
+DNA_STRUCT_RENAME_ELEM(UVProjectModifierData, num_projectors, projectors_num)
DNA_STRUCT_RENAME_ELEM(UserDef, gp_manhattendist, gp_manhattandist)
DNA_STRUCT_RENAME_ELEM(VFont, name, filepath)
DNA_STRUCT_RENAME_ELEM(View3D, far, clip_end)
diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h
index 4292c270b6f..e1e655fad4b 100644
--- a/source/blender/makesrna/RNA_access.h
+++ b/source/blender/makesrna/RNA_access.h
@@ -802,7 +802,7 @@ void RNA_collection_clear(PointerRNA *ptr, const char *name);
bool RNA_property_is_set_ex(PointerRNA *ptr, PropertyRNA *prop, bool use_ghost);
bool RNA_property_is_set(PointerRNA *ptr, PropertyRNA *prop);
void RNA_property_unset(PointerRNA *ptr, PropertyRNA *prop);
-/** See #RNA_property_is_set_ex documentation. */
+/** See #RNA_property_is_set_ex documentation. */
bool RNA_struct_property_is_set_ex(PointerRNA *ptr, const char *identifier, bool use_ghost);
bool RNA_struct_property_is_set(PointerRNA *ptr, const char *identifier);
bool RNA_property_is_idprop(const PropertyRNA *prop);
diff --git a/source/blender/makesrna/intern/rna_ID.c b/source/blender/makesrna/intern/rna_ID.c
index 82d90a5c54b..d3b7e380afa 100644
--- a/source/blender/makesrna/intern/rna_ID.c
+++ b/source/blender/makesrna/intern/rna_ID.c
@@ -762,7 +762,8 @@ static void rna_ID_override_library_reset(ID *id,
IDOverrideLibrary *UNUSED(override_library),
Main *bmain,
ReportList *reports,
- bool do_hierarchy)
+ bool do_hierarchy,
+ bool set_system_override)
{
if (!ID_IS_OVERRIDE_LIBRARY_REAL(id)) {
BKE_reportf(reports, RPT_ERROR, "ID '%s' isn't an override", id->name);
@@ -770,10 +771,10 @@ static void rna_ID_override_library_reset(ID *id,
}
if (do_hierarchy) {
- BKE_lib_override_library_id_hierarchy_reset(bmain, id);
+ BKE_lib_override_library_id_hierarchy_reset(bmain, id, set_system_override);
}
else {
- BKE_lib_override_library_id_reset(bmain, id);
+ BKE_lib_override_library_id_reset(bmain, id, set_system_override);
}
WM_main_add_notifier(NC_WM | ND_LIB_OVERRIDE_CHANGED, NULL);
@@ -1832,6 +1833,17 @@ static void rna_def_ID_override_library(BlenderRNA *brna)
"hierarchy, or as a single, isolated and autonomous override");
RNA_def_property_update(prop, NC_WM | ND_LIB_OVERRIDE_CHANGED, NULL);
RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", IDOVERRIDE_LIBRARY_FLAG_NO_HIERARCHY);
+ RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
+
+ prop = RNA_def_boolean(srna,
+ "is_system_override",
+ false,
+ "Is System Override",
+ "Whether this library override exists only for the override hierarchy, "
+ "or if it is actually editable by the user");
+ RNA_def_property_update(prop, NC_WM | ND_LIB_OVERRIDE_CHANGED, NULL);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", IDOVERRIDE_LIBRARY_FLAG_SYSTEM_DEFINED);
+ RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
prop = RNA_def_collection(srna,
"properties",
@@ -1858,6 +1870,11 @@ static void rna_def_ID_override_library(BlenderRNA *brna)
true,
"",
"Also reset all the dependencies of this override to match their reference linked IDs");
+ RNA_def_boolean(func,
+ "set_system_override",
+ false,
+ "",
+ "Reset all user-editable overrides as (non-editable) system overrides");
func = RNA_def_function(srna, "destroy", "rna_ID_override_library_destroy");
RNA_def_function_ui_description(
@@ -1987,6 +2004,8 @@ static void rna_def_ID(BlenderRNA *brna)
prop = RNA_def_pointer(
srna, "override_library", "IDOverrideLibrary", "Library Override", "Library override data");
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_override_flag(prop,
+ PROPOVERRIDE_NO_COMPARISON | PROPOVERRIDE_OVERRIDABLE_LIBRARY);
prop = RNA_def_pointer(srna,
"preview",
diff --git a/source/blender/makesrna/intern/rna_access.c b/source/blender/makesrna/intern/rna_access.c
index b4617321f44..5690d864a75 100644
--- a/source/blender/makesrna/intern/rna_access.c
+++ b/source/blender/makesrna/intern/rna_access.c
@@ -32,8 +32,10 @@
#include "BKE_collection.h"
#include "BKE_context.h"
#include "BKE_fcurve.h"
+#include "BKE_global.h"
#include "BKE_idprop.h"
#include "BKE_idtype.h"
+#include "BKE_lib_override.h"
#include "BKE_main.h"
#include "BKE_node.h"
#include "BKE_report.h"
@@ -1930,17 +1932,29 @@ static bool rna_property_editable_do(PointerRNA *ptr,
/* Handle linked or liboverride ID cases. */
const bool is_linked_prop_exception = (prop->flag & PROP_LIB_EXCEPTION) != 0;
- if (ID_IS_LINKED(id) && !is_linked_prop_exception) {
+ if (ID_IS_LINKED(id)) {
+ if (is_linked_prop_exception) {
+ return true;
+ }
if (r_info != NULL && (*r_info)[0] == '\0') {
*r_info = N_("Can't edit this property from a linked data-block");
}
return false;
}
- if (ID_IS_OVERRIDE_LIBRARY(id) && !RNA_property_overridable_get(ptr, prop_orig)) {
- if (r_info != NULL && (*r_info)[0] == '\0') {
- *r_info = N_("Can't edit this property from an override data-block");
+ if (ID_IS_OVERRIDE_LIBRARY(id)) {
+ const bool is_liboverride_system = BKE_lib_override_library_is_system_defined(G_MAIN, id);
+ if (!RNA_property_overridable_get(ptr, prop_orig)) {
+ if (r_info != NULL && (*r_info)[0] == '\0') {
+ *r_info = N_("Can't edit this property from an override data-block");
+ }
+ return false;
+ }
+ if (is_liboverride_system && !is_linked_prop_exception) {
+ if (r_info != NULL && (*r_info)[0] == '\0') {
+ *r_info = N_("Can't edit this property from a system override data-block");
+ }
+ return false;
}
- return false;
}
/* At this point, property is owned by a local ID and therefore fully editable. */
@@ -6012,13 +6026,29 @@ char *RNA_path_struct_property_py(PointerRNA *ptr, PropertyRNA *prop, int index)
char *RNA_path_property_py(const PointerRNA *UNUSED(ptr), PropertyRNA *prop, int index)
{
+ const bool is_rna = (prop->magic == RNA_MAGIC);
+ const char *propname = RNA_property_identifier(prop);
char *ret;
if ((index == -1) || (RNA_property_array_check(prop) == false)) {
- ret = BLI_sprintfN("%s", RNA_property_identifier(prop));
+ if (is_rna) {
+ ret = BLI_strdup(propname);
+ }
+ else {
+ char propname_esc[MAX_IDPROP_NAME * 2];
+ BLI_str_escape(propname_esc, propname, sizeof(propname_esc));
+ ret = BLI_sprintfN("[\"%s\"]", propname_esc);
+ }
}
else {
- ret = BLI_sprintfN("%s[%d]", RNA_property_identifier(prop), index);
+ if (is_rna) {
+ ret = BLI_sprintfN("%s[%d]", propname, index);
+ }
+ else {
+ char propname_esc[MAX_IDPROP_NAME * 2];
+ BLI_str_escape(propname_esc, propname, sizeof(propname_esc));
+ ret = BLI_sprintfN("[\"%s\"][%d]", propname_esc, index);
+ }
}
return ret;
diff --git a/source/blender/makesrna/intern/rna_access_compare_override.c b/source/blender/makesrna/intern/rna_access_compare_override.c
index cce310e4b6d..5974788884e 100644
--- a/source/blender/makesrna/intern/rna_access_compare_override.c
+++ b/source/blender/makesrna/intern/rna_access_compare_override.c
@@ -612,10 +612,6 @@ static bool rna_property_override_operation_apply(Main *bmain,
ptr_item_src,
ptr_item_storage,
opop);
- if (success) {
- RNA_property_update_main(bmain, NULL, ptr_dst, prop_dst);
- }
-
return success;
}
diff --git a/source/blender/makesrna/intern/rna_animation.c b/source/blender/makesrna/intern/rna_animation.c
index ba7f3c55460..4f07cb235fa 100644
--- a/source/blender/makesrna/intern/rna_animation.c
+++ b/source/blender/makesrna/intern/rna_animation.c
@@ -680,7 +680,7 @@ static FCurve *rna_Driver_find(AnimData *adt,
return BKE_fcurve_find(&adt->drivers, data_path, index);
}
-bool rna_AnimaData_override_apply(Main *UNUSED(bmain),
+bool rna_AnimaData_override_apply(Main *bmain,
PointerRNA *ptr_dst,
PointerRNA *ptr_src,
PointerRNA *ptr_storage,
@@ -707,11 +707,13 @@ bool rna_AnimaData_override_apply(Main *UNUSED(bmain),
if (adt_dst == NULL && adt_src != NULL) {
/* Copy anim data from reference into final local ID. */
BKE_animdata_copy_id(NULL, ptr_dst->owner_id, ptr_src->owner_id, 0);
+ RNA_property_update_main(bmain, NULL, ptr_dst, prop_dst);
return true;
}
else if (adt_dst != NULL && adt_src == NULL) {
/* Override has cleared/removed anim data from its reference. */
BKE_animdata_free(ptr_dst->owner_id, true);
+ RNA_property_update_main(bmain, NULL, ptr_dst, prop_dst);
return true;
}
@@ -722,7 +724,7 @@ bool rna_NLA_tracks_override_apply(Main *bmain,
PointerRNA *ptr_dst,
PointerRNA *ptr_src,
PointerRNA *UNUSED(ptr_storage),
- PropertyRNA *UNUSED(prop_dst),
+ PropertyRNA *prop_dst,
PropertyRNA *UNUSED(prop_src),
PropertyRNA *UNUSED(prop_storage),
const int UNUSED(len_dst),
@@ -771,6 +773,8 @@ bool rna_NLA_tracks_override_apply(Main *bmain,
BLI_insertlinkafter(&anim_data_dst->nla_tracks, nla_track_anchor, nla_track_dst);
// printf("%s: We inserted a NLA Track...\n", __func__);
+
+ RNA_property_update_main(bmain, NULL, ptr_dst, prop_dst);
return true;
}
diff --git a/source/blender/makesrna/intern/rna_collection.c b/source/blender/makesrna/intern/rna_collection.c
index eceabe65a67..599d36c0af7 100644
--- a/source/blender/makesrna/intern/rna_collection.c
+++ b/source/blender/makesrna/intern/rna_collection.c
@@ -138,7 +138,7 @@ static bool rna_Collection_objects_override_apply(Main *bmain,
PointerRNA *ptr_dst,
PointerRNA *UNUSED(ptr_src),
PointerRNA *UNUSED(ptr_storage),
- PropertyRNA *UNUSED(prop_dst),
+ PropertyRNA *prop_dst,
PropertyRNA *UNUSED(prop_src),
PropertyRNA *UNUSED(prop_storage),
const int UNUSED(len_dst),
@@ -185,6 +185,7 @@ static bool rna_Collection_objects_override_apply(Main *bmain,
BKE_main_collection_sync(bmain);
}
+ RNA_property_update_main(bmain, NULL, ptr_dst, prop_dst);
return true;
}
@@ -245,7 +246,7 @@ static bool rna_Collection_children_override_apply(Main *bmain,
PointerRNA *ptr_dst,
PointerRNA *UNUSED(ptr_src),
PointerRNA *UNUSED(ptr_storage),
- PropertyRNA *UNUSED(prop_dst),
+ PropertyRNA *prop_dst,
PropertyRNA *UNUSED(prop_src),
PropertyRNA *UNUSED(prop_storage),
const int UNUSED(len_dst),
@@ -287,6 +288,7 @@ static bool rna_Collection_children_override_apply(Main *bmain,
BKE_collection_object_cache_free(coll_dst);
BKE_main_collection_sync(bmain);
+ RNA_property_update_main(bmain, NULL, ptr_dst, prop_dst);
return true;
}
diff --git a/source/blender/makesrna/intern/rna_gpencil.c b/source/blender/makesrna/intern/rna_gpencil.c
index ba94fbe88e5..9a9b6d582e5 100644
--- a/source/blender/makesrna/intern/rna_gpencil.c
+++ b/source/blender/makesrna/intern/rna_gpencil.c
@@ -848,10 +848,6 @@ static float rna_GPencilStrokePoints_weight_get(bGPDstroke *stroke,
}
MDeformVert *pt_dvert = stroke->dvert + point_index;
- if ((pt_dvert) && (pt_dvert->totweight <= vertex_group_index || vertex_group_index < 0)) {
- BKE_report(reports, RPT_ERROR, "Groups: index out of range");
- return -1.0f;
- }
MDeformWeight *dw = BKE_defvert_find_index(pt_dvert, vertex_group_index);
if (dw) {
diff --git a/source/blender/makesrna/intern/rna_gpencil_modifier.c b/source/blender/makesrna/intern/rna_gpencil_modifier.c
index 9e25ddaf790..b09d8a4738d 100644
--- a/source/blender/makesrna/intern/rna_gpencil_modifier.c
+++ b/source/blender/makesrna/intern/rna_gpencil_modifier.c
@@ -382,6 +382,7 @@ RNA_GP_MOD_VGROUP_NAME_SET(WeightAngle, vgname);
RNA_GP_MOD_VGROUP_NAME_SET(Lineart, vgname);
RNA_GP_MOD_VGROUP_NAME_SET(Shrinkwrap, vgname);
RNA_GP_MOD_VGROUP_NAME_SET(Envelope, vgname);
+RNA_GP_MOD_VGROUP_NAME_SET(Build, target_vgname);
# undef RNA_GP_MOD_VGROUP_NAME_SET
@@ -416,6 +417,7 @@ RNA_GP_MOD_OBJECT_SET(Mirror, object, OB_EMPTY);
RNA_GP_MOD_OBJECT_SET(WeightProx, object, OB_EMPTY);
RNA_GP_MOD_OBJECT_SET(Shrinkwrap, target, OB_MESH);
RNA_GP_MOD_OBJECT_SET(Shrinkwrap, aux_target, OB_MESH);
+RNA_GP_MOD_OBJECT_SET(Build, object, OB_EMPTY);
# undef RNA_GP_MOD_OBJECT_SET
@@ -1031,7 +1033,7 @@ static void rna_def_modifier_gpencilsmooth(BlenderRNA *brna)
prop, "Step", "Number of times to apply smooth (high numbers can reduce fps)");
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
- prop = RNA_def_property(srna, "keep_shape", PROP_BOOLEAN, PROP_NONE);
+ prop = RNA_def_property(srna, "use_keep_shape", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_SMOOTH_KEEP_SHAPE);
RNA_def_property_ui_text(prop, "Keep Shape", "Smooth the details, but keep the overall shape");
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
@@ -2133,10 +2135,10 @@ static void rna_def_modifier_gpencilbuild(BlenderRNA *brna)
"Shrink",
"Hide points from the end of each stroke to the start "
"(e.g. for animating lines being erased)"},
- {GP_BUILD_TRANSITION_FADE,
- "FADE",
+ {GP_BUILD_TRANSITION_VANISH,
+ "FADE", /* "Fade" is the original id string kept for compatibility purpose. */
0,
- "Fade",
+ "Vanish",
"Hide points in the order they occur in each stroke "
"(e.g. for animating ink fading or vanishing after getting drawn)"},
{0, NULL, 0, NULL, NULL},
@@ -2242,6 +2244,43 @@ static void rna_def_modifier_gpencilbuild(BlenderRNA *brna)
RNA_def_property_range(prop, MINAFRAMEF, MAXFRAMEF);
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+ prop = RNA_def_property(srna, "use_fading", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_BUILD_USE_FADING);
+ RNA_def_property_ui_text(prop, "Use Fading", "Fade out strokes instead of directly cutting off");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "fade_factor", PROP_FLOAT, PROP_FACTOR);
+ RNA_def_property_float_sdna(prop, NULL, "fade_fac");
+ RNA_def_property_ui_text(prop, "Fade Factor", "Defines how much of the stroke is fading in/out");
+ RNA_def_property_range(prop, 0.0f, 1.0f);
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "target_vertex_group", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_sdna(prop, NULL, "target_vgname");
+ RNA_def_property_ui_text(prop, "Vertex Group", "Output Vertex group");
+ RNA_def_property_string_funcs(prop, NULL, NULL, "rna_BuildGpencilModifier_target_vgname_set");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "fade_opacity_strength", PROP_FLOAT, PROP_FACTOR);
+ RNA_def_property_float_sdna(prop, NULL, "fade_opacity_strength");
+ RNA_def_property_ui_text(
+ prop, "Opacity Strength", "How much strength fading applies on top of stroke opacity");
+ RNA_def_property_range(prop, 0.0f, 1.0f);
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "fade_thickness_strength", PROP_FLOAT, PROP_FACTOR);
+ RNA_def_property_float_sdna(prop, NULL, "fade_thickness_strength");
+ RNA_def_property_ui_text(
+ prop, "Thickness Strength", "How much strength fading applies on top of stroke thickness");
+ RNA_def_property_range(prop, 0.0f, 1.0f);
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "object", PROP_POINTER, PROP_NONE);
+ RNA_def_property_ui_text(prop, "Object", "Object used as build starting position");
+ RNA_def_property_pointer_funcs(prop, NULL, "rna_BuildGpencilModifier_object_set", NULL, NULL);
+ RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK);
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_dependency_update");
+
/* Filters - Layer */
prop = RNA_def_property(srna, "layer", PROP_STRING, PROP_NONE);
RNA_def_property_string_sdna(prop, NULL, "layername");
@@ -3745,7 +3784,7 @@ static void rna_def_modifier_gpencildash(BlenderRNA *brna)
prop = RNA_def_property(srna, "use_cyclic", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_DASH_USE_CYCLIC);
- RNA_def_property_ui_text(prop, "Use Cyclic", "Enable cyclic on individual stroke dashes");
+ RNA_def_property_ui_text(prop, "Cyclic", "Enable cyclic on individual stroke dashes");
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
srna = RNA_def_struct(brna, "DashGpencilModifierData", "GpencilModifier");
diff --git a/source/blender/makesrna/intern/rna_internal.h b/source/blender/makesrna/intern/rna_internal.h
index 84f083cb37a..0df0be07fee 100644
--- a/source/blender/makesrna/intern/rna_internal.h
+++ b/source/blender/makesrna/intern/rna_internal.h
@@ -355,6 +355,10 @@ void rna_ViewLayer_active_aov_index_range(
PointerRNA *ptr, int *min, int *max, int *softmin, int *softmax);
int rna_ViewLayer_active_aov_index_get(PointerRNA *ptr);
void rna_ViewLayer_active_aov_index_set(PointerRNA *ptr, int value);
+void rna_ViewLayer_active_lightgroup_index_range(
+ PointerRNA *ptr, int *min, int *max, int *softmin, int *softmax);
+int rna_ViewLayer_active_lightgroup_index_get(PointerRNA *ptr);
+void rna_ViewLayer_active_lightgroup_index_set(PointerRNA *ptr, int value);
/**
* Set `r_rna_path` with the base view-layer path.
* `rna_path_buffer_size` should be at least `sizeof(ViewLayer.name) * 3`.
diff --git a/source/blender/makesrna/intern/rna_main_api.c b/source/blender/makesrna/intern/rna_main_api.c
index b239260c8eb..6c621604e40 100644
--- a/source/blender/makesrna/intern/rna_main_api.c
+++ b/source/blender/makesrna/intern/rna_main_api.c
@@ -92,6 +92,7 @@
# include "DNA_volume_types.h"
# include "DNA_world_types.h"
+# include "ED_node.h"
# include "ED_screen.h"
# include "BLT_translation.h"
@@ -291,6 +292,7 @@ static struct bNodeTree *rna_Main_nodetree_new(Main *bmain, const char *name, in
bNodeTreeType *typeinfo = rna_node_tree_type_from_enum(type);
if (typeinfo) {
bNodeTree *ntree = ntreeAddTree(bmain, safe_name, typeinfo->idname);
+ ED_node_tree_propagate_change(NULL, bmain, ntree);
id_us_min(&ntree->id);
return ntree;
diff --git a/source/blender/makesrna/intern/rna_modifier.c b/source/blender/makesrna/intern/rna_modifier.c
index 2ef2e776842..4f9a10c9993 100644
--- a/source/blender/makesrna/intern/rna_modifier.c
+++ b/source/blender/makesrna/intern/rna_modifier.c
@@ -687,7 +687,7 @@ static void rna_UVProject_projectors_begin(CollectionPropertyIterator *iter, Poi
{
UVProjectModifierData *uvp = (UVProjectModifierData *)ptr->data;
rna_iterator_array_begin(
- iter, (void *)uvp->projectors, sizeof(Object *), uvp->num_projectors, 0, NULL);
+ iter, (void *)uvp->projectors, sizeof(Object *), uvp->projectors_num, 0, NULL);
}
static StructRNA *rna_Modifier_refine(struct PointerRNA *ptr)
@@ -895,7 +895,7 @@ static void rna_HookModifier_object_set(PointerRNA *ptr,
BKE_object_modifier_hook_reset(owner, hmd);
}
-static bool rna_HookModifier_object_override_apply(Main *UNUSED(bmain),
+static bool rna_HookModifier_object_override_apply(Main *bmain,
PointerRNA *ptr_dst,
PointerRNA *ptr_src,
PointerRNA *ptr_storage,
@@ -933,6 +933,7 @@ static bool rna_HookModifier_object_override_apply(Main *UNUSED(bmain),
/* The only case where we do want default behavior (with matrix reset). */
BKE_object_modifier_hook_reset(owner, hmd);
}
+ RNA_property_update_main(bmain, NULL, ptr_dst, prop_dst);
return true;
}
@@ -949,15 +950,15 @@ static int rna_HookModifier_vertex_indices_get_length(PointerRNA *ptr,
int length[RNA_MAX_ARRAY_DIMENSION])
{
HookModifierData *hmd = ptr->data;
- int totindex = hmd->indexar ? hmd->totindex : 0;
- return (length[0] = totindex);
+ int indexar_num = hmd->indexar ? hmd->indexar_num : 0;
+ return (length[0] = indexar_num);
}
static void rna_HookModifier_vertex_indices_get(PointerRNA *ptr, int *values)
{
HookModifierData *hmd = ptr->data;
if (hmd->indexar != NULL) {
- memcpy(values, hmd->indexar, sizeof(int) * hmd->totindex);
+ memcpy(values, hmd->indexar, sizeof(int) * hmd->indexar_num);
}
}
@@ -968,7 +969,7 @@ static void rna_HookModifier_vertex_indices_set(HookModifierData *hmd,
{
if (indices_len == 0) {
MEM_SAFE_FREE(hmd->indexar);
- hmd->totindex = 0;
+ hmd->indexar_num = 0;
}
else {
/* Reject negative indices. */
@@ -998,7 +999,7 @@ static void rna_HookModifier_vertex_indices_set(HookModifierData *hmd,
/* Success - save the new array. */
MEM_SAFE_FREE(hmd->indexar);
hmd->indexar = buffer;
- hmd->totindex = indices_len;
+ hmd->indexar_num = indices_len;
}
}
@@ -1148,8 +1149,8 @@ static void rna_UVProjectModifier_num_projectors_set(PointerRNA *ptr, int value)
UVProjectModifierData *md = (UVProjectModifierData *)ptr->data;
int a;
- md->num_projectors = CLAMPIS(value, 1, MOD_UVPROJECT_MAXPROJECTORS);
- for (a = md->num_projectors; a < MOD_UVPROJECT_MAXPROJECTORS; a++) {
+ md->projectors_num = CLAMPIS(value, 1, MOD_UVPROJECT_MAXPROJECTORS);
+ for (a = md->projectors_num; a < MOD_UVPROJECT_MAXPROJECTORS; a++) {
md->projectors[a] = NULL;
}
}
@@ -3104,7 +3105,7 @@ static void rna_def_modifier_uvproject(BlenderRNA *brna)
RNA_def_property_update(prop, 0, "rna_Modifier_update");
prop = RNA_def_property(srna, "projector_count", PROP_INT, PROP_NONE);
- RNA_def_property_int_sdna(prop, NULL, "num_projectors");
+ RNA_def_property_int_sdna(prop, NULL, "projectors_num");
RNA_def_property_ui_text(prop, "Number of Projectors", "Number of projectors to use");
RNA_def_property_int_funcs(prop, NULL, "rna_UVProjectModifier_num_projectors_set", NULL);
RNA_def_property_range(prop, 1, MOD_UVPROJECT_MAXPROJECTORS);
@@ -4081,7 +4082,8 @@ static void rna_def_modifier_bevel(BlenderRNA *brna)
prop = RNA_def_property(srna, "segments", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "res");
- RNA_def_property_range(prop, 1, 100);
+ RNA_def_property_range(prop, 1, 1000);
+ RNA_def_property_ui_range(prop, 1, 100, 1, -1);
RNA_def_property_ui_text(prop, "Segments", "Number of segments for round edges/verts");
RNA_def_property_update(prop, 0, "rna_BevelModifier_update_segments");
diff --git a/source/blender/makesrna/intern/rna_object.c b/source/blender/makesrna/intern/rna_object.c
index 7164f24c2f7..f995ee3383e 100644
--- a/source/blender/makesrna/intern/rna_object.c
+++ b/source/blender/makesrna/intern/rna_object.c
@@ -200,12 +200,6 @@ static EnumPropertyItem instance_items_nogroup[] = {
{0, NULL, 0, NULL, NULL},
};
-static EnumPropertyItem instance_items_pointcloud[] = {
- {0, "NONE", 0, "None", ""},
- {OB_DUPLIVERTS, "POINTS", 0, "Points", "Instantiate child objects on all points"},
- {0, NULL, 0, NULL, NULL},
-};
-
static EnumPropertyItem instance_items_empty[] = {
{0, "NONE", 0, "None", ""},
INSTANCE_ITEM_COLLECTION,
@@ -652,7 +646,7 @@ static void rna_Object_parent_set(PointerRNA *ptr,
}
}
-static bool rna_Object_parent_override_apply(Main *UNUSED(bmain),
+static bool rna_Object_parent_override_apply(Main *bmain,
PointerRNA *ptr_dst,
PointerRNA *ptr_src,
PointerRNA *ptr_storage,
@@ -689,6 +683,7 @@ static bool rna_Object_parent_override_apply(Main *UNUSED(bmain),
else {
ob->parent = parent_src;
}
+ RNA_property_update_main(bmain, NULL, ptr_dst, prop_dst);
return true;
}
@@ -760,9 +755,6 @@ static const EnumPropertyItem *rna_Object_instance_type_itemf(bContext *UNUSED(C
if (ob->type == OB_EMPTY) {
item = instance_items_empty;
}
- else if (ob->type == OB_POINTCLOUD) {
- item = instance_items_pointcloud;
- }
else if (ob->type == OB_FONT) {
item = instance_items_font;
}
@@ -1676,11 +1668,11 @@ static bConstraint *rna_Object_constraints_copy(Object *object, Main *bmain, Poi
return new_con;
}
-bool rna_Object_constraints_override_apply(Main *UNUSED(bmain),
+bool rna_Object_constraints_override_apply(Main *bmain,
PointerRNA *ptr_dst,
PointerRNA *ptr_src,
PointerRNA *UNUSED(ptr_storage),
- PropertyRNA *UNUSED(prop_dst),
+ PropertyRNA *prop_dst,
PropertyRNA *UNUSED(prop_src),
PropertyRNA *UNUSED(prop_storage),
const int UNUSED(len_dst),
@@ -1725,6 +1717,7 @@ bool rna_Object_constraints_override_apply(Main *UNUSED(bmain),
BKE_constraint_unique_name(con_dst, &ob_dst->constraints);
// printf("%s: We inserted a constraint...\n", __func__);
+ RNA_property_update_main(bmain, NULL, ptr_dst, prop_dst);
return true;
}
@@ -1795,7 +1788,7 @@ bool rna_Object_modifiers_override_apply(Main *bmain,
PointerRNA *ptr_dst,
PointerRNA *ptr_src,
PointerRNA *UNUSED(ptr_storage),
- PropertyRNA *UNUSED(prop_dst),
+ PropertyRNA *prop_dst,
PropertyRNA *UNUSED(prop_src),
PropertyRNA *UNUSED(prop_storage),
const int UNUSED(len_dst),
@@ -1856,6 +1849,7 @@ bool rna_Object_modifiers_override_apply(Main *bmain,
BLI_insertlinkafter(&ob_dst->modifiers, mod_anchor, mod_dst);
// printf("%s: We inserted a modifier '%s'...\n", __func__, mod_dst->name);
+ RNA_property_update_main(bmain, NULL, ptr_dst, prop_dst);
return true;
}
@@ -1892,7 +1886,7 @@ bool rna_Object_greasepencil_modifiers_override_apply(Main *bmain,
PointerRNA *ptr_dst,
PointerRNA *ptr_src,
PointerRNA *UNUSED(ptr_storage),
- PropertyRNA *UNUSED(prop_dst),
+ PropertyRNA *prop_dst,
PropertyRNA *UNUSED(prop_src),
PropertyRNA *UNUSED(prop_storage),
const int UNUSED(len_dst),
@@ -1941,6 +1935,7 @@ bool rna_Object_greasepencil_modifiers_override_apply(Main *bmain,
BLI_insertlinkafter(&ob_dst->greasepencil_modifiers, mod_anchor, mod_dst);
// printf("%s: We inserted a gpencil modifier '%s'...\n", __func__, mod_dst->name);
+ RNA_property_update_main(bmain, NULL, ptr_dst, prop_dst);
return true;
}
@@ -1976,7 +1971,7 @@ static void rna_Object_shaderfx_clear(Object *object, bContext *C)
static void rna_Object_boundbox_get(PointerRNA *ptr, float *values)
{
Object *ob = (Object *)ptr->owner_id;
- BoundBox *bb = BKE_object_boundbox_get(ob);
+ const BoundBox *bb = BKE_object_boundbox_get(ob);
if (bb) {
memcpy(values, bb->vec, sizeof(bb->vec));
}
@@ -2297,6 +2292,21 @@ static int rna_Object_mesh_symmetry_yz_editable(PointerRNA *ptr, const char **UN
return PROP_EDITABLE;
}
+void rna_Object_lightgroup_get(PointerRNA *ptr, char *value)
+{
+ BKE_lightgroup_membership_get(((Object *)ptr->owner_id)->lightgroup, value);
+}
+
+int rna_Object_lightgroup_length(PointerRNA *ptr)
+{
+ return BKE_lightgroup_membership_length(((Object *)ptr->owner_id)->lightgroup);
+}
+
+void rna_Object_lightgroup_set(PointerRNA *ptr, const char *value)
+{
+ BKE_lightgroup_membership_set(&((Object *)ptr->owner_id)->lightgroup, value);
+}
+
#else
static void rna_def_vertex_group(BlenderRNA *brna)
@@ -3780,6 +3790,15 @@ static void rna_def_object(BlenderRNA *brna)
RNA_def_property_editable_func(prop, "rna_Object_mesh_symmetry_yz_editable");
RNA_def_property_ui_text(prop, "Z", "Enable mesh symmetry in the Z axis");
+ /* Lightgroup Membership */
+ prop = RNA_def_property(srna, "lightgroup", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_funcs(prop,
+ "rna_Object_lightgroup_get",
+ "rna_Object_lightgroup_length",
+ "rna_Object_lightgroup_set");
+ RNA_def_property_flag(prop, PROP_EDITABLE);
+ RNA_def_property_ui_text(prop, "Lightgroup", "Lightgroup that the object belongs to");
+
RNA_define_lib_overridable(false);
/* anim */
diff --git a/source/blender/makesrna/intern/rna_object_api.c b/source/blender/makesrna/intern/rna_object_api.c
index ece1c5e5815..6967f78026a 100644
--- a/source/blender/makesrna/intern/rna_object_api.c
+++ b/source/blender/makesrna/intern/rna_object_api.c
@@ -594,7 +594,7 @@ static void rna_Object_ray_cast(Object *ob,
}
/* Test BoundBox first (efficiency) */
- BoundBox *bb = BKE_object_boundbox_get(ob);
+ const BoundBox *bb = BKE_object_boundbox_get(ob);
float distmin;
/* Needed for valid distance check from #isect_ray_aabb_v3_simple() call. */
diff --git a/source/blender/makesrna/intern/rna_object_force.c b/source/blender/makesrna/intern/rna_object_force.c
index 8579f188428..ce4b1a193a3 100644
--- a/source/blender/makesrna/intern/rna_object_force.c
+++ b/source/blender/makesrna/intern/rna_object_force.c
@@ -49,6 +49,8 @@ static const EnumPropertyItem effector_shape_items[] = {
# include "BLI_math_base.h"
+# include "RNA_access.h"
+
/* type specific return values only used from functions */
static const EnumPropertyItem curve_shape_items[] = {
{PFIELD_SHAPE_POINT, "POINT", 0, "Point", "Field originates from the object center"},
@@ -239,6 +241,33 @@ static void rna_Cache_toggle_disk_cache(Main *UNUSED(bmain), Scene *UNUSED(scene
}
}
+bool rna_Cache_use_disk_cache_override_apply(Main *UNUSED(bmain),
+ PointerRNA *ptr_dst,
+ PointerRNA *ptr_src,
+ PointerRNA *UNUSED(ptr_storage),
+ PropertyRNA *prop_dst,
+ PropertyRNA *prop_src,
+ PropertyRNA *UNUSED(prop_storage),
+ const int UNUSED(len_dst),
+ const int UNUSED(len_src),
+ const int UNUSED(len_storage),
+ PointerRNA *UNUSED(ptr_item_dst),
+ PointerRNA *UNUSED(ptr_item_src),
+ PointerRNA *UNUSED(ptr_item_storage),
+ IDOverrideLibraryPropertyOperation *opop)
+{
+ BLI_assert(RNA_property_type(prop_dst) == PROP_BOOLEAN);
+ BLI_assert(opop->operation == IDOVERRIDE_LIBRARY_OP_REPLACE);
+ UNUSED_VARS_NDEBUG(opop);
+
+ RNA_property_boolean_set(ptr_dst, prop_dst, RNA_property_boolean_get(ptr_src, prop_src));
+
+ /* DO NOT call `RNA_property_update_main(bmain, NULL, ptr_dst, prop_dst);`, that would trigger
+ * the whole 'update from mem point cache' process, ending up in the complete deletion of an
+ * existing diskcache if any. */
+ return true;
+}
+
static void rna_Cache_idname_change(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
Object *ob = NULL;
@@ -407,7 +436,7 @@ int rna_Cache_info_length(PointerRNA *ptr)
PTCacheID pid = BKE_ptcache_id_find(ob, scene, cache);
- if (cache->flag & PTCACHE_FLAG_INFO_DIRTY) {
+ if (pid.cache != NULL && pid.cache->flag & PTCACHE_FLAG_INFO_DIRTY) {
BKE_ptcache_update_info(&pid);
}
@@ -983,6 +1012,7 @@ static void rna_def_pointcache_common(StructRNA *srna)
RNA_def_property_ui_text(
prop, "Disk Cache", "Save cache files to disk (.blend file must be saved first)");
RNA_def_property_update(prop, NC_OBJECT, "rna_Cache_toggle_disk_cache");
+ RNA_def_property_override_funcs(prop, NULL, NULL, "rna_Cache_use_disk_cache_override_apply");
prop = RNA_def_property(srna, "is_outdated", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", PTCACHE_OUTDATED);
@@ -1016,6 +1046,7 @@ static void rna_def_pointcache_common(StructRNA *srna)
prop = RNA_def_property(srna, "info", PROP_STRING, PROP_NONE);
RNA_def_property_string_sdna(prop, NULL, "info");
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_override_flag(prop, PROPOVERRIDE_NO_COMPARISON);
/* Note that we do not actually need a getter here, `rna_Cache_info_length` will update the info
* string just as well. */
RNA_def_property_string_funcs(prop, NULL, "rna_Cache_info_length", NULL);
diff --git a/source/blender/makesrna/intern/rna_pose.c b/source/blender/makesrna/intern/rna_pose.c
index 8b59962d858..2390fdd72f0 100644
--- a/source/blender/makesrna/intern/rna_pose.c
+++ b/source/blender/makesrna/intern/rna_pose.c
@@ -644,11 +644,11 @@ static bConstraint *rna_PoseChannel_constraints_copy(ID *id,
return new_con;
}
-bool rna_PoseChannel_constraints_override_apply(Main *UNUSED(bmain),
+bool rna_PoseChannel_constraints_override_apply(Main *bmain,
PointerRNA *ptr_dst,
PointerRNA *ptr_src,
PointerRNA *UNUSED(ptr_storage),
- PropertyRNA *UNUSED(prop_dst),
+ PropertyRNA *prop_dst,
PropertyRNA *UNUSED(prop_src),
PropertyRNA *UNUSED(prop_storage),
const int UNUSED(len_dst),
@@ -694,6 +694,7 @@ bool rna_PoseChannel_constraints_override_apply(Main *UNUSED(bmain),
BKE_constraint_unique_name(con_dst, &pchan_dst->constraints);
// printf("%s: We inserted a constraint...\n", __func__);
+ RNA_property_update_main(bmain, NULL, ptr_dst, prop_dst);
return true;
}
diff --git a/source/blender/makesrna/intern/rna_rna.c b/source/blender/makesrna/intern/rna_rna.c
index 8f1847c00f4..373df6b7444 100644
--- a/source/blender/makesrna/intern/rna_rna.c
+++ b/source/blender/makesrna/intern/rna_rna.c
@@ -2297,7 +2297,7 @@ bool rna_property_override_store_default(Main *UNUSED(bmain),
return changed;
}
-bool rna_property_override_apply_default(Main *UNUSED(bmain),
+bool rna_property_override_apply_default(Main *bmain,
PointerRNA *ptr_dst,
PointerRNA *ptr_src,
PointerRNA *ptr_storage,
@@ -2319,6 +2319,8 @@ bool rna_property_override_apply_default(Main *UNUSED(bmain),
const int index = is_array ? opop->subitem_reference_index : 0;
const short override_op = opop->operation;
+ bool ret_success = true;
+
switch (RNA_property_type(prop_dst)) {
case PROP_BOOLEAN:
if (is_array && index == -1) {
@@ -2355,7 +2357,7 @@ bool rna_property_override_apply_default(Main *UNUSED(bmain),
return false;
}
}
- return true;
+ break;
case PROP_INT:
if (is_array && index == -1) {
int array_stack_a[RNA_STACK_ARRAY], array_stack_b[RNA_STACK_ARRAY];
@@ -2434,7 +2436,7 @@ bool rna_property_override_apply_default(Main *UNUSED(bmain),
return false;
}
}
- return true;
+ break;
case PROP_FLOAT:
if (is_array && index == -1) {
float array_stack_a[RNA_STACK_ARRAY], array_stack_b[RNA_STACK_ARRAY];
@@ -2527,7 +2529,7 @@ bool rna_property_override_apply_default(Main *UNUSED(bmain),
return false;
}
}
- return true;
+ break;
case PROP_ENUM: {
const int value = RNA_property_enum_get(ptr_src, prop_src);
@@ -2540,7 +2542,7 @@ bool rna_property_override_apply_default(Main *UNUSED(bmain),
BLI_assert_msg(0, "Unsupported RNA override operation on enum");
return false;
}
- return true;
+ break;
}
case PROP_POINTER: {
PointerRNA value = RNA_property_pointer_get(ptr_src, prop_src);
@@ -2553,7 +2555,7 @@ bool rna_property_override_apply_default(Main *UNUSED(bmain),
BLI_assert_msg(0, "Unsupported RNA override operation on pointer");
return false;
}
- return true;
+ break;
}
case PROP_STRING: {
char buff[256];
@@ -2571,7 +2573,7 @@ bool rna_property_override_apply_default(Main *UNUSED(bmain),
if (value != buff) {
MEM_freeN(value);
}
- return true;
+ break;
}
case PROP_COLLECTION: {
/* We only support IDProperty-based collection insertion here. */
@@ -2636,19 +2638,27 @@ bool rna_property_override_apply_default(Main *UNUSED(bmain),
IDProperty *item_idprop_dst = item_ptr_dst.data;
IDP_CopyPropertyContent(item_idprop_dst, item_idprop_src);
- return RNA_property_collection_move(ptr_dst, prop_dst, item_index_added, item_index_dst);
+ ret_success = RNA_property_collection_move(
+ ptr_dst, prop_dst, item_index_added, item_index_dst);
+ break;
}
default:
BLI_assert_msg(0, "Unsupported RNA override operation on collection");
return false;
}
+ break;
}
default:
BLI_assert(0);
return false;
}
- return false;
+ /* Default apply callback always call property update. */
+ if (ret_success) {
+ RNA_property_update_main(bmain, NULL, ptr_dst, prop_dst);
+ }
+
+ return ret_success;
}
# undef RNA_PROPERTY_GET_SINGLE
diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c
index 6be2c361ba9..0960d246257 100644
--- a/source/blender/makesrna/intern/rna_scene.c
+++ b/source/blender/makesrna/intern/rna_scene.c
@@ -1767,6 +1767,10 @@ void rna_ViewLayer_pass_update(Main *bmain, Scene *activescene, PointerRNA *ptr)
ViewLayerAOV *aov = (ViewLayerAOV *)ptr->data;
view_layer = BKE_view_layer_find_with_aov(scene, aov);
}
+ else if (ptr->type == &RNA_Lightgroup) {
+ ViewLayerLightgroup *lightgroup = (ViewLayerLightgroup *)ptr->data;
+ view_layer = BKE_view_layer_find_with_lightgroup(scene, lightgroup);
+ }
if (view_layer) {
RenderEngineType *engine_type = RE_engines_find(scene->r.engine);
@@ -1878,7 +1882,7 @@ static void rna_Scene_editmesh_select_mode_update(bContext *C, PointerRNA *UNUSE
static void rna_Scene_uv_select_mode_update(bContext *C, PointerRNA *UNUSED(ptr))
{
/* Makes sure that the UV selection states are consistent with the current UV select mode and
- * sticky mode.*/
+ * sticky mode. */
ED_uvedit_selectmode_clean_multi(C);
}
@@ -2447,6 +2451,49 @@ void rna_ViewLayer_active_aov_index_set(PointerRNA *ptr, int value)
view_layer->active_aov = aov;
}
+void rna_ViewLayer_active_lightgroup_index_range(
+ PointerRNA *ptr, int *min, int *max, int *UNUSED(softmin), int *UNUSED(softmax))
+{
+ ViewLayer *view_layer = (ViewLayer *)ptr->data;
+
+ *min = 0;
+ *max = max_ii(0, BLI_listbase_count(&view_layer->lightgroups) - 1);
+}
+
+int rna_ViewLayer_active_lightgroup_index_get(PointerRNA *ptr)
+{
+ ViewLayer *view_layer = (ViewLayer *)ptr->data;
+ return BLI_findindex(&view_layer->lightgroups, view_layer->active_lightgroup);
+}
+
+void rna_ViewLayer_active_lightgroup_index_set(PointerRNA *ptr, int value)
+{
+ ViewLayer *view_layer = (ViewLayer *)ptr->data;
+ ViewLayerLightgroup *lightgroup = BLI_findlink(&view_layer->lightgroups, value);
+ view_layer->active_lightgroup = lightgroup;
+}
+
+static void rna_ViewLayerLightgroup_name_get(PointerRNA *ptr, char *value)
+{
+ ViewLayerLightgroup *lightgroup = (ViewLayerLightgroup *)ptr->data;
+ BLI_strncpy(value, lightgroup->name, sizeof(lightgroup->name));
+}
+
+static int rna_ViewLayerLightgroup_name_length(PointerRNA *ptr)
+{
+ ViewLayerLightgroup *lightgroup = (ViewLayerLightgroup *)ptr->data;
+ return strlen(lightgroup->name);
+}
+
+static void rna_ViewLayerLightgroup_name_set(PointerRNA *ptr, const char *value)
+{
+ ViewLayerLightgroup *lightgroup = (ViewLayerLightgroup *)ptr->data;
+ Scene *scene = (Scene *)ptr->owner_id;
+ ViewLayer *view_layer = BKE_view_layer_find_with_lightgroup(scene, lightgroup);
+
+ BKE_view_layer_rename_lightgroup(view_layer, lightgroup, value);
+}
+
/* Fake value, used internally (not saved to DNA). */
# define V3D_ORIENT_DEFAULT -1
@@ -4156,6 +4203,43 @@ static void rna_def_view_layer_aov(BlenderRNA *brna)
RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_ViewLayer_pass_update");
}
+static void rna_def_view_layer_lightgroups(BlenderRNA *brna, PropertyRNA *cprop)
+{
+ StructRNA *srna;
+ /* PropertyRNA *prop; */
+
+ FunctionRNA *func;
+ PropertyRNA *parm;
+
+ RNA_def_property_srna(cprop, "Lightgroups");
+ srna = RNA_def_struct(brna, "Lightgroups", NULL);
+ RNA_def_struct_sdna(srna, "ViewLayer");
+ RNA_def_struct_ui_text(srna, "List of Lightgroups", "Collection of Lightgroups");
+
+ func = RNA_def_function(srna, "add", "BKE_view_layer_add_lightgroup");
+ parm = RNA_def_pointer(func, "lightgroup", "Lightgroup", "", "Newly created Lightgroup");
+ RNA_def_function_return(func, parm);
+}
+
+static void rna_def_view_layer_lightgroup(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+ srna = RNA_def_struct(brna, "Lightgroup", NULL);
+ RNA_def_struct_sdna(srna, "ViewLayerLightgroup");
+ RNA_def_struct_ui_text(srna, "Light Group", "");
+
+ prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
+ RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
+ RNA_def_property_string_funcs(prop,
+ "rna_ViewLayerLightgroup_name_get",
+ "rna_ViewLayerLightgroup_name_length",
+ "rna_ViewLayerLightgroup_name_set");
+ RNA_def_property_ui_text(prop, "Name", "Name of the Lightgroup");
+ RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_ViewLayer_pass_update");
+ RNA_def_struct_name_property(srna, prop);
+}
+
void rna_def_view_layer_common(BlenderRNA *brna, StructRNA *srna, const bool scene)
{
PropertyRNA *prop;
@@ -4226,6 +4310,25 @@ void rna_def_view_layer_common(BlenderRNA *brna, StructRNA *srna, const bool sce
RNA_def_property_ui_text(prop, "Active AOV Index", "Index of active aov");
RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
+ prop = RNA_def_property(srna, "lightgroups", PROP_COLLECTION, PROP_NONE);
+ RNA_def_property_collection_sdna(prop, NULL, "lightgroups", NULL);
+ RNA_def_property_struct_type(prop, "Lightgroup");
+ RNA_def_property_ui_text(prop, "Light Groups", "");
+ rna_def_view_layer_lightgroups(brna, prop);
+
+ prop = RNA_def_property(srna, "active_lightgroup", PROP_POINTER, PROP_NONE);
+ RNA_def_property_struct_type(prop, "Lightgroup");
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_ui_text(prop, "Light Groups", "Active Lightgroup");
+
+ prop = RNA_def_property(srna, "active_lightgroup_index", PROP_INT, PROP_UNSIGNED);
+ RNA_def_property_int_funcs(prop,
+ "rna_ViewLayer_active_lightgroup_index_get",
+ "rna_ViewLayer_active_lightgroup_index_set",
+ "rna_ViewLayer_active_lightgroup_index_range");
+ RNA_def_property_ui_text(prop, "Active Lightgroup Index", "Index of active lightgroup");
+ RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
+
prop = RNA_def_property(srna, "use_pass_cryptomatte_object", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "cryptomatte_flag", VIEW_LAYER_CRYPTOMATTE_OBJECT);
RNA_def_property_ui_text(
@@ -8088,6 +8191,7 @@ void RNA_def_scene(BlenderRNA *brna)
rna_def_scene_display(brna);
rna_def_scene_eevee(brna);
rna_def_view_layer_aov(brna);
+ rna_def_view_layer_lightgroup(brna);
rna_def_view_layer_eevee(brna);
rna_def_scene_gpencil(brna);
RNA_define_animate_sdna(true);
diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c
index 3839b3ba6a4..e21c10166ab 100644
--- a/source/blender/makesrna/intern/rna_space.c
+++ b/source/blender/makesrna/intern/rna_space.c
@@ -3593,6 +3593,21 @@ static void rna_def_space_outliner(BlenderRNA *brna)
{0, NULL, 0, NULL, NULL},
};
+ static const EnumPropertyItem lib_override_view_mode[] = {
+ {SO_LIB_OVERRIDE_VIEW_PROPERTIES,
+ "PROPERTIES",
+ ICON_NONE,
+ "Properties",
+ "Display all local override data-blocks with their overridden properties and buttons to "
+ "edit them"},
+ {SO_LIB_OVERRIDE_VIEW_HIERARCHIES,
+ "HIERARCHIES",
+ ICON_NONE,
+ "Hierarchies",
+ "Display library override relationships"},
+ {0, NULL, 0, NULL, NULL},
+ };
+
static const EnumPropertyItem filter_state_items[] = {
{SO_FILTER_OB_ALL, "ALL", 0, "All", "Show all objects in the view layer"},
{SO_FILTER_OB_VISIBLE, "VISIBLE", 0, "Visible", "Show visible objects"},
@@ -3612,6 +3627,13 @@ static void rna_def_space_outliner(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Display Mode", "Type of information to display");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_OUTLINER, NULL);
+ prop = RNA_def_property(srna, "lib_override_view_mode", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_items(prop, lib_override_view_mode);
+ RNA_def_property_ui_text(prop,
+ "Library Override View Mode",
+ "Choose different visualizations of library override data");
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_OUTLINER, NULL);
+
prop = RNA_def_property(srna, "filter_text", PROP_STRING, PROP_NONE);
RNA_def_property_string_sdna(prop, NULL, "search_string");
RNA_def_property_ui_text(prop, "Display Filter", "Live search filtering string");
diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c
index 164564241ed..fd2bb9cb7cc 100644
--- a/source/blender/makesrna/intern/rna_userdef.c
+++ b/source/blender/makesrna/intern/rna_userdef.c
@@ -2923,8 +2923,8 @@ static void rna_def_userdef_theme_space_node(BlenderRNA *brna)
prop = RNA_def_property(srna, "grid_levels", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "grid_levels");
- RNA_def_property_int_default(prop, 7);
- RNA_def_property_range(prop, 0, 9);
+ RNA_def_property_int_default(prop, 3);
+ RNA_def_property_range(prop, 0, 3);
RNA_def_property_ui_text(
prop, "Grid Levels", "Number of subdivisions for the dot grid displayed in the background");
RNA_def_property_update(prop, 0, "rna_userdef_theme_update");
diff --git a/source/blender/makesrna/intern/rna_world.c b/source/blender/makesrna/intern/rna_world.c
index 04008665342..d1049eef2c7 100644
--- a/source/blender/makesrna/intern/rna_world.c
+++ b/source/blender/makesrna/intern/rna_world.c
@@ -22,6 +22,7 @@
# include "MEM_guardedalloc.h"
# include "BKE_context.h"
+# include "BKE_layer.h"
# include "BKE_main.h"
# include "BKE_texture.h"
@@ -84,6 +85,21 @@ static void rna_World_use_nodes_update(bContext *C, PointerRNA *ptr)
rna_World_draw_update(bmain, scene, ptr);
}
+void rna_World_lightgroup_get(PointerRNA *ptr, char *value)
+{
+ BKE_lightgroup_membership_get(((World *)ptr->owner_id)->lightgroup, value);
+}
+
+int rna_World_lightgroup_length(PointerRNA *ptr)
+{
+ return BKE_lightgroup_membership_length(((World *)ptr->owner_id)->lightgroup);
+}
+
+void rna_World_lightgroup_set(PointerRNA *ptr, const char *value)
+{
+ BKE_lightgroup_membership_set(&((World *)ptr->owner_id)->lightgroup, value);
+}
+
#else
static void rna_def_lighting(BlenderRNA *brna)
@@ -234,6 +250,13 @@ void RNA_def_world(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Use Nodes", "Use shader nodes to render the world");
RNA_def_property_update(prop, 0, "rna_World_use_nodes_update");
+ /* Lightgroup Membership */
+ prop = RNA_def_property(srna, "lightgroup", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_funcs(
+ prop, "rna_World_lightgroup_get", "rna_World_lightgroup_length", "rna_World_lightgroup_set");
+ RNA_def_property_flag(prop, PROP_EDITABLE);
+ RNA_def_property_ui_text(prop, "Lightgroup", "Lightgroup that the world belongs to");
+
rna_def_lighting(brna);
rna_def_world_mist(brna);
}
diff --git a/source/blender/modifiers/MOD_nodes.h b/source/blender/modifiers/MOD_nodes.h
index 053fb6e3244..4a3ccd8ecd1 100644
--- a/source/blender/modifiers/MOD_nodes.h
+++ b/source/blender/modifiers/MOD_nodes.h
@@ -17,8 +17,6 @@ extern "C" {
*/
void MOD_nodes_update_interface(struct Object *object, struct NodesModifierData *nmd);
-void MOD_nodes_init(struct Main *bmain, struct NodesModifierData *nmd);
-
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/modifiers/intern/MOD_armature.c b/source/blender/modifiers/intern/MOD_armature.c
index 5d37ac79fa6..f6e8a26f0e1 100644
--- a/source/blender/modifiers/intern/MOD_armature.c
+++ b/source/blender/modifiers/intern/MOD_armature.c
@@ -132,7 +132,7 @@ static void deformVerts(ModifierData *md,
const ModifierEvalContext *ctx,
Mesh *mesh,
float (*vertexCos)[3],
- int numVerts)
+ int verts_num)
{
ArmatureModifierData *amd = (ArmatureModifierData *)md;
@@ -142,7 +142,7 @@ static void deformVerts(ModifierData *md,
ctx->object,
vertexCos,
NULL,
- numVerts,
+ verts_num,
amd->deformflag,
amd->vert_coords_prev,
amd->defgrp_name,
@@ -157,10 +157,10 @@ static void deformVertsEM(ModifierData *md,
struct BMEditMesh *em,
Mesh *mesh,
float (*vertexCos)[3],
- int numVerts)
+ int verts_num)
{
if (mesh != NULL) {
- deformVerts(md, ctx, mesh, vertexCos, numVerts);
+ deformVerts(md, ctx, mesh, vertexCos, verts_num);
return;
}
@@ -172,7 +172,7 @@ static void deformVertsEM(ModifierData *md,
ctx->object,
vertexCos,
NULL,
- numVerts,
+ verts_num,
amd->deformflag,
amd->vert_coords_prev,
amd->defgrp_name,
@@ -188,7 +188,7 @@ static void deformMatricesEM(ModifierData *md,
Mesh *UNUSED(mesh),
float (*vertexCos)[3],
float (*defMats)[3][3],
- int numVerts)
+ int verts_num)
{
ArmatureModifierData *amd = (ArmatureModifierData *)md;
@@ -196,7 +196,7 @@ static void deformMatricesEM(ModifierData *md,
ctx->object,
vertexCos,
defMats,
- numVerts,
+ verts_num,
amd->deformflag,
NULL,
amd->defgrp_name,
@@ -208,16 +208,17 @@ static void deformMatrices(ModifierData *md,
Mesh *mesh,
float (*vertexCos)[3],
float (*defMats)[3][3],
- int numVerts)
+ int verts_num)
{
ArmatureModifierData *amd = (ArmatureModifierData *)md;
- Mesh *mesh_src = MOD_deform_mesh_eval_get(ctx->object, NULL, mesh, NULL, numVerts, false, false);
+ Mesh *mesh_src = MOD_deform_mesh_eval_get(
+ ctx->object, NULL, mesh, NULL, verts_num, false, false);
BKE_armature_deform_coords_with_mesh(amd->object,
ctx->object,
vertexCos,
defMats,
- numVerts,
+ verts_num,
amd->deformflag,
NULL,
amd->defgrp_name,
diff --git a/source/blender/modifiers/intern/MOD_array.c b/source/blender/modifiers/intern/MOD_array.c
index b237f952287..758858c8b1d 100644
--- a/source/blender/modifiers/intern/MOD_array.c
+++ b/source/blender/modifiers/intern/MOD_array.c
@@ -139,17 +139,17 @@ static void svert_from_mvert(SortVertsElem *sv,
/**
* Take as inputs two sets of verts, to be processed for detection of doubles and mapping.
- * Each set of verts is defined by its start within mverts array and its num_verts;
+ * Each set of verts is defined by its start within mverts array and its verts_num;
* It builds a mapping for all vertices within source,
* to vertices within target, or -1 if no double found.
- * The int doubles_map[num_verts_source] array must have been allocated by caller.
+ * The `int doubles_map[verts_source_num]` array must have been allocated by caller.
*/
static void dm_mvert_map_doubles(int *doubles_map,
const MVert *mverts,
const int target_start,
- const int target_num_verts,
+ const int target_verts_num,
const int source_start,
- const int source_num_verts,
+ const int source_verts_num,
const float dist)
{
const float dist3 = ((float)M_SQRT3 + 0.00005f) * dist; /* Just above sqrt(3) */
@@ -158,12 +158,12 @@ static void dm_mvert_map_doubles(int *doubles_map,
SortVertsElem *sve_source, *sve_target, *sve_target_low_bound;
bool target_scan_completed;
- target_end = target_start + target_num_verts;
- source_end = source_start + source_num_verts;
+ target_end = target_start + target_verts_num;
+ source_end = source_start + source_verts_num;
/* build array of MVerts to be tested for merging */
- sorted_verts_target = MEM_malloc_arrayN(target_num_verts, sizeof(SortVertsElem), __func__);
- sorted_verts_source = MEM_malloc_arrayN(source_num_verts, sizeof(SortVertsElem), __func__);
+ sorted_verts_target = MEM_malloc_arrayN(target_verts_num, sizeof(SortVertsElem), __func__);
+ sorted_verts_source = MEM_malloc_arrayN(source_verts_num, sizeof(SortVertsElem), __func__);
/* Copy target vertices index and cos into SortVertsElem array */
svert_from_mvert(sorted_verts_target, mverts + target_start, target_start, target_end);
@@ -172,8 +172,8 @@ static void dm_mvert_map_doubles(int *doubles_map,
svert_from_mvert(sorted_verts_source, mverts + source_start, source_start, source_end);
/* sort arrays according to sum of vertex coordinates (sumco) */
- qsort(sorted_verts_target, target_num_verts, sizeof(SortVertsElem), svert_sum_cmp);
- qsort(sorted_verts_source, source_num_verts, sizeof(SortVertsElem), svert_sum_cmp);
+ qsort(sorted_verts_target, target_verts_num, sizeof(SortVertsElem), svert_sum_cmp);
+ qsort(sorted_verts_source, source_verts_num, sizeof(SortVertsElem), svert_sum_cmp);
sve_target_low_bound = sorted_verts_target;
i_target_low_bound = 0;
@@ -181,7 +181,7 @@ static void dm_mvert_map_doubles(int *doubles_map,
/* Scan source vertices, in #SortVertsElem sorted array,
* all the while maintaining the lower bound of possible doubles in target vertices. */
- for (i_source = 0, sve_source = sorted_verts_source; i_source < source_num_verts;
+ for (i_source = 0, sve_source = sorted_verts_source; i_source < source_verts_num;
i_source++, sve_source++) {
int best_target_vertex = -1;
float best_dist_sq = dist * dist;
@@ -202,13 +202,13 @@ static void dm_mvert_map_doubles(int *doubles_map,
/* Skip all target vertices that are more than dist3 lower in terms of sumco */
/* and advance the overall lower bound, applicable to all remaining vertices as well. */
- while ((i_target_low_bound < target_num_verts) &&
+ while ((i_target_low_bound < target_verts_num) &&
(sve_target_low_bound->sum_co < sve_source_sumco - dist3)) {
i_target_low_bound++;
sve_target_low_bound++;
}
/* If end of target list reached, then no more possible doubles */
- if (i_target_low_bound >= target_num_verts) {
+ if (i_target_low_bound >= target_verts_num) {
doubles_map[sve_source->vertex_num] = -1;
target_scan_completed = true;
continue;
@@ -221,7 +221,7 @@ static void dm_mvert_map_doubles(int *doubles_map,
/* i_target will scan vertices in the
* [v_source_sumco - dist3; v_source_sumco + dist3] range */
- while ((i_target < target_num_verts) && (sve_target->sum_co <= sve_source_sumco + dist3)) {
+ while ((i_target < target_verts_num) && (sve_target->sum_co <= sve_source_sumco + dist3)) {
/* Testing distance for candidate double in target */
/* v_target is within dist3 of v_source in terms of sumco; check real distance */
float dist_sq;
@@ -478,7 +478,7 @@ static Mesh *arrayModifier_doArray(ArrayModifierData *amd,
}
/* About 67 million vertices max seems a decent limit for now. */
- const size_t max_num_vertices = 1 << 26;
+ const size_t max_vertices_num = 1 << 26;
/* calculate the maximum number of copies which will fit within the
* prescribed length */
@@ -496,7 +496,7 @@ static Mesh *arrayModifier_doArray(ArrayModifierData *amd,
* vertices.
*/
if (((size_t)count * (size_t)chunk_nverts + (size_t)start_cap_nverts +
- (size_t)end_cap_nverts) > max_num_vertices) {
+ (size_t)end_cap_nverts) > max_vertices_num) {
count = 1;
offset_is_too_small = true;
}
@@ -518,7 +518,7 @@ static Mesh *arrayModifier_doArray(ArrayModifierData *amd,
* vertices.
*/
else if (((size_t)count * (size_t)chunk_nverts + (size_t)start_cap_nverts +
- (size_t)end_cap_nverts) > max_num_vertices) {
+ (size_t)end_cap_nverts) > max_vertices_num) {
count = 1;
BKE_modifier_set_error(ctx->object,
&amd->modifier,
diff --git a/source/blender/modifiers/intern/MOD_build.c b/source/blender/modifiers/intern/MOD_build.c
index cd77abfca50..61959d242d8 100644
--- a/source/blender/modifiers/intern/MOD_build.c
+++ b/source/blender/modifiers/intern/MOD_build.c
@@ -46,9 +46,7 @@ static void initData(ModifierData *md)
MEMCPY_STRUCT_AFTER(bmd, DNA_struct_default_get(BuildModifierData), modifier);
}
-static bool dependsOnTime(struct Scene *UNUSED(scene),
- ModifierData *UNUSED(md),
- const int UNUSED(dag_eval_mode))
+static bool dependsOnTime(struct Scene *UNUSED(scene), ModifierData *UNUSED(md))
{
return true;
}
@@ -58,7 +56,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, struct
Mesh *result;
BuildModifierData *bmd = (BuildModifierData *)md;
int i, j, k;
- int numFaces_dst, numEdges_dst, numLoops_dst = 0;
+ int faces_dst_num, edges_dst_num, loops_dst_num = 0;
int *vertMap, *edgeMap, *faceMap;
float frac;
MPoly *mpoly_dst;
@@ -71,21 +69,21 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, struct
/* maps edge indices in old mesh to indices in new mesh */
GHash *edgeHash2 = BLI_ghash_int_new("build ed apply gh");
- const int numVert_src = mesh->totvert;
- const int numEdge_src = mesh->totedge;
- const int numPoly_src = mesh->totpoly;
+ const int vert_src_num = mesh->totvert;
+ const int edge_src_num = mesh->totedge;
+ const int poly_src_num = mesh->totpoly;
MPoly *mpoly_src = mesh->mpoly;
MLoop *mloop_src = mesh->mloop;
MEdge *medge_src = mesh->medge;
MVert *mvert_src = mesh->mvert;
- vertMap = MEM_malloc_arrayN(numVert_src, sizeof(*vertMap), "build modifier vertMap");
- edgeMap = MEM_malloc_arrayN(numEdge_src, sizeof(*edgeMap), "build modifier edgeMap");
- faceMap = MEM_malloc_arrayN(numPoly_src, sizeof(*faceMap), "build modifier faceMap");
+ vertMap = MEM_malloc_arrayN(vert_src_num, sizeof(*vertMap), "build modifier vertMap");
+ edgeMap = MEM_malloc_arrayN(edge_src_num, sizeof(*edgeMap), "build modifier edgeMap");
+ faceMap = MEM_malloc_arrayN(poly_src_num, sizeof(*faceMap), "build modifier faceMap");
- range_vn_i(vertMap, numVert_src, 0);
- range_vn_i(edgeMap, numEdge_src, 0);
- range_vn_i(faceMap, numPoly_src, 0);
+ range_vn_i(vertMap, vert_src_num, 0);
+ range_vn_i(edgeMap, edge_src_num, 0);
+ range_vn_i(faceMap, poly_src_num, 0);
struct Scene *scene = DEG_get_input_scene(ctx->depsgraph);
frac = (BKE_scene_ctime_get(scene) - bmd->start) / bmd->length;
@@ -94,17 +92,17 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, struct
frac = 1.0f - frac;
}
- numFaces_dst = numPoly_src * frac;
- numEdges_dst = numEdge_src * frac;
+ faces_dst_num = poly_src_num * frac;
+ edges_dst_num = edge_src_num * frac;
/* if there's at least one face, build based on faces */
- if (numFaces_dst) {
+ if (faces_dst_num) {
MPoly *mpoly, *mp;
MLoop *ml, *mloop;
uintptr_t hash_num, hash_num_alt;
if (bmd->flag & MOD_BUILD_FLAG_RANDOMIZE) {
- BLI_array_randomize(faceMap, sizeof(*faceMap), numPoly_src, bmd->seed);
+ BLI_array_randomize(faceMap, sizeof(*faceMap), poly_src_num, bmd->seed);
}
/* get the set of all vert indices that will be in the final mesh,
@@ -113,7 +111,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, struct
mpoly = mpoly_src;
mloop = mloop_src;
hash_num = 0;
- for (i = 0; i < numFaces_dst; i++) {
+ for (i = 0; i < faces_dst_num; i++) {
mp = mpoly + faceMap[i];
ml = mloop + mp->loopstart;
@@ -125,7 +123,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, struct
}
}
- numLoops_dst += mp->totloop;
+ loops_dst_num += mp->totloop;
}
BLI_assert(hash_num == BLI_ghash_len(vertHash));
@@ -134,7 +132,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, struct
*/
hash_num = 0;
hash_num_alt = 0;
- for (i = 0; i < numEdge_src; i++, hash_num_alt++) {
+ for (i = 0; i < edge_src_num; i++, hash_num_alt++) {
MEdge *me = medge_src + i;
if (BLI_ghash_haskey(vertHash, POINTER_FROM_INT(me->v1)) &&
@@ -146,12 +144,12 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, struct
}
BLI_assert(hash_num == BLI_ghash_len(edgeHash));
}
- else if (numEdges_dst) {
+ else if (edges_dst_num) {
MEdge *medge, *me;
uintptr_t hash_num;
if (bmd->flag & MOD_BUILD_FLAG_RANDOMIZE) {
- BLI_array_randomize(edgeMap, sizeof(*edgeMap), numEdge_src, bmd->seed);
+ BLI_array_randomize(edgeMap, sizeof(*edgeMap), edge_src_num, bmd->seed);
}
/* get the set of all vert indices that will be in the final mesh,
@@ -160,7 +158,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, struct
medge = medge_src;
hash_num = 0;
BLI_assert(hash_num == BLI_ghash_len(vertHash));
- for (i = 0; i < numEdges_dst; i++) {
+ for (i = 0; i < edges_dst_num; i++) {
void **val_p;
me = medge + edgeMap[i];
@@ -176,7 +174,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, struct
BLI_assert(hash_num == BLI_ghash_len(vertHash));
/* get the set of edges that will be in the new mesh */
- for (i = 0; i < numEdges_dst; i++) {
+ for (i = 0; i < edges_dst_num; i++) {
j = BLI_ghash_len(edgeHash);
BLI_ghash_insert(edgeHash, POINTER_FROM_INT(j), POINTER_FROM_INT(edgeMap[i]));
@@ -184,23 +182,23 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, struct
}
}
else {
- int numVerts = numVert_src * frac;
+ int verts_num = vert_src_num * frac;
if (bmd->flag & MOD_BUILD_FLAG_RANDOMIZE) {
- BLI_array_randomize(vertMap, sizeof(*vertMap), numVert_src, bmd->seed);
+ BLI_array_randomize(vertMap, sizeof(*vertMap), vert_src_num, bmd->seed);
}
/* get the set of all vert indices that will be in the final mesh,
* mapped to the new indices
*/
- for (i = 0; i < numVerts; i++) {
+ for (i = 0; i < verts_num; i++) {
BLI_ghash_insert(vertHash, POINTER_FROM_INT(vertMap[i]), POINTER_FROM_INT(i));
}
}
/* now we know the number of verts, edges and faces, we can create the mesh. */
result = BKE_mesh_new_nomain_from_template(
- mesh, BLI_ghash_len(vertHash), BLI_ghash_len(edgeHash), 0, numLoops_dst, numFaces_dst);
+ mesh, BLI_ghash_len(vertHash), BLI_ghash_len(edgeHash), 0, loops_dst_num, faces_dst_num);
/* copy the vertices across */
GHASH_ITER (gh_iter, vertHash) {
@@ -237,7 +235,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, struct
/* copy the faces across, remapping indices */
k = 0;
- for (i = 0; i < numFaces_dst; i++) {
+ for (i = 0; i < faces_dst_num; i++) {
MPoly *source;
MPoly *dest;
diff --git a/source/blender/modifiers/intern/MOD_cast.c b/source/blender/modifiers/intern/MOD_cast.c
index fb395631451..3916551bc90 100644
--- a/source/blender/modifiers/intern/MOD_cast.c
+++ b/source/blender/modifiers/intern/MOD_cast.c
@@ -96,7 +96,7 @@ static void sphere_do(CastModifierData *cmd,
Object *ob,
Mesh *mesh,
float (*vertexCos)[3],
- int numVerts)
+ int verts_num)
{
MDeformVert *dvert = NULL;
const bool invert_vgroup = (cmd->flag & MOD_CAST_INVERT_VGROUP) != 0;
@@ -159,17 +159,17 @@ static void sphere_do(CastModifierData *cmd,
}
if (len <= 0) {
- for (i = 0; i < numVerts; i++) {
+ for (i = 0; i < verts_num; i++) {
len += len_v3v3(center, vertexCos[i]);
}
- len /= numVerts;
+ len /= verts_num;
if (len == 0.0f) {
len = 10.0f;
}
}
- for (i = 0; i < numVerts; i++) {
+ for (i = 0; i < verts_num; i++) {
float tmp_co[3];
copy_v3_v3(tmp_co, vertexCos[i]);
@@ -237,7 +237,7 @@ static void cuboid_do(CastModifierData *cmd,
Object *ob,
Mesh *mesh,
float (*vertexCos)[3],
- int numVerts)
+ int verts_num)
{
MDeformVert *dvert = NULL;
int defgrp_index;
@@ -312,13 +312,13 @@ static void cuboid_do(CastModifierData *cmd,
/* let the center of the ctrl_ob be part of the bound box: */
minmax_v3v3_v3(min, max, center);
- for (i = 0; i < numVerts; i++) {
+ for (i = 0; i < verts_num; i++) {
sub_v3_v3v3(vec, vertexCos[i], center);
minmax_v3v3_v3(min, max, vec);
}
}
else {
- for (i = 0; i < numVerts; i++) {
+ for (i = 0; i < verts_num; i++) {
minmax_v3v3_v3(min, max, vertexCos[i]);
}
}
@@ -347,7 +347,7 @@ static void cuboid_do(CastModifierData *cmd,
bb[4][2] = bb[5][2] = bb[6][2] = bb[7][2] = max[2];
/* ready to apply the effect, one vertex at a time */
- for (i = 0; i < numVerts; i++) {
+ for (i = 0; i < verts_num; i++) {
int octant, coord;
float d[3], dmax, apex[3], fbb;
float tmp_co[3];
@@ -460,21 +460,21 @@ static void deformVerts(ModifierData *md,
const ModifierEvalContext *ctx,
Mesh *mesh,
float (*vertexCos)[3],
- int numVerts)
+ int verts_num)
{
CastModifierData *cmd = (CastModifierData *)md;
Mesh *mesh_src = NULL;
if (ctx->object->type == OB_MESH && cmd->defgrp_name[0] != '\0') {
/* mesh_src is only needed for vgroups. */
- mesh_src = MOD_deform_mesh_eval_get(ctx->object, NULL, mesh, NULL, numVerts, false, false);
+ mesh_src = MOD_deform_mesh_eval_get(ctx->object, NULL, mesh, NULL, verts_num, false, false);
}
if (cmd->type == MOD_CAST_TYPE_CUBOID) {
- cuboid_do(cmd, ctx, ctx->object, mesh_src, vertexCos, numVerts);
+ cuboid_do(cmd, ctx, ctx->object, mesh_src, vertexCos, verts_num);
}
else { /* MOD_CAST_TYPE_SPHERE or MOD_CAST_TYPE_CYLINDER */
- sphere_do(cmd, ctx, ctx->object, mesh_src, vertexCos, numVerts);
+ sphere_do(cmd, ctx, ctx->object, mesh_src, vertexCos, verts_num);
}
if (!ELEM(mesh_src, NULL, mesh)) {
@@ -487,17 +487,18 @@ static void deformVertsEM(ModifierData *md,
struct BMEditMesh *editData,
Mesh *mesh,
float (*vertexCos)[3],
- int numVerts)
+ int verts_num)
{
CastModifierData *cmd = (CastModifierData *)md;
Mesh *mesh_src = NULL;
if (cmd->defgrp_name[0] != '\0') {
- mesh_src = MOD_deform_mesh_eval_get(ctx->object, editData, mesh, NULL, numVerts, false, false);
+ mesh_src = MOD_deform_mesh_eval_get(
+ ctx->object, editData, mesh, NULL, verts_num, false, false);
}
if (mesh && mesh->runtime.wrapper_type == ME_WRAPPER_TYPE_MDATA) {
- BLI_assert(mesh->totvert == numVerts);
+ BLI_assert(mesh->totvert == verts_num);
}
/* TODO(Campbell): use edit-mode data only (remove this line). */
@@ -506,10 +507,10 @@ static void deformVertsEM(ModifierData *md,
}
if (cmd->type == MOD_CAST_TYPE_CUBOID) {
- cuboid_do(cmd, ctx, ctx->object, mesh_src, vertexCos, numVerts);
+ cuboid_do(cmd, ctx, ctx->object, mesh_src, vertexCos, verts_num);
}
else { /* MOD_CAST_TYPE_SPHERE or MOD_CAST_TYPE_CYLINDER */
- sphere_do(cmd, ctx, ctx->object, mesh_src, vertexCos, numVerts);
+ sphere_do(cmd, ctx, ctx->object, mesh_src, vertexCos, verts_num);
}
if (!ELEM(mesh_src, NULL, mesh)) {
diff --git a/source/blender/modifiers/intern/MOD_cloth.c b/source/blender/modifiers/intern/MOD_cloth.c
index 4bc79a9dd45..185b05b4cf9 100644
--- a/source/blender/modifiers/intern/MOD_cloth.c
+++ b/source/blender/modifiers/intern/MOD_cloth.c
@@ -78,7 +78,7 @@ static void deformVerts(ModifierData *md,
const ModifierEvalContext *ctx,
Mesh *mesh,
float (*vertexCos)[3],
- int numVerts)
+ int verts_num)
{
Mesh *mesh_src;
ClothModifierData *clmd = (ClothModifierData *)md;
@@ -94,7 +94,7 @@ static void deformVerts(ModifierData *md,
}
if (mesh == NULL) {
- mesh_src = MOD_deform_mesh_eval_get(ctx->object, NULL, NULL, NULL, numVerts, false, false);
+ mesh_src = MOD_deform_mesh_eval_get(ctx->object, NULL, NULL, NULL, verts_num, false, false);
}
else {
/* Not possible to use get_mesh() in this case as we'll modify its vertices
@@ -118,7 +118,7 @@ static void deformVerts(ModifierData *md,
&mesh_src->vdata, CD_CLOTH_ORCO, CD_CALLOC, NULL, mesh_src->totvert);
}
- memcpy(layerorco, kb->data, sizeof(float[3]) * numVerts);
+ memcpy(layerorco, kb->data, sizeof(float[3]) * verts_num);
}
}
@@ -201,9 +201,7 @@ static void copyData(const ModifierData *md, ModifierData *target, const int fla
tclmd->solver_result = NULL;
}
-static bool dependsOnTime(struct Scene *UNUSED(scene),
- ModifierData *UNUSED(md),
- const int UNUSED(dag_eval_mode))
+static bool dependsOnTime(struct Scene *UNUSED(scene), ModifierData *UNUSED(md))
{
return true;
}
diff --git a/source/blender/modifiers/intern/MOD_collision.c b/source/blender/modifiers/intern/MOD_collision.c
index 33a5934d2b0..1cb308bb2a0 100644
--- a/source/blender/modifiers/intern/MOD_collision.c
+++ b/source/blender/modifiers/intern/MOD_collision.c
@@ -80,9 +80,7 @@ static void freeData(ModifierData *md)
}
}
-static bool dependsOnTime(struct Scene *UNUSED(scene),
- ModifierData *UNUSED(md),
- const int UNUSED(dag_eval_mode))
+static bool dependsOnTime(struct Scene *UNUSED(scene), ModifierData *UNUSED(md))
{
return true;
}
@@ -91,7 +89,7 @@ static void deformVerts(ModifierData *md,
const ModifierEvalContext *ctx,
Mesh *mesh,
float (*vertexCos)[3],
- int numVerts)
+ int verts_num)
{
CollisionModifierData *collmd = (CollisionModifierData *)md;
Mesh *mesh_src;
@@ -109,7 +107,7 @@ static void deformVerts(ModifierData *md,
}
if (mesh == NULL) {
- mesh_src = MOD_deform_mesh_eval_get(ob, NULL, NULL, NULL, numVerts, false, false);
+ mesh_src = MOD_deform_mesh_eval_get(ob, NULL, NULL, NULL, verts_num, false, false);
}
else {
/* Not possible to use get_mesh() in this case as we'll modify its vertices
@@ -268,9 +266,9 @@ static void blendRead(BlendDataReader *UNUSED(reader), ModifierData *md)
collmd->xnew = newdataadr(fd, collmd->xnew);
collmd->mfaces = newdataadr(fd, collmd->mfaces);
- collmd->current_x = MEM_calloc_arrayN(collmd->numverts, sizeof(MVert), "current_x");
- collmd->current_xnew = MEM_calloc_arrayN(collmd->numverts, sizeof(MVert), "current_xnew");
- collmd->current_v = MEM_calloc_arrayN(collmd->numverts, sizeof(MVert), "current_v");
+ collmd->current_x = MEM_calloc_arrayN(collmd->mvert_num, sizeof(MVert), "current_x");
+ collmd->current_xnew = MEM_calloc_arrayN(collmd->mvert_num, sizeof(MVert), "current_xnew");
+ collmd->current_v = MEM_calloc_arrayN(collmd->mvert_num, sizeof(MVert), "current_v");
#endif
collmd->x = NULL;
diff --git a/source/blender/modifiers/intern/MOD_correctivesmooth.c b/source/blender/modifiers/intern/MOD_correctivesmooth.c
index b61419eb663..52162eaacc5 100644
--- a/source/blender/modifiers/intern/MOD_correctivesmooth.c
+++ b/source/blender/modifiers/intern/MOD_correctivesmooth.c
@@ -111,13 +111,13 @@ static void requiredDataMask(Object *UNUSED(ob),
/* check individual weights for changes and cache values */
static void mesh_get_weights(MDeformVert *dvert,
const int defgrp_index,
- const uint numVerts,
+ const uint verts_num,
const bool use_invert_vgroup,
float *smooth_weights)
{
uint i;
- for (i = 0; i < numVerts; i++, dvert++) {
+ for (i = 0; i < verts_num; i++, dvert++) {
const float w = BKE_defvert_find_weight(dvert, defgrp_index);
if (use_invert_vgroup == false) {
@@ -170,25 +170,25 @@ static void mesh_get_boundaries(Mesh *mesh, float *smooth_weights)
static void smooth_iter__simple(CorrectiveSmoothModifierData *csmd,
Mesh *mesh,
float (*vertexCos)[3],
- uint numVerts,
+ uint verts_num,
const float *smooth_weights,
uint iterations)
{
const float lambda = csmd->lambda;
uint i;
- const uint numEdges = (uint)mesh->totedge;
+ const uint edges_num = (uint)mesh->totedge;
const MEdge *edges = mesh->medge;
float *vertex_edge_count_div;
struct SmoothingData_Simple {
float delta[3];
- } *smooth_data = MEM_calloc_arrayN(numVerts, sizeof(*smooth_data), __func__);
+ } *smooth_data = MEM_calloc_arrayN(verts_num, sizeof(*smooth_data), __func__);
- vertex_edge_count_div = MEM_calloc_arrayN(numVerts, sizeof(float), __func__);
+ vertex_edge_count_div = MEM_calloc_arrayN(verts_num, sizeof(float), __func__);
/* calculate as floats to avoid int->float conversion in #smooth_iter */
- for (i = 0; i < numEdges; i++) {
+ for (i = 0; i < edges_num; i++) {
vertex_edge_count_div[edges[i].v1] += 1.0f;
vertex_edge_count_div[edges[i].v2] += 1.0f;
}
@@ -196,14 +196,14 @@ static void smooth_iter__simple(CorrectiveSmoothModifierData *csmd,
/* a little confusing, but we can include 'lambda' and smoothing weight
* here to avoid multiplying for every iteration */
if (smooth_weights == NULL) {
- for (i = 0; i < numVerts; i++) {
+ for (i = 0; i < verts_num; i++) {
vertex_edge_count_div[i] = lambda * (vertex_edge_count_div[i] ?
(1.0f / vertex_edge_count_div[i]) :
1.0f);
}
}
else {
- for (i = 0; i < numVerts; i++) {
+ for (i = 0; i < verts_num; i++) {
vertex_edge_count_div[i] = smooth_weights[i] * lambda *
(vertex_edge_count_div[i] ? (1.0f / vertex_edge_count_div[i]) :
1.0f);
@@ -214,7 +214,7 @@ static void smooth_iter__simple(CorrectiveSmoothModifierData *csmd,
/* Main Smoothing Loop */
while (iterations--) {
- for (i = 0; i < numEdges; i++) {
+ for (i = 0; i < edges_num; i++) {
struct SmoothingData_Simple *sd_v1;
struct SmoothingData_Simple *sd_v2;
float edge_dir[3];
@@ -228,7 +228,7 @@ static void smooth_iter__simple(CorrectiveSmoothModifierData *csmd,
sub_v3_v3(sd_v2->delta, edge_dir);
}
- for (i = 0; i < numVerts; i++) {
+ for (i = 0; i < verts_num; i++) {
struct SmoothingData_Simple *sd = &smooth_data[i];
madd_v3_v3fl(vertexCos[i], sd->delta, vertex_edge_count_div[i]);
/* zero for the next iteration (saves memset on entire array) */
@@ -246,12 +246,12 @@ static void smooth_iter__simple(CorrectiveSmoothModifierData *csmd,
static void smooth_iter__length_weight(CorrectiveSmoothModifierData *csmd,
Mesh *mesh,
float (*vertexCos)[3],
- uint numVerts,
+ uint verts_num,
const float *smooth_weights,
uint iterations)
{
const float eps = FLT_EPSILON * 10.0f;
- const uint numEdges = (uint)mesh->totedge;
+ const uint edges_num = (uint)mesh->totedge;
/* NOTE: the way this smoothing method works, its approx half as strong as the simple-smooth,
* and 2.0 rarely spikes, double the value for consistent behavior. */
const float lambda = csmd->lambda * 2.0f;
@@ -262,11 +262,11 @@ static void smooth_iter__length_weight(CorrectiveSmoothModifierData *csmd,
struct SmoothingData_Weighted {
float delta[3];
float edge_length_sum;
- } *smooth_data = MEM_calloc_arrayN(numVerts, sizeof(*smooth_data), __func__);
+ } *smooth_data = MEM_calloc_arrayN(verts_num, sizeof(*smooth_data), __func__);
/* calculate as floats to avoid int->float conversion in #smooth_iter */
- vertex_edge_count = MEM_calloc_arrayN(numVerts, sizeof(float), __func__);
- for (i = 0; i < numEdges; i++) {
+ vertex_edge_count = MEM_calloc_arrayN(verts_num, sizeof(float), __func__);
+ for (i = 0; i < edges_num; i++) {
vertex_edge_count[edges[i].v1] += 1.0f;
vertex_edge_count[edges[i].v2] += 1.0f;
}
@@ -275,7 +275,7 @@ static void smooth_iter__length_weight(CorrectiveSmoothModifierData *csmd,
/* Main Smoothing Loop */
while (iterations--) {
- for (i = 0; i < numEdges; i++) {
+ for (i = 0; i < edges_num; i++) {
struct SmoothingData_Weighted *sd_v1;
struct SmoothingData_Weighted *sd_v2;
float edge_dir[3];
@@ -299,7 +299,7 @@ static void smooth_iter__length_weight(CorrectiveSmoothModifierData *csmd,
if (smooth_weights == NULL) {
/* fast-path */
- for (i = 0; i < numVerts; i++) {
+ for (i = 0; i < verts_num; i++) {
struct SmoothingData_Weighted *sd = &smooth_data[i];
/* Divide by sum of all neighbor distances (weighted) and amount of neighbors,
* (mean average). */
@@ -320,7 +320,7 @@ static void smooth_iter__length_weight(CorrectiveSmoothModifierData *csmd,
}
}
else {
- for (i = 0; i < numVerts; i++) {
+ for (i = 0; i < verts_num; i++) {
struct SmoothingData_Weighted *sd = &smooth_data[i];
const float div = sd->edge_length_sum * vertex_edge_count[i];
if (div > eps) {
@@ -340,18 +340,18 @@ static void smooth_iter__length_weight(CorrectiveSmoothModifierData *csmd,
static void smooth_iter(CorrectiveSmoothModifierData *csmd,
Mesh *mesh,
float (*vertexCos)[3],
- uint numVerts,
+ uint verts_num,
const float *smooth_weights,
uint iterations)
{
switch (csmd->smooth_type) {
case MOD_CORRECTIVESMOOTH_SMOOTH_LENGTH_WEIGHT:
- smooth_iter__length_weight(csmd, mesh, vertexCos, numVerts, smooth_weights, iterations);
+ smooth_iter__length_weight(csmd, mesh, vertexCos, verts_num, smooth_weights, iterations);
break;
/* case MOD_CORRECTIVESMOOTH_SMOOTH_SIMPLE: */
default:
- smooth_iter__simple(csmd, mesh, vertexCos, numVerts, smooth_weights, iterations);
+ smooth_iter__simple(csmd, mesh, vertexCos, verts_num, smooth_weights, iterations);
break;
}
}
@@ -361,23 +361,23 @@ static void smooth_verts(CorrectiveSmoothModifierData *csmd,
MDeformVert *dvert,
const int defgrp_index,
float (*vertexCos)[3],
- uint numVerts)
+ uint verts_num)
{
float *smooth_weights = NULL;
if (dvert || (csmd->flag & MOD_CORRECTIVESMOOTH_PIN_BOUNDARY)) {
- smooth_weights = MEM_malloc_arrayN(numVerts, sizeof(float), __func__);
+ smooth_weights = MEM_malloc_arrayN(verts_num, sizeof(float), __func__);
if (dvert) {
mesh_get_weights(dvert,
defgrp_index,
- numVerts,
+ verts_num,
(csmd->flag & MOD_CORRECTIVESMOOTH_INVERT_VGROUP) != 0,
smooth_weights);
}
else {
- copy_vn_fl(smooth_weights, (int)numVerts, 1.0f);
+ copy_vn_fl(smooth_weights, (int)verts_num, 1.0f);
}
if (csmd->flag & MOD_CORRECTIVESMOOTH_PIN_BOUNDARY) {
@@ -385,7 +385,7 @@ static void smooth_verts(CorrectiveSmoothModifierData *csmd,
}
}
- smooth_iter(csmd, mesh, vertexCos, numVerts, smooth_weights, (uint)csmd->repeat);
+ smooth_iter(csmd, mesh, vertexCos, verts_num, smooth_weights, (uint)csmd->repeat);
if (smooth_weights) {
MEM_freeN(smooth_weights);
@@ -522,29 +522,29 @@ static void calc_deltas(CorrectiveSmoothModifierData *csmd,
MDeformVert *dvert,
const int defgrp_index,
const float (*rest_coords)[3],
- uint numVerts)
+ uint verts_num)
{
float(*smooth_vertex_coords)[3] = MEM_dupallocN(rest_coords);
float(*tangent_spaces)[3][3];
uint i;
- tangent_spaces = MEM_calloc_arrayN(numVerts, sizeof(float[3][3]), __func__);
+ tangent_spaces = MEM_calloc_arrayN(verts_num, sizeof(float[3][3]), __func__);
- if (csmd->delta_cache.totverts != numVerts) {
+ if (csmd->delta_cache.totverts != verts_num) {
MEM_SAFE_FREE(csmd->delta_cache.deltas);
}
/* allocate deltas if they have not yet been allocated, otherwise we will just write over them */
if (!csmd->delta_cache.deltas) {
- csmd->delta_cache.totverts = numVerts;
- csmd->delta_cache.deltas = MEM_malloc_arrayN(numVerts, sizeof(float[3]), __func__);
+ csmd->delta_cache.totverts = verts_num;
+ csmd->delta_cache.deltas = MEM_malloc_arrayN(verts_num, sizeof(float[3]), __func__);
}
- smooth_verts(csmd, mesh, dvert, defgrp_index, smooth_vertex_coords, numVerts);
+ smooth_verts(csmd, mesh, dvert, defgrp_index, smooth_vertex_coords, verts_num);
calc_tangent_spaces(mesh, smooth_vertex_coords, tangent_spaces);
- for (i = 0; i < numVerts; i++) {
+ for (i = 0; i < verts_num; i++) {
float imat[3][3], delta[3];
#ifdef USE_TANGENT_CALC_INLINE
@@ -567,7 +567,7 @@ static void correctivesmooth_modifier_do(ModifierData *md,
Object *ob,
Mesh *mesh,
float (*vertexCos)[3],
- uint numVerts,
+ uint verts_num,
struct BMEditMesh *em)
{
CorrectiveSmoothModifierData *csmd = (CorrectiveSmoothModifierData *)md;
@@ -591,7 +591,7 @@ static void correctivesmooth_modifier_do(ModifierData *md,
if (DEG_is_active(depsgraph)) {
BLI_assert(csmd->bind_coords == NULL);
csmd->bind_coords = MEM_dupallocN(vertexCos);
- csmd->bind_coords_num = numVerts;
+ csmd->bind_coords_num = verts_num;
BLI_assert(csmd->bind_coords != NULL);
/* Copy bound data to the original modifier. */
CorrectiveSmoothModifierData *csmd_orig = (CorrectiveSmoothModifierData *)
@@ -605,7 +605,7 @@ static void correctivesmooth_modifier_do(ModifierData *md,
}
if (UNLIKELY(use_only_smooth)) {
- smooth_verts(csmd, mesh, dvert, defgrp_index, vertexCos, numVerts);
+ smooth_verts(csmd, mesh, dvert, defgrp_index, vertexCos, verts_num);
return;
}
@@ -616,9 +616,9 @@ static void correctivesmooth_modifier_do(ModifierData *md,
/* If the number of verts has changed, the bind is invalid, so we do nothing */
if (csmd->rest_source == MOD_CORRECTIVESMOOTH_RESTSOURCE_BIND) {
- if (csmd->bind_coords_num != numVerts) {
+ if (csmd->bind_coords_num != verts_num) {
BKE_modifier_set_error(
- ob, md, "Bind vertex count mismatch: %u to %u", csmd->bind_coords_num, numVerts);
+ ob, md, "Bind vertex count mismatch: %u to %u", csmd->bind_coords_num, verts_num);
goto error;
}
}
@@ -631,16 +631,16 @@ static void correctivesmooth_modifier_do(ModifierData *md,
else {
uint me_numVerts = (uint)((em) ? em->bm->totvert : ((Mesh *)ob->data)->totvert);
- if (me_numVerts != numVerts) {
+ if (me_numVerts != verts_num) {
BKE_modifier_set_error(
- ob, md, "Original vertex count mismatch: %u to %u", me_numVerts, numVerts);
+ ob, md, "Original vertex count mismatch: %u to %u", me_numVerts, verts_num);
goto error;
}
}
}
/* check to see if our deltas are still valid */
- if (!csmd->delta_cache.deltas || (csmd->delta_cache.totverts != numVerts) ||
+ if (!csmd->delta_cache.deltas || (csmd->delta_cache.totverts != verts_num) ||
force_delta_cache_update) {
const float(*rest_coords)[3];
bool is_rest_coords_alloc = false;
@@ -649,7 +649,7 @@ static void correctivesmooth_modifier_do(ModifierData *md,
if (csmd->rest_source == MOD_CORRECTIVESMOOTH_RESTSOURCE_BIND) {
/* caller needs to do sanity check here */
- csmd->bind_coords_num = numVerts;
+ csmd->bind_coords_num = verts_num;
rest_coords = csmd->bind_coords;
}
else {
@@ -657,7 +657,7 @@ static void correctivesmooth_modifier_do(ModifierData *md,
rest_coords = em ? BKE_editmesh_vert_coords_alloc_orco(em, &me_numVerts) :
BKE_mesh_vert_coords_alloc(ob->data, &me_numVerts);
- BLI_assert((uint)me_numVerts == numVerts);
+ BLI_assert((uint)me_numVerts == verts_num);
is_rest_coords_alloc = true;
}
@@ -665,7 +665,7 @@ static void correctivesmooth_modifier_do(ModifierData *md,
TIMEIT_START(corrective_smooth_deltas);
#endif
- calc_deltas(csmd, mesh, dvert, defgrp_index, rest_coords, numVerts);
+ calc_deltas(csmd, mesh, dvert, defgrp_index, rest_coords, verts_num);
#ifdef DEBUG_TIME
TIMEIT_END(corrective_smooth_deltas);
@@ -677,7 +677,7 @@ static void correctivesmooth_modifier_do(ModifierData *md,
if (csmd->rest_source == MOD_CORRECTIVESMOOTH_RESTSOURCE_BIND) {
/* this could be a check, but at this point it _must_ be valid */
- BLI_assert(csmd->bind_coords_num == numVerts && csmd->delta_cache.deltas);
+ BLI_assert(csmd->bind_coords_num == verts_num && csmd->delta_cache.deltas);
}
#ifdef DEBUG_TIME
@@ -685,7 +685,7 @@ static void correctivesmooth_modifier_do(ModifierData *md,
#endif
/* do the actual delta mush */
- smooth_verts(csmd, mesh, dvert, defgrp_index, vertexCos, numVerts);
+ smooth_verts(csmd, mesh, dvert, defgrp_index, vertexCos, verts_num);
{
uint i;
@@ -693,11 +693,11 @@ static void correctivesmooth_modifier_do(ModifierData *md,
float(*tangent_spaces)[3][3];
const float scale = csmd->scale;
/* calloc, since values are accumulated */
- tangent_spaces = MEM_calloc_arrayN(numVerts, sizeof(float[3][3]), __func__);
+ tangent_spaces = MEM_calloc_arrayN(verts_num, sizeof(float[3][3]), __func__);
calc_tangent_spaces(mesh, vertexCos, tangent_spaces);
- for (i = 0; i < numVerts; i++) {
+ for (i = 0; i < verts_num; i++) {
float delta[3];
#ifdef USE_TANGENT_CALC_INLINE
@@ -727,12 +727,13 @@ static void deformVerts(ModifierData *md,
const ModifierEvalContext *ctx,
Mesh *mesh,
float (*vertexCos)[3],
- int numVerts)
+ int verts_num)
{
- Mesh *mesh_src = MOD_deform_mesh_eval_get(ctx->object, NULL, mesh, NULL, numVerts, false, false);
+ Mesh *mesh_src = MOD_deform_mesh_eval_get(
+ ctx->object, NULL, mesh, NULL, verts_num, false, false);
correctivesmooth_modifier_do(
- md, ctx->depsgraph, ctx->object, mesh_src, vertexCos, (uint)numVerts, NULL);
+ md, ctx->depsgraph, ctx->object, mesh_src, vertexCos, (uint)verts_num, NULL);
if (!ELEM(mesh_src, NULL, mesh)) {
BKE_id_free(NULL, mesh_src);
@@ -744,10 +745,10 @@ static void deformVertsEM(ModifierData *md,
struct BMEditMesh *editData,
Mesh *mesh,
float (*vertexCos)[3],
- int numVerts)
+ int verts_num)
{
Mesh *mesh_src = MOD_deform_mesh_eval_get(
- ctx->object, editData, mesh, NULL, numVerts, false, false);
+ ctx->object, editData, mesh, NULL, verts_num, false, false);
/* TODO(Campbell): use edit-mode data only (remove this line). */
if (mesh_src != NULL) {
@@ -755,7 +756,7 @@ static void deformVertsEM(ModifierData *md,
}
correctivesmooth_modifier_do(
- md, ctx->depsgraph, ctx->object, mesh_src, vertexCos, (uint)numVerts, editData);
+ md, ctx->depsgraph, ctx->object, mesh_src, vertexCos, (uint)verts_num, editData);
if (!ELEM(mesh_src, NULL, mesh)) {
BKE_id_free(NULL, mesh_src);
diff --git a/source/blender/modifiers/intern/MOD_curve.c b/source/blender/modifiers/intern/MOD_curve.c
index 5b22b933823..a82b999f4dc 100644
--- a/source/blender/modifiers/intern/MOD_curve.c
+++ b/source/blender/modifiers/intern/MOD_curve.c
@@ -104,14 +104,14 @@ static void deformVerts(ModifierData *md,
const ModifierEvalContext *ctx,
Mesh *mesh,
float (*vertexCos)[3],
- int numVerts)
+ int verts_num)
{
CurveModifierData *cmd = (CurveModifierData *)md;
Mesh *mesh_src = NULL;
if (ctx->object->type == OB_MESH && cmd->name[0] != '\0') {
/* mesh_src is only needed for vgroups. */
- mesh_src = MOD_deform_mesh_eval_get(ctx->object, NULL, mesh, NULL, numVerts, false, false);
+ mesh_src = MOD_deform_mesh_eval_get(ctx->object, NULL, mesh, NULL, verts_num, false, false);
}
struct MDeformVert *dvert = NULL;
@@ -124,7 +124,7 @@ static void deformVerts(ModifierData *md,
BKE_curve_deform_coords(cmd->object,
ctx->object,
vertexCos,
- numVerts,
+ verts_num,
dvert,
defgrp_index,
cmd->flag,
@@ -140,10 +140,10 @@ static void deformVertsEM(ModifierData *md,
BMEditMesh *em,
Mesh *mesh,
float (*vertexCos)[3],
- int numVerts)
+ int verts_num)
{
if (mesh != NULL) {
- deformVerts(md, ctx, mesh, vertexCos, numVerts);
+ deformVerts(md, ctx, mesh, vertexCos, verts_num);
return;
}
@@ -162,7 +162,7 @@ static void deformVertsEM(ModifierData *md,
BKE_curve_deform_coords_with_editmesh(cmd->object,
ctx->object,
vertexCos,
- numVerts,
+ verts_num,
defgrp_index,
cmd->flag,
cmd->defaxis - 1,
@@ -172,7 +172,7 @@ static void deformVertsEM(ModifierData *md,
BKE_curve_deform_coords(cmd->object,
ctx->object,
vertexCos,
- numVerts,
+ verts_num,
NULL,
defgrp_index,
cmd->flag,
diff --git a/source/blender/modifiers/intern/MOD_displace.c b/source/blender/modifiers/intern/MOD_displace.c
index 2f35ffb3e18..7ad7d6eef3d 100644
--- a/source/blender/modifiers/intern/MOD_displace.c
+++ b/source/blender/modifiers/intern/MOD_displace.c
@@ -80,9 +80,7 @@ static void requiredDataMask(Object *UNUSED(ob),
}
}
-static bool dependsOnTime(struct Scene *UNUSED(scene),
- ModifierData *md,
- const int UNUSED(dag_eval_mode))
+static bool dependsOnTime(struct Scene *UNUSED(scene), ModifierData *md)
{
DisplaceModifierData *dmd = (DisplaceModifierData *)md;
@@ -269,7 +267,7 @@ static void displaceModifier_do(DisplaceModifierData *dmd,
const ModifierEvalContext *ctx,
Mesh *mesh,
float (*vertexCos)[3],
- const int numVerts)
+ const int verts_num)
{
Object *ob = ctx->object;
MVert *mvert;
@@ -299,7 +297,7 @@ static void displaceModifier_do(DisplaceModifierData *dmd,
Tex *tex_target = dmd->texture;
if (tex_target != NULL) {
- tex_co = MEM_calloc_arrayN((size_t)numVerts, sizeof(*tex_co), "displaceModifier_do tex_co");
+ tex_co = MEM_calloc_arrayN((size_t)verts_num, sizeof(*tex_co), "displaceModifier_do tex_co");
MOD_get_texture_coords((MappingInfoModifierData *)dmd, ctx, ob, mesh, vertexCos, tex_co);
MOD_init_texture((MappingInfoModifierData *)dmd, ctx);
@@ -319,9 +317,9 @@ static void displaceModifier_do(DisplaceModifierData *dmd,
}
clnors = CustomData_get_layer(ldata, CD_NORMAL);
- vert_clnors = MEM_malloc_arrayN(numVerts, sizeof(*vert_clnors), __func__);
+ vert_clnors = MEM_malloc_arrayN(verts_num, sizeof(*vert_clnors), __func__);
BKE_mesh_normals_loop_to_vertex(
- numVerts, mesh->mloop, mesh->totloop, (const float(*)[3])clnors, vert_clnors);
+ verts_num, mesh->mloop, mesh->totloop, (const float(*)[3])clnors, vert_clnors);
}
else {
direction = MOD_DISP_DIR_NOR;
@@ -355,8 +353,8 @@ static void displaceModifier_do(DisplaceModifierData *dmd,
}
TaskParallelSettings settings;
BLI_parallel_range_settings_defaults(&settings);
- settings.use_threading = (numVerts > 512);
- BLI_task_parallel_range(0, numVerts, &data, displaceModifier_do_task, &settings);
+ settings.use_threading = (verts_num > 512);
+ BLI_task_parallel_range(0, verts_num, &data, displaceModifier_do_task, &settings);
if (data.pool != NULL) {
BKE_image_pool_free(data.pool);
@@ -375,11 +373,12 @@ static void deformVerts(ModifierData *md,
const ModifierEvalContext *ctx,
Mesh *mesh,
float (*vertexCos)[3],
- int numVerts)
+ int verts_num)
{
- Mesh *mesh_src = MOD_deform_mesh_eval_get(ctx->object, NULL, mesh, NULL, numVerts, false, false);
+ Mesh *mesh_src = MOD_deform_mesh_eval_get(
+ ctx->object, NULL, mesh, NULL, verts_num, false, false);
- displaceModifier_do((DisplaceModifierData *)md, ctx, mesh_src, vertexCos, numVerts);
+ displaceModifier_do((DisplaceModifierData *)md, ctx, mesh_src, vertexCos, verts_num);
if (!ELEM(mesh_src, NULL, mesh)) {
BKE_id_free(NULL, mesh_src);
@@ -391,17 +390,17 @@ static void deformVertsEM(ModifierData *md,
struct BMEditMesh *editData,
Mesh *mesh,
float (*vertexCos)[3],
- int numVerts)
+ int verts_num)
{
Mesh *mesh_src = MOD_deform_mesh_eval_get(
- ctx->object, editData, mesh, NULL, numVerts, false, false);
+ ctx->object, editData, mesh, NULL, verts_num, false, false);
/* TODO(Campbell): use edit-mode data only (remove this line). */
if (mesh_src != NULL) {
BKE_mesh_wrapper_ensure_mdata(mesh_src);
}
- displaceModifier_do((DisplaceModifierData *)md, ctx, mesh_src, vertexCos, numVerts);
+ displaceModifier_do((DisplaceModifierData *)md, ctx, mesh_src, vertexCos, verts_num);
if (!ELEM(mesh_src, NULL, mesh)) {
BKE_id_free(NULL, mesh_src);
diff --git a/source/blender/modifiers/intern/MOD_dynamicpaint.c b/source/blender/modifiers/intern/MOD_dynamicpaint.c
index 64f603b99a9..f8cf80b673c 100644
--- a/source/blender/modifiers/intern/MOD_dynamicpaint.c
+++ b/source/blender/modifiers/intern/MOD_dynamicpaint.c
@@ -142,9 +142,7 @@ static void updateDepsgraph(ModifierData *md, const ModifierUpdateDepsgraphConte
}
}
-static bool dependsOnTime(struct Scene *UNUSED(scene),
- ModifierData *UNUSED(md),
- const int UNUSED(dag_eval_mode))
+static bool dependsOnTime(struct Scene *UNUSED(scene), ModifierData *UNUSED(md))
{
return true;
}
diff --git a/source/blender/modifiers/intern/MOD_explode.c b/source/blender/modifiers/intern/MOD_explode.c
index 33b090b9577..87ff648f13d 100644
--- a/source/blender/modifiers/intern/MOD_explode.c
+++ b/source/blender/modifiers/intern/MOD_explode.c
@@ -71,9 +71,7 @@ static void copyData(const ModifierData *md, ModifierData *target, const int fla
temd->facepa = NULL;
}
-static bool dependsOnTime(struct Scene *UNUSED(scene),
- ModifierData *UNUSED(md),
- const int UNUSED(dag_eval_mode))
+static bool dependsOnTime(struct Scene *UNUSED(scene), ModifierData *UNUSED(md))
{
return true;
}
@@ -279,12 +277,12 @@ static void remap_faces_3_6_9_12(Mesh *mesh,
}
static void remap_uvs_3_6_9_12(
- Mesh *mesh, Mesh *split, int numlayer, int i, int cur, int c0, int c1, int c2, int c3)
+ Mesh *mesh, Mesh *split, int layers_num, int i, int cur, int c0, int c1, int c2, int c3)
{
MTFace *mf, *df1, *df2, *df3;
int l;
- for (l = 0; l < numlayer; l++) {
+ for (l = 0; l < layers_num; l++) {
mf = CustomData_get_layer_n(&split->fdata, CD_MTFACE, l);
df1 = mf + cur;
df2 = df1 + 1;
@@ -339,12 +337,12 @@ static void remap_faces_5_10(Mesh *mesh,
}
static void remap_uvs_5_10(
- Mesh *mesh, Mesh *split, int numlayer, int i, int cur, int c0, int c1, int c2, int c3)
+ Mesh *mesh, Mesh *split, int layers_num, int i, int cur, int c0, int c1, int c2, int c3)
{
MTFace *mf, *df1, *df2;
int l;
- for (l = 0; l < numlayer; l++) {
+ for (l = 0; l < layers_num; l++) {
mf = CustomData_get_layer_n(&split->fdata, CD_MTFACE, l);
df1 = mf + cur;
df2 = df1 + 1;
@@ -411,12 +409,12 @@ static void remap_faces_15(Mesh *mesh,
}
static void remap_uvs_15(
- Mesh *mesh, Mesh *split, int numlayer, int i, int cur, int c0, int c1, int c2, int c3)
+ Mesh *mesh, Mesh *split, int layers_num, int i, int cur, int c0, int c1, int c2, int c3)
{
MTFace *mf, *df1, *df2, *df3, *df4;
int l;
- for (l = 0; l < numlayer; l++) {
+ for (l = 0; l < layers_num; l++) {
mf = CustomData_get_layer_n(&split->fdata, CD_MTFACE, l);
df1 = mf + cur;
df2 = df1 + 1;
@@ -487,12 +485,12 @@ static void remap_faces_7_11_13_14(Mesh *mesh,
}
static void remap_uvs_7_11_13_14(
- Mesh *mesh, Mesh *split, int numlayer, int i, int cur, int c0, int c1, int c2, int c3)
+ Mesh *mesh, Mesh *split, int layers_num, int i, int cur, int c0, int c1, int c2, int c3)
{
MTFace *mf, *df1, *df2, *df3;
int l;
- for (l = 0; l < numlayer; l++) {
+ for (l = 0; l < layers_num; l++) {
mf = CustomData_get_layer_n(&split->fdata, CD_MTFACE, l);
df1 = mf + cur;
df2 = df1 + 1;
@@ -547,12 +545,12 @@ static void remap_faces_19_21_22(Mesh *mesh,
}
static void remap_uvs_19_21_22(
- Mesh *mesh, Mesh *split, int numlayer, int i, int cur, int c0, int c1, int c2)
+ Mesh *mesh, Mesh *split, int layers_num, int i, int cur, int c0, int c1, int c2)
{
MTFace *mf, *df1, *df2;
int l;
- for (l = 0; l < numlayer; l++) {
+ for (l = 0; l < layers_num; l++) {
mf = CustomData_get_layer_n(&split->fdata, CD_MTFACE, l);
df1 = mf + cur;
df2 = df1 + 1;
@@ -609,12 +607,12 @@ static void remap_faces_23(Mesh *mesh,
}
static void remap_uvs_23(
- Mesh *mesh, Mesh *split, int numlayer, int i, int cur, int c0, int c1, int c2)
+ Mesh *mesh, Mesh *split, int layers_num, int i, int cur, int c0, int c1, int c2)
{
MTFace *mf, *df1, *df2;
int l;
- for (l = 0; l < numlayer; l++) {
+ for (l = 0; l < layers_num; l++) {
mf = CustomData_get_layer_n(&split->fdata, CD_MTFACE, l);
df1 = mf + cur;
df2 = df1 + 1;
@@ -653,7 +651,7 @@ static Mesh *cutEdges(ExplodeModifierData *emd, Mesh *mesh)
int *fs, totesplit = 0, totfsplit = 0, curdupface = 0;
int i, v1, v2, v3, v4, esplit, v[4] = {0, 0, 0, 0}, /* To quite gcc barking... */
uv[4] = {0, 0, 0, 0}; /* To quite gcc barking... */
- int numlayer;
+ int layers_num;
uint ed_v1, ed_v2;
edgehash = BLI_edgehash_new(__func__);
@@ -728,7 +726,7 @@ static Mesh *cutEdges(ExplodeModifierData *emd, Mesh *mesh)
split_m = BKE_mesh_new_nomain_from_template(mesh, totesplit, 0, totface + totfsplit, 0, 0);
- numlayer = CustomData_number_of_layers(&split_m->fdata, CD_MTFACE);
+ layers_num = CustomData_number_of_layers(&split_m->fdata, CD_MTFACE);
/* copy new faces & verts (is it really this painful with custom data??) */
for (i = 0; i < totvert; i++) {
@@ -814,23 +812,23 @@ static Mesh *cutEdges(ExplodeModifierData *emd, Mesh *mesh)
case 12:
remap_faces_3_6_9_12(
mesh, split_m, mf, facepa, vertpa, i, edgehash, curdupface, v[0], v[1], v[2], v[3]);
- if (numlayer) {
- remap_uvs_3_6_9_12(mesh, split_m, numlayer, i, curdupface, uv[0], uv[1], uv[2], uv[3]);
+ if (layers_num) {
+ remap_uvs_3_6_9_12(mesh, split_m, layers_num, i, curdupface, uv[0], uv[1], uv[2], uv[3]);
}
break;
case 5:
case 10:
remap_faces_5_10(
mesh, split_m, mf, facepa, vertpa, i, edgehash, curdupface, v[0], v[1], v[2], v[3]);
- if (numlayer) {
- remap_uvs_5_10(mesh, split_m, numlayer, i, curdupface, uv[0], uv[1], uv[2], uv[3]);
+ if (layers_num) {
+ remap_uvs_5_10(mesh, split_m, layers_num, i, curdupface, uv[0], uv[1], uv[2], uv[3]);
}
break;
case 15:
remap_faces_15(
mesh, split_m, mf, facepa, vertpa, i, edgehash, curdupface, v[0], v[1], v[2], v[3]);
- if (numlayer) {
- remap_uvs_15(mesh, split_m, numlayer, i, curdupface, uv[0], uv[1], uv[2], uv[3]);
+ if (layers_num) {
+ remap_uvs_15(mesh, split_m, layers_num, i, curdupface, uv[0], uv[1], uv[2], uv[3]);
}
break;
case 7:
@@ -839,8 +837,9 @@ static Mesh *cutEdges(ExplodeModifierData *emd, Mesh *mesh)
case 14:
remap_faces_7_11_13_14(
mesh, split_m, mf, facepa, vertpa, i, edgehash, curdupface, v[0], v[1], v[2], v[3]);
- if (numlayer) {
- remap_uvs_7_11_13_14(mesh, split_m, numlayer, i, curdupface, uv[0], uv[1], uv[2], uv[3]);
+ if (layers_num) {
+ remap_uvs_7_11_13_14(
+ mesh, split_m, layers_num, i, curdupface, uv[0], uv[1], uv[2], uv[3]);
}
break;
case 19:
@@ -848,15 +847,15 @@ static Mesh *cutEdges(ExplodeModifierData *emd, Mesh *mesh)
case 22:
remap_faces_19_21_22(
mesh, split_m, mf, facepa, vertpa, i, edgehash, curdupface, v[0], v[1], v[2]);
- if (numlayer) {
- remap_uvs_19_21_22(mesh, split_m, numlayer, i, curdupface, uv[0], uv[1], uv[2]);
+ if (layers_num) {
+ remap_uvs_19_21_22(mesh, split_m, layers_num, i, curdupface, uv[0], uv[1], uv[2]);
}
break;
case 23:
remap_faces_23(
mesh, split_m, mf, facepa, vertpa, i, edgehash, curdupface, v[0], v[1], v[2]);
- if (numlayer) {
- remap_uvs_23(mesh, split_m, numlayer, i, curdupface, uv[0], uv[1], uv[2]);
+ if (layers_num) {
+ remap_uvs_23(mesh, split_m, layers_num, i, curdupface, uv[0], uv[1], uv[2]);
}
break;
case 0:
diff --git a/source/blender/modifiers/intern/MOD_fluid.c b/source/blender/modifiers/intern/MOD_fluid.c
index a4c34df7ccf..562f0df510d 100644
--- a/source/blender/modifiers/intern/MOD_fluid.c
+++ b/source/blender/modifiers/intern/MOD_fluid.c
@@ -151,9 +151,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *
#endif /* WITH_FLUID */
}
-static bool dependsOnTime(struct Scene *UNUSED(scene),
- ModifierData *UNUSED(md),
- const int UNUSED(dag_eval_mode))
+static bool dependsOnTime(struct Scene *UNUSED(scene), ModifierData *UNUSED(md))
{
return true;
}
diff --git a/source/blender/modifiers/intern/MOD_hook.c b/source/blender/modifiers/intern/MOD_hook.c
index 513000e3ad6..1000bbf45d6 100644
--- a/source/blender/modifiers/intern/MOD_hook.c
+++ b/source/blender/modifiers/intern/MOD_hook.c
@@ -152,14 +152,14 @@ struct HookData_cb {
bool invert_vgroup;
};
-static BLI_bitmap *hook_index_array_to_bitmap(HookModifierData *hmd, const int numVerts)
+static BLI_bitmap *hook_index_array_to_bitmap(HookModifierData *hmd, const int verts_num)
{
- BLI_bitmap *indexar_used = BLI_BITMAP_NEW(numVerts, __func__);
+ BLI_bitmap *indexar_used = BLI_BITMAP_NEW(verts_num, __func__);
int i;
int *index_pt;
- for (i = 0, index_pt = hmd->indexar; i < hmd->totindex; i++, index_pt++) {
+ for (i = 0, index_pt = hmd->indexar; i < hmd->indexar_num; i++, index_pt++) {
const int j = *index_pt;
- if (j < numVerts) {
+ if (j < verts_num) {
BLI_BITMAP_ENABLE(indexar_used, i);
}
}
@@ -275,7 +275,7 @@ static void deformVerts_do(HookModifierData *hmd,
Mesh *mesh,
BMEditMesh *em,
float (*vertexCos)[3],
- int numVerts)
+ int verts_num)
{
Object *ob_target = hmd->object;
bPoseChannel *pchan = BKE_pose_channel_find_name(ob_target->pose, hmd->subtarget);
@@ -365,15 +365,15 @@ static void deformVerts_do(HookModifierData *hmd,
const int *origindex_ar;
/* if mesh is present and has original index data, use it */
if (mesh && (origindex_ar = CustomData_get_layer(&mesh->vdata, CD_ORIGINDEX))) {
- int numVerts_orig = numVerts;
+ int verts_orig_num = verts_num;
if (ob->type == OB_MESH) {
const Mesh *me_orig = ob->data;
- numVerts_orig = me_orig->totvert;
+ verts_orig_num = me_orig->totvert;
}
- BLI_bitmap *indexar_used = hook_index_array_to_bitmap(hmd, numVerts_orig);
- for (i = 0; i < numVerts; i++) {
+ BLI_bitmap *indexar_used = hook_index_array_to_bitmap(hmd, verts_orig_num);
+ for (i = 0; i < verts_num; i++) {
int i_orig = origindex_ar[i];
- BLI_assert(i_orig < numVerts_orig);
+ BLI_assert(i_orig < verts_orig_num);
if (BLI_BITMAP_TEST(indexar_used, i_orig)) {
hook_co_apply(&hd, i, dvert ? &dvert[i] : NULL);
}
@@ -382,8 +382,8 @@ static void deformVerts_do(HookModifierData *hmd,
}
else { /* missing mesh or ORIGINDEX */
if ((em != NULL) && (hd.defgrp_index != -1)) {
- BLI_assert(em->bm->totvert == numVerts);
- BLI_bitmap *indexar_used = hook_index_array_to_bitmap(hmd, numVerts);
+ BLI_assert(em->bm->totvert == verts_num);
+ BLI_bitmap *indexar_used = hook_index_array_to_bitmap(hmd, verts_num);
BMIter iter;
BMVert *v;
BM_ITER_MESH_INDEX (v, &iter, em->bm, BM_VERTS_OF_MESH, i) {
@@ -395,9 +395,9 @@ static void deformVerts_do(HookModifierData *hmd,
MEM_freeN(indexar_used);
}
else {
- for (i = 0, index_pt = hmd->indexar; i < hmd->totindex; i++, index_pt++) {
+ for (i = 0, index_pt = hmd->indexar; i < hmd->indexar_num; i++, index_pt++) {
const int j = *index_pt;
- if (j < numVerts) {
+ if (j < verts_num) {
hook_co_apply(&hd, j, dvert ? &dvert[j] : NULL);
}
}
@@ -406,7 +406,7 @@ static void deformVerts_do(HookModifierData *hmd,
}
else if (hd.defgrp_index != -1) { /* vertex group hook */
if (em != NULL) {
- BLI_assert(em->bm->totvert == numVerts);
+ BLI_assert(em->bm->totvert == verts_num);
BMIter iter;
BMVert *v;
BM_ITER_MESH_INDEX (v, &iter, em->bm, BM_VERTS_OF_MESH, i) {
@@ -416,7 +416,7 @@ static void deformVerts_do(HookModifierData *hmd,
}
else {
BLI_assert(dvert != NULL);
- for (i = 0; i < numVerts; i++) {
+ for (i = 0; i < verts_num; i++) {
hook_co_apply(&hd, i, &dvert[i]);
}
}
@@ -427,12 +427,13 @@ static void deformVerts(struct ModifierData *md,
const struct ModifierEvalContext *ctx,
struct Mesh *mesh,
float (*vertexCos)[3],
- int numVerts)
+ int verts_num)
{
HookModifierData *hmd = (HookModifierData *)md;
- Mesh *mesh_src = MOD_deform_mesh_eval_get(ctx->object, NULL, mesh, NULL, numVerts, false, false);
+ Mesh *mesh_src = MOD_deform_mesh_eval_get(
+ ctx->object, NULL, mesh, NULL, verts_num, false, false);
- deformVerts_do(hmd, ctx, ctx->object, mesh_src, NULL, vertexCos, numVerts);
+ deformVerts_do(hmd, ctx, ctx->object, mesh_src, NULL, vertexCos, verts_num);
if (!ELEM(mesh_src, NULL, mesh)) {
BKE_id_free(NULL, mesh_src);
@@ -444,11 +445,11 @@ static void deformVertsEM(struct ModifierData *md,
struct BMEditMesh *editData,
struct Mesh *mesh,
float (*vertexCos)[3],
- int numVerts)
+ int verts_num)
{
HookModifierData *hmd = (HookModifierData *)md;
- deformVerts_do(hmd, ctx, ctx->object, mesh, mesh ? NULL : editData, vertexCos, numVerts);
+ deformVerts_do(hmd, ctx, ctx->object, mesh, mesh ? NULL : editData, vertexCos, verts_num);
}
static void panel_draw(const bContext *UNUSED(C), Panel *panel)
@@ -526,7 +527,7 @@ static void blendWrite(BlendWriter *writer, const ModifierData *md)
BKE_curvemapping_blend_write(writer, hmd->curfalloff);
}
- BLO_write_int32_array(writer, hmd->totindex, hmd->indexar);
+ BLO_write_int32_array(writer, hmd->indexar_num, hmd->indexar);
}
static void blendRead(BlendDataReader *reader, ModifierData *md)
@@ -538,7 +539,7 @@ static void blendRead(BlendDataReader *reader, ModifierData *md)
BKE_curvemapping_blend_read(reader, hmd->curfalloff);
}
- BLO_read_int32_array(reader, hmd->totindex, &hmd->indexar);
+ BLO_read_int32_array(reader, hmd->indexar_num, &hmd->indexar);
}
ModifierTypeInfo modifierType_Hook = {
diff --git a/source/blender/modifiers/intern/MOD_laplaciandeform.c b/source/blender/modifiers/intern/MOD_laplaciandeform.c
index d5f3902379d..239cb7f5a5a 100644
--- a/source/blender/modifiers/intern/MOD_laplaciandeform.c
+++ b/source/blender/modifiers/intern/MOD_laplaciandeform.c
@@ -58,10 +58,10 @@ enum {
typedef struct LaplacianSystem {
bool is_matrix_computed;
bool has_solution;
- int total_verts;
- int total_edges;
- int total_tris;
- int total_anchors;
+ int verts_num;
+ int edges_num;
+ int tris_num;
+ int anchors_num;
int repeat;
char anchor_grp_name[64]; /* Vertex Group name */
float (*co)[3]; /* Original vertex coordinates */
@@ -84,20 +84,20 @@ static LaplacianSystem *newLaplacianSystem(void)
sys->is_matrix_computed = false;
sys->has_solution = false;
- sys->total_verts = 0;
- sys->total_edges = 0;
- sys->total_anchors = 0;
- sys->total_tris = 0;
+ sys->verts_num = 0;
+ sys->edges_num = 0;
+ sys->anchors_num = 0;
+ sys->tris_num = 0;
sys->repeat = 1;
sys->anchor_grp_name[0] = '\0';
return sys;
}
-static LaplacianSystem *initLaplacianSystem(int totalVerts,
- int totalEdges,
- int totalTris,
- int totalAnchors,
+static LaplacianSystem *initLaplacianSystem(int verts_num,
+ int edges_num,
+ int tris_num,
+ int anchors_num,
const char defgrpName[64],
int iterations)
{
@@ -105,18 +105,18 @@ static LaplacianSystem *initLaplacianSystem(int totalVerts,
sys->is_matrix_computed = false;
sys->has_solution = false;
- sys->total_verts = totalVerts;
- sys->total_edges = totalEdges;
- sys->total_tris = totalTris;
- sys->total_anchors = totalAnchors;
+ sys->verts_num = verts_num;
+ sys->edges_num = edges_num;
+ sys->tris_num = tris_num;
+ sys->anchors_num = anchors_num;
sys->repeat = iterations;
BLI_strncpy(sys->anchor_grp_name, defgrpName, sizeof(sys->anchor_grp_name));
- sys->co = MEM_malloc_arrayN(totalVerts, sizeof(float[3]), "DeformCoordinates");
- sys->no = MEM_calloc_arrayN(totalVerts, sizeof(float[3]), "DeformNormals");
- sys->delta = MEM_calloc_arrayN(totalVerts, sizeof(float[3]), "DeformDeltas");
- sys->tris = MEM_malloc_arrayN(totalTris, sizeof(int[3]), "DeformFaces");
- sys->index_anchors = MEM_malloc_arrayN((totalAnchors), sizeof(int), "DeformAnchors");
- sys->unit_verts = MEM_calloc_arrayN(totalVerts, sizeof(int), "DeformUnitVerts");
+ sys->co = MEM_malloc_arrayN(verts_num, sizeof(float[3]), "DeformCoordinates");
+ sys->no = MEM_calloc_arrayN(verts_num, sizeof(float[3]), "DeformNormals");
+ sys->delta = MEM_calloc_arrayN(verts_num, sizeof(float[3]), "DeformDeltas");
+ sys->tris = MEM_malloc_arrayN(tris_num, sizeof(int[3]), "DeformFaces");
+ sys->index_anchors = MEM_malloc_arrayN((anchors_num), sizeof(int), "DeformAnchors");
+ sys->unit_verts = MEM_calloc_arrayN(verts_num, sizeof(int), "DeformUnitVerts");
return sys;
}
@@ -146,7 +146,7 @@ static void createFaceRingMap(const int mvert_tot,
MeshElemMap **r_map,
int **r_indices)
{
- int i, j, totalr = 0;
+ int i, j, indices_num = 0;
int *indices, *index_iter;
MeshElemMap *map = MEM_calloc_arrayN(mvert_tot, sizeof(MeshElemMap), "DeformRingMap");
const MLoopTri *mlt;
@@ -156,10 +156,10 @@ static void createFaceRingMap(const int mvert_tot,
for (j = 0; j < 3; j++) {
const uint v_index = mloop[mlt->tri[j]].v;
map[v_index].count++;
- totalr++;
+ indices_num++;
}
}
- indices = MEM_calloc_arrayN(totalr, sizeof(int), "DeformRingIndex");
+ indices = MEM_calloc_arrayN(indices_num, sizeof(int), "DeformRingIndex");
index_iter = indices;
for (i = 0; i < mvert_tot; i++) {
map[i].indices = index_iter;
@@ -184,7 +184,7 @@ static void createVertRingMap(const int mvert_tot,
int **r_indices)
{
MeshElemMap *map = MEM_calloc_arrayN(mvert_tot, sizeof(MeshElemMap), "DeformNeighborsMap");
- int i, vid[2], totalr = 0;
+ int i, vid[2], indices_num = 0;
int *indices, *index_iter;
const MEdge *me;
@@ -193,9 +193,9 @@ static void createVertRingMap(const int mvert_tot,
vid[1] = me->v2;
map[vid[0]].count++;
map[vid[1]].count++;
- totalr += 2;
+ indices_num += 2;
}
- indices = MEM_calloc_arrayN(totalr, sizeof(int), "DeformNeighborsIndex");
+ indices = MEM_calloc_arrayN(indices_num, sizeof(int), "DeformNeighborsIndex");
index_iter = indices;
for (i = 0; i < mvert_tot; i++) {
map[i].indices = index_iter;
@@ -253,7 +253,7 @@ static void initLaplacianMatrix(LaplacianSystem *sys)
int i = 3, j, ti;
int idv[3];
- for (ti = 0; ti < sys->total_tris; ti++) {
+ for (ti = 0; ti < sys->tris_num; ti++) {
const uint *vidt = sys->tris[ti];
const float *co[3];
@@ -305,7 +305,7 @@ static void computeImplictRotations(LaplacianSystem *sys)
float minj, mjt, qj[3], vj[3];
int i, j, ln;
- for (i = 0; i < sys->total_verts; i++) {
+ for (i = 0; i < sys->verts_num; i++) {
normalize_v3(sys->no[i]);
vidn = sys->ringv_map[i].indices;
ln = sys->ringv_map[i].count;
@@ -329,10 +329,10 @@ static void rotateDifferentialCoordinates(LaplacianSystem *sys)
float alpha, beta, gamma;
float pj[3], ni[3], di[3];
float uij[3], dun[3], e2[3], pi[3], fni[3], vn[3][3];
- int i, j, num_fni, k, fi;
+ int i, j, fidn_num, k, fi;
int *fidn;
- for (i = 0; i < sys->total_verts; i++) {
+ for (i = 0; i < sys->verts_num; i++) {
copy_v3_v3(pi, sys->co[i]);
copy_v3_v3(ni, sys->no[i]);
k = sys->unit_verts[i];
@@ -351,8 +351,8 @@ static void rotateDifferentialCoordinates(LaplacianSystem *sys)
pi[1] = EIG_linear_solver_variable_get(sys->context, 1, i);
pi[2] = EIG_linear_solver_variable_get(sys->context, 2, i);
zero_v3(ni);
- num_fni = sys->ringf_map[i].count;
- for (fi = 0; fi < num_fni; fi++) {
+ fidn_num = sys->ringf_map[i].count;
+ for (fi = 0; fi < fidn_num; fi++) {
const uint *vin;
fidn = sys->ringf_map[i].indices;
vin = sys->tris[fidn[fi]];
@@ -395,8 +395,8 @@ static void rotateDifferentialCoordinates(LaplacianSystem *sys)
static void laplacianDeformPreview(LaplacianSystem *sys, float (*vertexCos)[3])
{
int vid, i, j, n, na;
- n = sys->total_verts;
- na = sys->total_anchors;
+ n = sys->verts_num;
+ na = sys->anchors_num;
if (!sys->is_matrix_computed) {
sys->context = EIG_linear_least_squares_solver_new(n + na, n, 3);
@@ -447,7 +447,7 @@ static void laplacianDeformPreview(LaplacianSystem *sys, float (*vertexCos)[3])
}
}
if (sys->has_solution) {
- for (vid = 0; vid < sys->total_verts; vid++) {
+ for (vid = 0; vid < sys->verts_num; vid++) {
vertexCos[vid][0] = EIG_linear_solver_variable_get(sys->context, 0, vid);
vertexCos[vid][1] = EIG_linear_solver_variable_get(sys->context, 1, vid);
vertexCos[vid][2] = EIG_linear_solver_variable_get(sys->context, 2, vid);
@@ -493,7 +493,7 @@ static void laplacianDeformPreview(LaplacianSystem *sys, float (*vertexCos)[3])
}
}
if (sys->has_solution) {
- for (vid = 0; vid < sys->total_verts; vid++) {
+ for (vid = 0; vid < sys->verts_num; vid++) {
vertexCos[vid][0] = EIG_linear_solver_variable_get(sys->context, 0, vid);
vertexCos[vid][1] = EIG_linear_solver_variable_get(sys->context, 1, vid);
vertexCos[vid][2] = EIG_linear_solver_variable_get(sys->context, 2, vid);
@@ -520,11 +520,11 @@ static bool isValidVertexGroup(LaplacianDeformModifierData *lmd, Object *ob, Mes
}
static void initSystem(
- LaplacianDeformModifierData *lmd, Object *ob, Mesh *mesh, float (*vertexCos)[3], int numVerts)
+ LaplacianDeformModifierData *lmd, Object *ob, Mesh *mesh, float (*vertexCos)[3], int verts_num)
{
int i;
int defgrp_index;
- int total_anchors;
+ int anchors_num;
float wpaint;
MDeformVert *dvert = NULL;
MDeformVert *dv = NULL;
@@ -532,18 +532,18 @@ static void initSystem(
const bool invert_vgroup = (lmd->flag & MOD_LAPLACIANDEFORM_INVERT_VGROUP) != 0;
if (isValidVertexGroup(lmd, ob, mesh)) {
- int *index_anchors = MEM_malloc_arrayN(numVerts, sizeof(int), __func__); /* over-alloc */
+ int *index_anchors = MEM_malloc_arrayN(verts_num, sizeof(int), __func__); /* over-alloc */
const MLoopTri *mlooptri;
const MLoop *mloop;
STACK_DECLARE(index_anchors);
- STACK_INIT(index_anchors, numVerts);
+ STACK_INIT(index_anchors, verts_num);
MOD_get_vgroup(ob, mesh, lmd->anchor_grp_name, &dvert, &defgrp_index);
BLI_assert(dvert != NULL);
dv = dvert;
- for (i = 0; i < numVerts; i++) {
+ for (i = 0; i < verts_num; i++) {
wpaint = invert_vgroup ? 1.0f - BKE_defvert_find_weight(dv, defgrp_index) :
BKE_defvert_find_weight(dv, defgrp_index);
dv++;
@@ -552,20 +552,20 @@ static void initSystem(
}
}
- total_anchors = STACK_SIZE(index_anchors);
- lmd->cache_system = initLaplacianSystem(numVerts,
+ anchors_num = STACK_SIZE(index_anchors);
+ lmd->cache_system = initLaplacianSystem(verts_num,
mesh->totedge,
BKE_mesh_runtime_looptri_len(mesh),
- total_anchors,
+ anchors_num,
lmd->anchor_grp_name,
lmd->repeat);
sys = (LaplacianSystem *)lmd->cache_system;
- memcpy(sys->index_anchors, index_anchors, sizeof(int) * total_anchors);
- memcpy(sys->co, vertexCos, sizeof(float[3]) * numVerts);
+ memcpy(sys->index_anchors, index_anchors, sizeof(int) * anchors_num);
+ memcpy(sys->co, vertexCos, sizeof(float[3]) * verts_num);
MEM_freeN(index_anchors);
- lmd->vertexco = MEM_malloc_arrayN(numVerts, sizeof(float[3]), "ModDeformCoordinates");
- memcpy(lmd->vertexco, vertexCos, sizeof(float[3]) * numVerts);
- lmd->total_verts = numVerts;
+ lmd->vertexco = MEM_malloc_arrayN(verts_num, sizeof(float[3]), "ModDeformCoordinates");
+ memcpy(lmd->vertexco, vertexCos, sizeof(float[3]) * verts_num);
+ lmd->verts_num = verts_num;
createFaceRingMap(mesh->totvert,
BKE_mesh_runtime_looptri_ensure(mesh),
@@ -579,7 +579,7 @@ static void initSystem(
mlooptri = BKE_mesh_runtime_looptri_ensure(mesh);
mloop = mesh->mloop;
- for (i = 0; i < sys->total_tris; i++) {
+ for (i = 0; i < sys->tris_num; i++) {
sys->tris[i][0] = mloop[mlooptri[i].tri[0]].v;
sys->tris[i][1] = mloop[mlooptri[i].tri[1]].v;
sys->tris[i][2] = mloop[mlooptri[i].tri[2]].v;
@@ -590,21 +590,21 @@ static void initSystem(
static int isSystemDifferent(LaplacianDeformModifierData *lmd,
Object *ob,
Mesh *mesh,
- int numVerts)
+ int verts_num)
{
int i;
int defgrp_index;
- int total_anchors = 0;
+ int anchors_num = 0;
float wpaint;
MDeformVert *dvert = NULL;
MDeformVert *dv = NULL;
LaplacianSystem *sys = (LaplacianSystem *)lmd->cache_system;
const bool invert_vgroup = (lmd->flag & MOD_LAPLACIANDEFORM_INVERT_VGROUP) != 0;
- if (sys->total_verts != numVerts) {
+ if (sys->verts_num != verts_num) {
return LAPDEFORM_SYSTEM_CHANGE_VERTEXES;
}
- if (sys->total_edges != mesh->totedge) {
+ if (sys->edges_num != mesh->totedge) {
return LAPDEFORM_SYSTEM_CHANGE_EDGES;
}
if (!STREQ(lmd->anchor_grp_name, sys->anchor_grp_name)) {
@@ -615,15 +615,15 @@ static int isSystemDifferent(LaplacianDeformModifierData *lmd,
return LAPDEFORM_SYSTEM_CHANGE_NOT_VALID_GROUP;
}
dv = dvert;
- for (i = 0; i < numVerts; i++) {
+ for (i = 0; i < verts_num; i++) {
wpaint = invert_vgroup ? 1.0f - BKE_defvert_find_weight(dv, defgrp_index) :
BKE_defvert_find_weight(dv, defgrp_index);
dv++;
if (wpaint > 0.0f) {
- total_anchors++;
+ anchors_num++;
}
}
- if (sys->total_anchors != total_anchors) {
+ if (sys->anchors_num != anchors_num) {
return LAPDEFORM_SYSTEM_ONLY_CHANGE_ANCHORS;
}
@@ -631,7 +631,7 @@ static int isSystemDifferent(LaplacianDeformModifierData *lmd,
}
static void LaplacianDeformModifier_do(
- LaplacianDeformModifierData *lmd, Object *ob, Mesh *mesh, float (*vertexCos)[3], int numVerts)
+ LaplacianDeformModifierData *lmd, Object *ob, Mesh *mesh, float (*vertexCos)[3], int verts_num)
{
float(*filevertexCos)[3];
int sysdif;
@@ -643,22 +643,22 @@ static void LaplacianDeformModifier_do(
deleteLaplacianSystem(sys);
lmd->cache_system = NULL;
}
- lmd->total_verts = 0;
+ lmd->verts_num = 0;
MEM_SAFE_FREE(lmd->vertexco);
return;
}
if (lmd->cache_system) {
- sysdif = isSystemDifferent(lmd, ob, mesh, numVerts);
+ sysdif = isSystemDifferent(lmd, ob, mesh, verts_num);
sys = lmd->cache_system;
if (sysdif) {
if (ELEM(sysdif, LAPDEFORM_SYSTEM_ONLY_CHANGE_ANCHORS, LAPDEFORM_SYSTEM_ONLY_CHANGE_GROUP)) {
- filevertexCos = MEM_malloc_arrayN(numVerts, sizeof(float[3]), "TempModDeformCoordinates");
- memcpy(filevertexCos, lmd->vertexco, sizeof(float[3]) * numVerts);
+ filevertexCos = MEM_malloc_arrayN(verts_num, sizeof(float[3]), "TempModDeformCoordinates");
+ memcpy(filevertexCos, lmd->vertexco, sizeof(float[3]) * verts_num);
MEM_SAFE_FREE(lmd->vertexco);
- lmd->total_verts = 0;
+ lmd->verts_num = 0;
deleteLaplacianSystem(sys);
lmd->cache_system = NULL;
- initSystem(lmd, ob, mesh, filevertexCos, numVerts);
+ initSystem(lmd, ob, mesh, filevertexCos, verts_num);
sys = lmd->cache_system; /* may have been reallocated */
MEM_SAFE_FREE(filevertexCos);
if (sys) {
@@ -668,11 +668,11 @@ static void LaplacianDeformModifier_do(
else {
if (sysdif == LAPDEFORM_SYSTEM_CHANGE_VERTEXES) {
BKE_modifier_set_error(
- ob, &lmd->modifier, "Vertices changed from %d to %d", lmd->total_verts, numVerts);
+ ob, &lmd->modifier, "Vertices changed from %d to %d", lmd->verts_num, verts_num);
}
else if (sysdif == LAPDEFORM_SYSTEM_CHANGE_EDGES) {
BKE_modifier_set_error(
- ob, &lmd->modifier, "Edges changed from %d to %d", sys->total_edges, mesh->totedge);
+ ob, &lmd->modifier, "Edges changed from %d to %d", sys->edges_num, mesh->totedge);
}
else if (sysdif == LAPDEFORM_SYSTEM_CHANGE_NOT_VALID_GROUP) {
BKE_modifier_set_error(ob,
@@ -695,18 +695,18 @@ static void LaplacianDeformModifier_do(
lmd->anchor_grp_name);
lmd->flag &= ~MOD_LAPLACIANDEFORM_BIND;
}
- else if (lmd->total_verts > 0 && lmd->total_verts == numVerts) {
- filevertexCos = MEM_malloc_arrayN(numVerts, sizeof(float[3]), "TempDeformCoordinates");
- memcpy(filevertexCos, lmd->vertexco, sizeof(float[3]) * numVerts);
+ else if (lmd->verts_num > 0 && lmd->verts_num == verts_num) {
+ filevertexCos = MEM_malloc_arrayN(verts_num, sizeof(float[3]), "TempDeformCoordinates");
+ memcpy(filevertexCos, lmd->vertexco, sizeof(float[3]) * verts_num);
MEM_SAFE_FREE(lmd->vertexco);
- lmd->total_verts = 0;
- initSystem(lmd, ob, mesh, filevertexCos, numVerts);
+ lmd->verts_num = 0;
+ initSystem(lmd, ob, mesh, filevertexCos, verts_num);
sys = lmd->cache_system;
MEM_SAFE_FREE(filevertexCos);
laplacianDeformPreview(sys, vertexCos);
}
else {
- initSystem(lmd, ob, mesh, vertexCos, numVerts);
+ initSystem(lmd, ob, mesh, vertexCos, verts_num);
sys = lmd->cache_system;
laplacianDeformPreview(sys, vertexCos);
}
@@ -762,12 +762,13 @@ static void deformVerts(ModifierData *md,
const ModifierEvalContext *ctx,
Mesh *mesh,
float (*vertexCos)[3],
- int numVerts)
+ int verts_num)
{
- Mesh *mesh_src = MOD_deform_mesh_eval_get(ctx->object, NULL, mesh, NULL, numVerts, false, false);
+ Mesh *mesh_src = MOD_deform_mesh_eval_get(
+ ctx->object, NULL, mesh, NULL, verts_num, false, false);
LaplacianDeformModifier_do(
- (LaplacianDeformModifierData *)md, ctx->object, mesh_src, vertexCos, numVerts);
+ (LaplacianDeformModifierData *)md, ctx->object, mesh_src, vertexCos, verts_num);
if (!ELEM(mesh_src, NULL, mesh)) {
BKE_id_free(NULL, mesh_src);
@@ -779,10 +780,10 @@ static void deformVertsEM(ModifierData *md,
struct BMEditMesh *editData,
Mesh *mesh,
float (*vertexCos)[3],
- int numVerts)
+ int verts_num)
{
Mesh *mesh_src = MOD_deform_mesh_eval_get(
- ctx->object, editData, mesh, NULL, numVerts, false, false);
+ ctx->object, editData, mesh, NULL, verts_num, false, false);
/* TODO(Campbell): use edit-mode data only (remove this line). */
if (mesh_src != NULL) {
@@ -790,7 +791,7 @@ static void deformVertsEM(ModifierData *md,
}
LaplacianDeformModifier_do(
- (LaplacianDeformModifierData *)md, ctx->object, mesh_src, vertexCos, numVerts);
+ (LaplacianDeformModifierData *)md, ctx->object, mesh_src, vertexCos, verts_num);
if (!ELEM(mesh_src, NULL, mesh)) {
BKE_id_free(NULL, mesh_src);
@@ -805,7 +806,7 @@ static void freeData(ModifierData *md)
deleteLaplacianSystem(sys);
}
MEM_SAFE_FREE(lmd->vertexco);
- lmd->total_verts = 0;
+ lmd->verts_num = 0;
}
static void panel_draw(const bContext *UNUSED(C), Panel *panel)
@@ -846,14 +847,14 @@ static void blendWrite(BlendWriter *writer, const ModifierData *md)
{
LaplacianDeformModifierData *lmd = (LaplacianDeformModifierData *)md;
- BLO_write_float3_array(writer, lmd->total_verts, lmd->vertexco);
+ BLO_write_float3_array(writer, lmd->verts_num, lmd->vertexco);
}
static void blendRead(BlendDataReader *reader, ModifierData *md)
{
LaplacianDeformModifierData *lmd = (LaplacianDeformModifierData *)md;
- BLO_read_float3_array(reader, lmd->total_verts, &lmd->vertexco);
+ BLO_read_float3_array(reader, lmd->verts_num, &lmd->vertexco);
lmd->cache_system = NULL;
}
diff --git a/source/blender/modifiers/intern/MOD_laplaciansmooth.c b/source/blender/modifiers/intern/MOD_laplaciansmooth.c
index effe2a5af90..11abe9a4d0a 100644
--- a/source/blender/modifiers/intern/MOD_laplaciansmooth.c
+++ b/source/blender/modifiers/intern/MOD_laplaciansmooth.c
@@ -45,12 +45,12 @@ struct BLaplacianSystem {
float *ring_areas; /* Total area per ring. */
float *vlengths; /* Total sum of lengths(edges) per vertex. */
float *vweights; /* Total sum of weights per vertex. */
- int numEdges; /* Number of edges. */
- int numLoops; /* Number of edges. */
- int numPolys; /* Number of faces. */
- int numVerts; /* Number of verts. */
- short *numNeFa; /* Number of neighbors faces around vertex. */
- short *numNeEd; /* Number of neighbors Edges around vertex. */
+ int edges_num; /* Number of edges. */
+ int loops_num; /* Number of edges. */
+ int polys_num; /* Number of faces. */
+ int verts_num; /* Number of verts. */
+ short *ne_fa_num; /* Number of neighbors faces around vertex. */
+ short *ne_ed_num; /* Number of neighbors Edges around vertex. */
bool *zerola; /* Is zero area or length. */
/* Pointers to data. */
@@ -71,7 +71,7 @@ static bool is_disabled(const struct Scene *scene, ModifierData *md, bool useRen
static float compute_volume(const float center[3],
float (*vertexCos)[3],
const MPoly *mpoly,
- int numPolys,
+ int polys_num,
const MLoop *mloop);
static LaplacianSystem *init_laplacian_system(int a_numEdges,
int a_numPolys,
@@ -89,8 +89,8 @@ static void delete_laplacian_system(LaplacianSystem *sys)
{
MEM_SAFE_FREE(sys->eweights);
MEM_SAFE_FREE(sys->fweights);
- MEM_SAFE_FREE(sys->numNeEd);
- MEM_SAFE_FREE(sys->numNeFa);
+ MEM_SAFE_FREE(sys->ne_ed_num);
+ MEM_SAFE_FREE(sys->ne_fa_num);
MEM_SAFE_FREE(sys->ring_areas);
MEM_SAFE_FREE(sys->vlengths);
MEM_SAFE_FREE(sys->vweights);
@@ -108,14 +108,14 @@ static void delete_laplacian_system(LaplacianSystem *sys)
static void memset_laplacian_system(LaplacianSystem *sys, int val)
{
- memset(sys->eweights, val, sizeof(float) * sys->numEdges);
- memset(sys->fweights, val, sizeof(float[3]) * sys->numLoops);
- memset(sys->numNeEd, val, sizeof(short) * sys->numVerts);
- memset(sys->numNeFa, val, sizeof(short) * sys->numVerts);
- memset(sys->ring_areas, val, sizeof(float) * sys->numVerts);
- memset(sys->vlengths, val, sizeof(float) * sys->numVerts);
- memset(sys->vweights, val, sizeof(float) * sys->numVerts);
- memset(sys->zerola, val, sizeof(bool) * sys->numVerts);
+ memset(sys->eweights, val, sizeof(float) * sys->edges_num);
+ memset(sys->fweights, val, sizeof(float[3]) * sys->loops_num);
+ memset(sys->ne_ed_num, val, sizeof(short) * sys->verts_num);
+ memset(sys->ne_fa_num, val, sizeof(short) * sys->verts_num);
+ memset(sys->ring_areas, val, sizeof(float) * sys->verts_num);
+ memset(sys->vlengths, val, sizeof(float) * sys->verts_num);
+ memset(sys->vweights, val, sizeof(float) * sys->verts_num);
+ memset(sys->zerola, val, sizeof(bool) * sys->verts_num);
}
static LaplacianSystem *init_laplacian_system(int a_numEdges,
@@ -125,19 +125,19 @@ static LaplacianSystem *init_laplacian_system(int a_numEdges,
{
LaplacianSystem *sys;
sys = MEM_callocN(sizeof(LaplacianSystem), "ModLaplSmoothSystem");
- sys->numEdges = a_numEdges;
- sys->numPolys = a_numPolys;
- sys->numLoops = a_numLoops;
- sys->numVerts = a_numVerts;
-
- sys->eweights = MEM_calloc_arrayN(sys->numEdges, sizeof(float), __func__);
- sys->fweights = MEM_calloc_arrayN(sys->numLoops, sizeof(float[3]), __func__);
- sys->numNeEd = MEM_calloc_arrayN(sys->numVerts, sizeof(short), __func__);
- sys->numNeFa = MEM_calloc_arrayN(sys->numVerts, sizeof(short), __func__);
- sys->ring_areas = MEM_calloc_arrayN(sys->numVerts, sizeof(float), __func__);
- sys->vlengths = MEM_calloc_arrayN(sys->numVerts, sizeof(float), __func__);
- sys->vweights = MEM_calloc_arrayN(sys->numVerts, sizeof(float), __func__);
- sys->zerola = MEM_calloc_arrayN(sys->numVerts, sizeof(bool), __func__);
+ sys->edges_num = a_numEdges;
+ sys->polys_num = a_numPolys;
+ sys->loops_num = a_numLoops;
+ sys->verts_num = a_numVerts;
+
+ sys->eweights = MEM_calloc_arrayN(sys->edges_num, sizeof(float), __func__);
+ sys->fweights = MEM_calloc_arrayN(sys->loops_num, sizeof(float[3]), __func__);
+ sys->ne_ed_num = MEM_calloc_arrayN(sys->verts_num, sizeof(short), __func__);
+ sys->ne_fa_num = MEM_calloc_arrayN(sys->verts_num, sizeof(short), __func__);
+ sys->ring_areas = MEM_calloc_arrayN(sys->verts_num, sizeof(float), __func__);
+ sys->vlengths = MEM_calloc_arrayN(sys->verts_num, sizeof(float), __func__);
+ sys->vweights = MEM_calloc_arrayN(sys->verts_num, sizeof(float), __func__);
+ sys->zerola = MEM_calloc_arrayN(sys->verts_num, sizeof(bool), __func__);
return sys;
}
@@ -145,13 +145,13 @@ static LaplacianSystem *init_laplacian_system(int a_numEdges,
static float compute_volume(const float center[3],
float (*vertexCos)[3],
const MPoly *mpoly,
- int numPolys,
+ int polys_num,
const MLoop *mloop)
{
int i;
float vol = 0.0f;
- for (i = 0; i < numPolys; i++) {
+ for (i = 0; i < polys_num; i++) {
const MPoly *mp = &mpoly[i];
const MLoop *l_first = &mloop[mp->loopstart];
const MLoop *l_prev = l_first + 1;
@@ -174,7 +174,7 @@ static void volume_preservation(LaplacianSystem *sys, float vini, float vend, sh
if (vend != 0.0f) {
beta = pow(vini / vend, 1.0f / 3.0f);
- for (i = 0; i < sys->numVerts; i++) {
+ for (i = 0; i < sys->verts_num; i++) {
if (flag & MOD_LAPLACIANSMOOTH_X) {
sys->vertexCos[i][0] = (sys->vertexCos[i][0] - sys->vert_centroid[0]) * beta +
sys->vert_centroid[0];
@@ -199,15 +199,15 @@ static void init_laplacian_matrix(LaplacianSystem *sys)
int i;
uint idv1, idv2;
- for (i = 0; i < sys->numEdges; i++) {
+ for (i = 0; i < sys->edges_num; i++) {
idv1 = sys->medges[i].v1;
idv2 = sys->medges[i].v2;
v1 = sys->vertexCos[idv1];
v2 = sys->vertexCos[idv2];
- sys->numNeEd[idv1] = sys->numNeEd[idv1] + 1;
- sys->numNeEd[idv2] = sys->numNeEd[idv2] + 1;
+ sys->ne_ed_num[idv1] = sys->ne_ed_num[idv1] + 1;
+ sys->ne_ed_num[idv2] = sys->ne_ed_num[idv2] + 1;
w1 = len_v3v3(v1, v2);
if (w1 < sys->min_area) {
sys->zerola[idv1] = true;
@@ -220,7 +220,7 @@ static void init_laplacian_matrix(LaplacianSystem *sys)
sys->eweights[i] = w1;
}
- for (i = 0; i < sys->numPolys; i++) {
+ for (i = 0; i < sys->polys_num; i++) {
const MPoly *mp = &sys->mpoly[i];
const MLoop *l_next = &sys->mloop[mp->loopstart];
const MLoop *l_term = l_next + mp->totloop;
@@ -233,7 +233,7 @@ static void init_laplacian_matrix(LaplacianSystem *sys)
const float *v_next = sys->vertexCos[l_next->v];
const uint l_curr_index = l_curr - sys->mloop;
- sys->numNeFa[l_curr->v] += 1;
+ sys->ne_fa_num[l_curr->v] += 1;
areaf = area_tri_v3(v_prev, v_curr, v_next);
@@ -258,11 +258,12 @@ static void init_laplacian_matrix(LaplacianSystem *sys)
sys->vweights[l_prev->v] += w1 + w2;
}
}
- for (i = 0; i < sys->numEdges; i++) {
+ for (i = 0; i < sys->edges_num; i++) {
idv1 = sys->medges[i].v1;
idv2 = sys->medges[i].v2;
/* if is boundary, apply scale-dependent umbrella operator only with neighbors in boundary */
- if (sys->numNeEd[idv1] != sys->numNeFa[idv1] && sys->numNeEd[idv2] != sys->numNeFa[idv2]) {
+ if (sys->ne_ed_num[idv1] != sys->ne_fa_num[idv1] &&
+ sys->ne_ed_num[idv2] != sys->ne_fa_num[idv2]) {
sys->vlengths[idv1] += sys->eweights[i];
sys->vlengths[idv2] += sys->eweights[i];
}
@@ -274,7 +275,7 @@ static void fill_laplacian_matrix(LaplacianSystem *sys)
int i;
uint idv1, idv2;
- for (i = 0; i < sys->numPolys; i++) {
+ for (i = 0; i < sys->polys_num; i++) {
const MPoly *mp = &sys->mpoly[i];
const MLoop *l_next = &sys->mloop[mp->loopstart];
const MLoop *l_term = l_next + mp->totloop;
@@ -285,7 +286,8 @@ static void fill_laplacian_matrix(LaplacianSystem *sys)
const uint l_curr_index = l_curr - sys->mloop;
/* Is ring if number of faces == number of edges around vertex. */
- if (sys->numNeEd[l_curr->v] == sys->numNeFa[l_curr->v] && sys->zerola[l_curr->v] == false) {
+ if (sys->ne_ed_num[l_curr->v] == sys->ne_fa_num[l_curr->v] &&
+ sys->zerola[l_curr->v] == false) {
EIG_linear_solver_matrix_add(sys->context,
l_curr->v,
l_next->v,
@@ -295,7 +297,8 @@ static void fill_laplacian_matrix(LaplacianSystem *sys)
l_prev->v,
sys->fweights[l_curr_index][1] * sys->vweights[l_curr->v]);
}
- if (sys->numNeEd[l_next->v] == sys->numNeFa[l_next->v] && sys->zerola[l_next->v] == false) {
+ if (sys->ne_ed_num[l_next->v] == sys->ne_fa_num[l_next->v] &&
+ sys->zerola[l_next->v] == false) {
EIG_linear_solver_matrix_add(sys->context,
l_next->v,
l_curr->v,
@@ -305,7 +308,8 @@ static void fill_laplacian_matrix(LaplacianSystem *sys)
l_prev->v,
sys->fweights[l_curr_index][0] * sys->vweights[l_next->v]);
}
- if (sys->numNeEd[l_prev->v] == sys->numNeFa[l_prev->v] && sys->zerola[l_prev->v] == false) {
+ if (sys->ne_ed_num[l_prev->v] == sys->ne_fa_num[l_prev->v] &&
+ sys->zerola[l_prev->v] == false) {
EIG_linear_solver_matrix_add(sys->context,
l_prev->v,
l_curr->v,
@@ -318,12 +322,13 @@ static void fill_laplacian_matrix(LaplacianSystem *sys)
}
}
- for (i = 0; i < sys->numEdges; i++) {
+ for (i = 0; i < sys->edges_num; i++) {
idv1 = sys->medges[i].v1;
idv2 = sys->medges[i].v2;
/* Is boundary */
- if (sys->numNeEd[idv1] != sys->numNeFa[idv1] && sys->numNeEd[idv2] != sys->numNeFa[idv2] &&
- sys->zerola[idv1] == false && sys->zerola[idv2] == false) {
+ if (sys->ne_ed_num[idv1] != sys->ne_fa_num[idv1] &&
+ sys->ne_ed_num[idv2] != sys->ne_fa_num[idv2] && sys->zerola[idv1] == false &&
+ sys->zerola[idv2] == false) {
EIG_linear_solver_matrix_add(
sys->context, idv1, idv2, sys->eweights[i] * sys->vlengths[idv1]);
EIG_linear_solver_matrix_add(
@@ -340,12 +345,12 @@ static void validate_solution(LaplacianSystem *sys, short flag, float lambda, fl
if (flag & MOD_LAPLACIANSMOOTH_PRESERVE_VOLUME) {
vini = compute_volume(
- sys->vert_centroid, sys->vertexCos, sys->mpoly, sys->numPolys, sys->mloop);
+ sys->vert_centroid, sys->vertexCos, sys->mpoly, sys->polys_num, sys->mloop);
}
- for (i = 0; i < sys->numVerts; i++) {
+ for (i = 0; i < sys->verts_num; i++) {
if (sys->zerola[i] == false) {
- lam = sys->numNeEd[i] == sys->numNeFa[i] ? (lambda >= 0.0f ? 1.0f : -1.0f) :
- (lambda_border >= 0.0f ? 1.0f : -1.0f);
+ lam = sys->ne_ed_num[i] == sys->ne_fa_num[i] ? (lambda >= 0.0f ? 1.0f : -1.0f) :
+ (lambda_border >= 0.0f ? 1.0f : -1.0f);
if (flag & MOD_LAPLACIANSMOOTH_X) {
sys->vertexCos[i][0] += lam * ((float)EIG_linear_solver_variable_get(sys->context, 0, i) -
sys->vertexCos[i][0]);
@@ -362,13 +367,13 @@ static void validate_solution(LaplacianSystem *sys, short flag, float lambda, fl
}
if (flag & MOD_LAPLACIANSMOOTH_PRESERVE_VOLUME) {
vend = compute_volume(
- sys->vert_centroid, sys->vertexCos, sys->mpoly, sys->numPolys, sys->mloop);
+ sys->vert_centroid, sys->vertexCos, sys->mpoly, sys->polys_num, sys->mloop);
volume_preservation(sys, vini, vend, flag);
}
}
static void laplaciansmoothModifier_do(
- LaplacianSmoothModifierData *smd, Object *ob, Mesh *mesh, float (*vertexCos)[3], int numVerts)
+ LaplacianSmoothModifierData *smd, Object *ob, Mesh *mesh, float (*vertexCos)[3], int verts_num)
{
LaplacianSystem *sys;
MDeformVert *dvert = NULL;
@@ -378,7 +383,7 @@ static void laplaciansmoothModifier_do(
int defgrp_index;
const bool invert_vgroup = (smd->flag & MOD_LAPLACIANSMOOTH_INVERT_VGROUP) != 0;
- sys = init_laplacian_system(mesh->totedge, mesh->totpoly, mesh->totloop, numVerts);
+ sys = init_laplacian_system(mesh->totedge, mesh->totpoly, mesh->totloop, verts_num);
if (!sys) {
return;
}
@@ -395,12 +400,12 @@ static void laplaciansmoothModifier_do(
sys->vert_centroid[2] = 0.0f;
memset_laplacian_system(sys, 0);
- sys->context = EIG_linear_least_squares_solver_new(numVerts, numVerts, 3);
+ sys->context = EIG_linear_least_squares_solver_new(verts_num, verts_num, 3);
init_laplacian_matrix(sys);
for (iter = 0; iter < smd->repeat; iter++) {
- for (i = 0; i < numVerts; i++) {
+ for (i = 0; i < verts_num; i++) {
EIG_linear_solver_variable_set(sys->context, 0, i, vertexCos[i][0]);
EIG_linear_solver_variable_set(sys->context, 1, i, vertexCos[i][1]);
EIG_linear_solver_variable_set(sys->context, 2, i, vertexCos[i][2]);
@@ -408,12 +413,12 @@ static void laplaciansmoothModifier_do(
add_v3_v3(sys->vert_centroid, vertexCos[i]);
}
}
- if (iter == 0 && numVerts > 0) {
- mul_v3_fl(sys->vert_centroid, 1.0f / (float)numVerts);
+ if (iter == 0 && verts_num > 0) {
+ mul_v3_fl(sys->vert_centroid, 1.0f / (float)verts_num);
}
dv = dvert;
- for (i = 0; i < numVerts; i++) {
+ for (i = 0; i < verts_num; i++) {
EIG_linear_solver_right_hand_side_add(sys->context, 0, i, vertexCos[i][0]);
EIG_linear_solver_right_hand_side_add(sys->context, 1, i, vertexCos[i][1]);
EIG_linear_solver_right_hand_side_add(sys->context, 2, i, vertexCos[i][2]);
@@ -433,7 +438,7 @@ static void laplaciansmoothModifier_do(
sys->vweights[i] = (w == 0.0f) ? 0.0f : -fabsf(smd->lambda) * wpaint / w;
w = sys->vlengths[i];
sys->vlengths[i] = (w == 0.0f) ? 0.0f : -fabsf(smd->lambda_border) * wpaint * 2.0f / w;
- if (sys->numNeEd[i] == sys->numNeFa[i]) {
+ if (sys->ne_ed_num[i] == sys->ne_fa_num[i]) {
EIG_linear_solver_matrix_add(sys->context, i, i, 1.0f + fabsf(smd->lambda) * wpaint);
}
else {
@@ -447,7 +452,7 @@ static void laplaciansmoothModifier_do(
w = sys->vlengths[i];
sys->vlengths[i] = (w == 0.0f) ? 0.0f : -fabsf(smd->lambda_border) * wpaint * 2.0f / w;
- if (sys->numNeEd[i] == sys->numNeFa[i]) {
+ if (sys->ne_ed_num[i] == sys->ne_fa_num[i]) {
EIG_linear_solver_matrix_add(sys->context,
i,
i,
@@ -522,18 +527,18 @@ static void deformVerts(ModifierData *md,
const ModifierEvalContext *ctx,
Mesh *mesh,
float (*vertexCos)[3],
- int numVerts)
+ int verts_num)
{
Mesh *mesh_src;
- if (numVerts == 0) {
+ if (verts_num == 0) {
return;
}
- mesh_src = MOD_deform_mesh_eval_get(ctx->object, NULL, mesh, NULL, numVerts, false, false);
+ mesh_src = MOD_deform_mesh_eval_get(ctx->object, NULL, mesh, NULL, verts_num, false, false);
laplaciansmoothModifier_do(
- (LaplacianSmoothModifierData *)md, ctx->object, mesh_src, vertexCos, numVerts);
+ (LaplacianSmoothModifierData *)md, ctx->object, mesh_src, vertexCos, verts_num);
if (!ELEM(mesh_src, NULL, mesh)) {
BKE_id_free(NULL, mesh_src);
@@ -545,15 +550,15 @@ static void deformVertsEM(ModifierData *md,
struct BMEditMesh *editData,
Mesh *mesh,
float (*vertexCos)[3],
- int numVerts)
+ int verts_num)
{
Mesh *mesh_src;
- if (numVerts == 0) {
+ if (verts_num == 0) {
return;
}
- mesh_src = MOD_deform_mesh_eval_get(ctx->object, editData, mesh, NULL, numVerts, false, false);
+ mesh_src = MOD_deform_mesh_eval_get(ctx->object, editData, mesh, NULL, verts_num, false, false);
/* TODO(Campbell): use edit-mode data only (remove this line). */
if (mesh_src != NULL) {
@@ -561,7 +566,7 @@ static void deformVertsEM(ModifierData *md,
}
laplaciansmoothModifier_do(
- (LaplacianSmoothModifierData *)md, ctx->object, mesh_src, vertexCos, numVerts);
+ (LaplacianSmoothModifierData *)md, ctx->object, mesh_src, vertexCos, verts_num);
if (!ELEM(mesh_src, NULL, mesh)) {
BKE_id_free(NULL, mesh_src);
diff --git a/source/blender/modifiers/intern/MOD_lattice.c b/source/blender/modifiers/intern/MOD_lattice.c
index 1017f6cca1a..832372304a0 100644
--- a/source/blender/modifiers/intern/MOD_lattice.c
+++ b/source/blender/modifiers/intern/MOD_lattice.c
@@ -94,18 +94,18 @@ static void deformVerts(ModifierData *md,
const ModifierEvalContext *ctx,
struct Mesh *mesh,
float (*vertexCos)[3],
- int numVerts)
+ int verts_num)
{
LatticeModifierData *lmd = (LatticeModifierData *)md;
struct Mesh *mesh_src = MOD_deform_mesh_eval_get(
- ctx->object, NULL, mesh, NULL, numVerts, false, false);
+ ctx->object, NULL, mesh, NULL, verts_num, false, false);
MOD_previous_vcos_store(md, vertexCos); /* if next modifier needs original vertices */
BKE_lattice_deform_coords_with_mesh(lmd->object,
ctx->object,
vertexCos,
- numVerts,
+ verts_num,
lmd->flag,
lmd->name,
lmd->strength,
@@ -121,10 +121,10 @@ static void deformVertsEM(ModifierData *md,
struct BMEditMesh *em,
struct Mesh *mesh,
float (*vertexCos)[3],
- int numVerts)
+ int verts_num)
{
if (mesh != NULL) {
- deformVerts(md, ctx, mesh, vertexCos, numVerts);
+ deformVerts(md, ctx, mesh, vertexCos, verts_num);
return;
}
@@ -133,7 +133,7 @@ static void deformVertsEM(ModifierData *md,
MOD_previous_vcos_store(md, vertexCos); /* if next modifier needs original vertices */
BKE_lattice_deform_coords_with_editmesh(
- lmd->object, ctx->object, vertexCos, numVerts, lmd->flag, lmd->name, lmd->strength, em);
+ lmd->object, ctx->object, vertexCos, verts_num, lmd->flag, lmd->name, lmd->strength, em);
}
static void panel_draw(const bContext *UNUSED(C), Panel *panel)
diff --git a/source/blender/modifiers/intern/MOD_mask.cc b/source/blender/modifiers/intern/MOD_mask.cc
index 1cb720f4b02..cb26bd1b26b 100644
--- a/source/blender/modifiers/intern/MOD_mask.cc
+++ b/source/blender/modifiers/intern/MOD_mask.cc
@@ -145,58 +145,58 @@ static void invert_boolean_array(MutableSpan<bool> array)
static void compute_masked_vertices(Span<bool> vertex_mask,
MutableSpan<int> r_vertex_map,
- uint *r_num_masked_vertices)
+ uint *r_verts_masked_num)
{
BLI_assert(vertex_mask.size() == r_vertex_map.size());
- uint num_masked_vertices = 0;
+ uint verts_masked_num = 0;
for (uint i_src : r_vertex_map.index_range()) {
if (vertex_mask[i_src]) {
- r_vertex_map[i_src] = num_masked_vertices;
- num_masked_vertices++;
+ r_vertex_map[i_src] = verts_masked_num;
+ verts_masked_num++;
}
else {
r_vertex_map[i_src] = -1;
}
}
- *r_num_masked_vertices = num_masked_vertices;
+ *r_verts_masked_num = verts_masked_num;
}
static void computed_masked_edges(const Mesh *mesh,
Span<bool> vertex_mask,
MutableSpan<int> r_edge_map,
- uint *r_num_masked_edges)
+ uint *r_edges_masked_num)
{
BLI_assert(mesh->totedge == r_edge_map.size());
- uint num_masked_edges = 0;
+ uint edges_masked_num = 0;
for (int i : IndexRange(mesh->totedge)) {
const MEdge &edge = mesh->medge[i];
/* only add if both verts will be in new mesh */
if (vertex_mask[edge.v1] && vertex_mask[edge.v2]) {
- r_edge_map[i] = num_masked_edges;
- num_masked_edges++;
+ r_edge_map[i] = edges_masked_num;
+ edges_masked_num++;
}
else {
r_edge_map[i] = -1;
}
}
- *r_num_masked_edges = num_masked_edges;
+ *r_edges_masked_num = edges_masked_num;
}
static void computed_masked_edges_smooth(const Mesh *mesh,
Span<bool> vertex_mask,
MutableSpan<int> r_edge_map,
- uint *r_num_masked_edges,
- uint *r_num_add_vertices)
+ uint *r_edges_masked_num,
+ uint *r_verts_add_num)
{
BLI_assert(mesh->totedge == r_edge_map.size());
- uint num_masked_edges = 0;
- uint num_add_vertices = 0;
+ uint edges_masked_num = 0;
+ uint verts_add_num = 0;
for (int i : IndexRange(mesh->totedge)) {
const MEdge &edge = mesh->medge[i];
@@ -204,36 +204,36 @@ static void computed_masked_edges_smooth(const Mesh *mesh,
bool v1 = vertex_mask[edge.v1];
bool v2 = vertex_mask[edge.v2];
if (v1 && v2) {
- r_edge_map[i] = num_masked_edges;
- num_masked_edges++;
+ r_edge_map[i] = edges_masked_num;
+ edges_masked_num++;
}
else if (v1 != v2) {
r_edge_map[i] = -2;
- num_add_vertices++;
+ verts_add_num++;
}
else {
r_edge_map[i] = -1;
}
}
- num_masked_edges += num_add_vertices;
- *r_num_masked_edges = num_masked_edges;
- *r_num_add_vertices = num_add_vertices;
+ edges_masked_num += verts_add_num;
+ *r_edges_masked_num = edges_masked_num;
+ *r_verts_add_num = verts_add_num;
}
static void computed_masked_polygons(const Mesh *mesh,
Span<bool> vertex_mask,
Vector<int> &r_masked_poly_indices,
Vector<int> &r_loop_starts,
- uint *r_num_masked_polys,
- uint *r_num_masked_loops)
+ uint *r_polys_masked_num,
+ uint *r_loops_masked_num)
{
BLI_assert(mesh->totvert == vertex_mask.size());
r_masked_poly_indices.reserve(mesh->totpoly);
r_loop_starts.reserve(mesh->totpoly);
- uint num_masked_loops = 0;
+ uint loops_masked_num = 0;
for (int i : IndexRange(mesh->totpoly)) {
const MPoly &poly_src = mesh->mpoly[i];
@@ -248,35 +248,35 @@ static void computed_masked_polygons(const Mesh *mesh,
if (all_verts_in_mask) {
r_masked_poly_indices.append_unchecked(i);
- r_loop_starts.append_unchecked(num_masked_loops);
- num_masked_loops += poly_src.totloop;
+ r_loop_starts.append_unchecked(loops_masked_num);
+ loops_masked_num += poly_src.totloop;
}
}
- *r_num_masked_polys = r_masked_poly_indices.size();
- *r_num_masked_loops = num_masked_loops;
+ *r_polys_masked_num = r_masked_poly_indices.size();
+ *r_loops_masked_num = loops_masked_num;
}
static void compute_interpolated_polygons(const Mesh *mesh,
Span<bool> vertex_mask,
- uint num_add_vertices,
- uint num_masked_loops,
+ uint verts_add_num,
+ uint loops_masked_num,
Vector<int> &r_masked_poly_indices,
Vector<int> &r_loop_starts,
- uint *r_num_add_edges,
- uint *r_num_add_polys,
- uint *r_num_add_loops)
+ uint *r_edges_add_num,
+ uint *r_polys_add_num,
+ uint *r_loops_add_num)
{
BLI_assert(mesh->totvert == vertex_mask.size());
/* Can't really know ahead of time how much space to use exactly. Estimate limit instead. */
/* NOTE: this reserve can only lift the capacity if there are ngons, which get split. */
- r_masked_poly_indices.reserve(r_masked_poly_indices.size() + num_add_vertices);
- r_loop_starts.reserve(r_loop_starts.size() + num_add_vertices);
+ r_masked_poly_indices.reserve(r_masked_poly_indices.size() + verts_add_num);
+ r_loop_starts.reserve(r_loop_starts.size() + verts_add_num);
- uint num_add_edges = 0;
- uint num_add_polys = 0;
- uint num_add_loops = 0;
+ uint edges_add_num = 0;
+ uint polys_add_num = 0;
+ uint loops_add_num = 0;
for (int i : IndexRange(mesh->totpoly)) {
const MPoly &poly_src = mesh->mpoly[i];
@@ -306,10 +306,10 @@ static void compute_interpolated_polygons(const Mesh *mesh,
else if (!v_loop_in_mask && v_loop_in_mask_last) {
BLI_assert(dst_totloop > 2);
r_masked_poly_indices.append(i);
- r_loop_starts.append(num_masked_loops + num_add_loops);
- num_add_loops += dst_totloop;
- num_add_polys++;
- num_add_edges++;
+ r_loop_starts.append(loops_masked_num + loops_add_num);
+ loops_add_num += dst_totloop;
+ polys_add_num++;
+ edges_add_num++;
dst_totloop = -1;
}
else if (v_loop_in_mask && v_loop_in_mask_last) {
@@ -322,9 +322,9 @@ static void compute_interpolated_polygons(const Mesh *mesh,
}
}
- *r_num_add_edges = num_add_edges;
- *r_num_add_polys = num_add_polys;
- *r_num_add_loops = num_add_loops;
+ *r_edges_add_num = edges_add_num;
+ *r_polys_add_num = polys_add_num;
+ *r_loops_add_num = loops_add_num;
}
static void copy_masked_vertices_to_new_mesh(const Mesh &src_mesh,
@@ -363,15 +363,15 @@ static void add_interp_verts_copy_edges_to_new_mesh(const Mesh &src_mesh,
MDeformVert *dvert,
int defgrp_index,
float threshold,
- uint num_masked_edges,
- uint num_add_verts,
+ uint edges_masked_num,
+ uint verts_add_num,
MutableSpan<int> r_edge_map)
{
BLI_assert(src_mesh.totvert == vertex_mask.size());
BLI_assert(src_mesh.totedge == r_edge_map.size());
- uint vert_index = dst_mesh.totvert - num_add_verts;
- uint edge_index = num_masked_edges - num_add_verts;
+ uint vert_index = dst_mesh.totvert - verts_add_num;
+ uint edge_index = edges_masked_num - verts_add_num;
for (int i_src : IndexRange(src_mesh.totedge)) {
if (r_edge_map[i_src] != -1) {
int i_dst = r_edge_map[i_src];
@@ -416,7 +416,7 @@ static void add_interp_verts_copy_edges_to_new_mesh(const Mesh &src_mesh,
}
}
BLI_assert(vert_index == dst_mesh.totvert);
- BLI_assert(edge_index == num_masked_edges);
+ BLI_assert(edge_index == edges_masked_num);
}
static void copy_masked_edges_to_new_mesh(const Mesh &src_mesh,
@@ -448,9 +448,9 @@ static void copy_masked_polys_to_new_mesh(const Mesh &src_mesh,
Span<int> edge_map,
Span<int> masked_poly_indices,
Span<int> new_loop_starts,
- int num_masked_polys)
+ int polys_masked_num)
{
- for (const int i_dst : IndexRange(num_masked_polys)) {
+ for (const int i_dst : IndexRange(polys_masked_num)) {
const int i_src = masked_poly_indices[i_dst];
const MPoly &mp_src = src_mesh.mpoly[i_src];
@@ -483,14 +483,14 @@ static void add_interpolated_polys_to_new_mesh(const Mesh &src_mesh,
float threshold,
Span<int> masked_poly_indices,
Span<int> new_loop_starts,
- int num_masked_polys,
- int num_add_edges)
+ int polys_masked_num,
+ int edges_add_num)
{
- int edge_index = dst_mesh.totedge - num_add_edges;
+ int edge_index = dst_mesh.totedge - edges_add_num;
int sub_poly_index = 0;
int last_i_src = -1;
for (const int i_dst :
- IndexRange(num_masked_polys, masked_poly_indices.size() - num_masked_polys)) {
+ IndexRange(polys_masked_num, masked_poly_indices.size() - polys_masked_num)) {
const int i_src = masked_poly_indices[i_dst];
if (i_src == last_i_src) {
sub_poly_index++;
@@ -662,53 +662,52 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *UNUSED(ctx)
}
Array<int> vertex_map(mesh->totvert);
- uint num_masked_vertices;
- compute_masked_vertices(vertex_mask, vertex_map, &num_masked_vertices);
+ uint verts_masked_num;
+ compute_masked_vertices(vertex_mask, vertex_map, &verts_masked_num);
Array<int> edge_map(mesh->totedge);
- uint num_masked_edges;
- uint num_add_vertices;
+ uint edges_masked_num;
+ uint verts_add_num;
if (use_interpolation) {
- computed_masked_edges_smooth(
- mesh, vertex_mask, edge_map, &num_masked_edges, &num_add_vertices);
+ computed_masked_edges_smooth(mesh, vertex_mask, edge_map, &edges_masked_num, &verts_add_num);
}
else {
- computed_masked_edges(mesh, vertex_mask, edge_map, &num_masked_edges);
- num_add_vertices = 0;
+ computed_masked_edges(mesh, vertex_mask, edge_map, &edges_masked_num);
+ verts_add_num = 0;
}
Vector<int> masked_poly_indices;
Vector<int> new_loop_starts;
- uint num_masked_polys;
- uint num_masked_loops;
+ uint polys_masked_num;
+ uint loops_masked_num;
computed_masked_polygons(mesh,
vertex_mask,
masked_poly_indices,
new_loop_starts,
- &num_masked_polys,
- &num_masked_loops);
+ &polys_masked_num,
+ &loops_masked_num);
- uint num_add_edges = 0;
- uint num_add_polys = 0;
- uint num_add_loops = 0;
+ uint edges_add_num = 0;
+ uint polys_add_num = 0;
+ uint loops_add_num = 0;
if (use_interpolation) {
compute_interpolated_polygons(mesh,
vertex_mask,
- num_add_vertices,
- num_masked_loops,
+ verts_add_num,
+ loops_masked_num,
masked_poly_indices,
new_loop_starts,
- &num_add_edges,
- &num_add_polys,
- &num_add_loops);
+ &edges_add_num,
+ &polys_add_num,
+ &loops_add_num);
}
Mesh *result = BKE_mesh_new_nomain_from_template(mesh,
- num_masked_vertices + num_add_vertices,
- num_masked_edges + num_add_edges,
+ verts_masked_num + verts_add_num,
+ edges_masked_num + edges_add_num,
0,
- num_masked_loops + num_add_loops,
- num_masked_polys + num_add_polys);
+ loops_masked_num + loops_add_num,
+ polys_masked_num + polys_add_num);
copy_masked_vertices_to_new_mesh(*mesh, *result, vertex_map);
if (use_interpolation) {
@@ -719,8 +718,8 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *UNUSED(ctx)
dvert,
defgrp_index,
mmd->threshold,
- num_masked_edges,
- num_add_vertices,
+ edges_masked_num,
+ verts_add_num,
edge_map);
}
else {
@@ -732,7 +731,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *UNUSED(ctx)
edge_map,
masked_poly_indices,
new_loop_starts,
- num_masked_polys);
+ polys_masked_num);
if (use_interpolation) {
add_interpolated_polys_to_new_mesh(*mesh,
*result,
@@ -744,8 +743,8 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *UNUSED(ctx)
mmd->threshold,
masked_poly_indices,
new_loop_starts,
- num_masked_polys,
- num_add_edges);
+ polys_masked_num,
+ edges_add_num);
}
BKE_mesh_calc_edges_loose(result);
diff --git a/source/blender/modifiers/intern/MOD_meshcache.c b/source/blender/modifiers/intern/MOD_meshcache.c
index 3e022a5951d..6f065797b43 100644
--- a/source/blender/modifiers/intern/MOD_meshcache.c
+++ b/source/blender/modifiers/intern/MOD_meshcache.c
@@ -54,9 +54,7 @@ static void initData(ModifierData *md)
MEMCPY_STRUCT_AFTER(mcmd, DNA_struct_default_get(MeshCacheModifierData), modifier);
}
-static bool dependsOnTime(struct Scene *UNUSED(scene),
- ModifierData *md,
- const int UNUSED(dag_eval_mode))
+static bool dependsOnTime(struct Scene *UNUSED(scene), ModifierData *md)
{
MeshCacheModifierData *mcmd = (MeshCacheModifierData *)md;
return (mcmd->play_mode == MOD_MESHCACHE_PLAY_CFEA);
@@ -77,7 +75,7 @@ static void meshcache_do(MeshCacheModifierData *mcmd,
Object *ob,
Mesh *mesh,
float (*vertexCos_Real)[3],
- int numVerts)
+ int verts_num)
{
const bool use_factor = mcmd->factor < 1.0f;
int influence_group_index;
@@ -87,7 +85,7 @@ static void meshcache_do(MeshCacheModifierData *mcmd,
float(*vertexCos_Store)[3] = (use_factor || influence_group_index != -1 ||
(mcmd->deform_mode == MOD_MESHCACHE_DEFORM_INTEGRATE)) ?
MEM_malloc_arrayN(
- numVerts, sizeof(*vertexCos_Store), __func__) :
+ verts_num, sizeof(*vertexCos_Store), __func__) :
NULL;
float(*vertexCos)[3] = vertexCos_Store ? vertexCos_Store : vertexCos_Real;
@@ -151,11 +149,11 @@ static void meshcache_do(MeshCacheModifierData *mcmd,
switch (mcmd->type) {
case MOD_MESHCACHE_TYPE_MDD:
ok = MOD_meshcache_read_mdd_times(
- filepath, vertexCos, numVerts, mcmd->interp, time, fps, mcmd->time_mode, &err_str);
+ filepath, vertexCos, verts_num, mcmd->interp, time, fps, mcmd->time_mode, &err_str);
break;
case MOD_MESHCACHE_TYPE_PC2:
ok = MOD_meshcache_read_pc2_times(
- filepath, vertexCos, numVerts, mcmd->interp, time, fps, mcmd->time_mode, &err_str);
+ filepath, vertexCos, verts_num, mcmd->interp, time, fps, mcmd->time_mode, &err_str);
break;
default:
ok = false;
@@ -171,7 +169,7 @@ static void meshcache_do(MeshCacheModifierData *mcmd,
if (UNLIKELY(ob->type != OB_MESH)) {
BKE_modifier_set_error(ob, &mcmd->modifier, "'Integrate' only valid for Mesh objects");
}
- else if (UNLIKELY(me->totvert != numVerts)) {
+ else if (UNLIKELY(me->totvert != verts_num)) {
BKE_modifier_set_error(ob, &mcmd->modifier, "'Integrate' original mesh vertex mismatch");
}
else if (UNLIKELY(me->totpoly == 0)) {
@@ -182,11 +180,11 @@ static void meshcache_do(MeshCacheModifierData *mcmd,
int i;
float(*vertexCos_Source)[3] = MEM_malloc_arrayN(
- numVerts, sizeof(*vertexCos_Source), __func__);
- float(*vertexCos_New)[3] = MEM_malloc_arrayN(numVerts, sizeof(*vertexCos_New), __func__);
+ verts_num, sizeof(*vertexCos_Source), __func__);
+ float(*vertexCos_New)[3] = MEM_malloc_arrayN(verts_num, sizeof(*vertexCos_New), __func__);
MVert *mv = me->mvert;
- for (i = 0; i < numVerts; i++, mv++) {
+ for (i = 0; i < verts_num; i++, mv++) {
copy_v3_v3(vertexCos_Source[i], mv->co);
}
@@ -204,7 +202,7 @@ static void meshcache_do(MeshCacheModifierData *mcmd,
);
/* write the corrected locations back into the result */
- memcpy(vertexCos, vertexCos_New, sizeof(*vertexCos) * numVerts);
+ memcpy(vertexCos, vertexCos_New, sizeof(*vertexCos) * verts_num);
MEM_freeN(vertexCos_Source);
MEM_freeN(vertexCos_New);
@@ -244,7 +242,7 @@ static void meshcache_do(MeshCacheModifierData *mcmd,
if (use_matrix) {
int i;
- for (i = 0; i < numVerts; i++) {
+ for (i = 0; i < verts_num; i++) {
mul_m3_v3(mat, vertexCos[i]);
}
}
@@ -260,7 +258,7 @@ static void meshcache_do(MeshCacheModifierData *mcmd,
mcmd->factor :
0.0f;
if (mesh->dvert != NULL) {
- for (int i = 0; i < numVerts; i++) {
+ for (int i = 0; i < verts_num; i++) {
/* For each vertex, compute its blending factor between the mesh cache (for `fac = 0`)
* and the former position of the vertex (for `fac = 1`). */
const MDeformVert *currentIndexDVert = dvert + i;
@@ -275,10 +273,10 @@ static void meshcache_do(MeshCacheModifierData *mcmd,
}
else if (use_factor) {
/* Influence_group_index is -1. */
- interp_vn_vn(*vertexCos_Real, *vertexCos_Store, mcmd->factor, numVerts * 3);
+ interp_vn_vn(*vertexCos_Real, *vertexCos_Store, mcmd->factor, verts_num * 3);
}
else {
- memcpy(vertexCos_Real, vertexCos_Store, sizeof(*vertexCos_Store) * numVerts);
+ memcpy(vertexCos_Real, vertexCos_Store, sizeof(*vertexCos_Store) * verts_num);
}
}
@@ -290,7 +288,7 @@ static void deformVerts(ModifierData *md,
const ModifierEvalContext *ctx,
Mesh *mesh,
float (*vertexCos)[3],
- int numVerts)
+ int verts_num)
{
MeshCacheModifierData *mcmd = (MeshCacheModifierData *)md;
Scene *scene = DEG_get_evaluated_scene(ctx->depsgraph);
@@ -299,9 +297,9 @@ static void deformVerts(ModifierData *md,
if (ctx->object->type == OB_MESH && mcmd->defgrp_name[0] != '\0') {
/* `mesh_src` is only needed for vertex groups. */
- mesh_src = MOD_deform_mesh_eval_get(ctx->object, NULL, mesh, NULL, numVerts, false, false);
+ mesh_src = MOD_deform_mesh_eval_get(ctx->object, NULL, mesh, NULL, verts_num, false, false);
}
- meshcache_do(mcmd, scene, ctx->object, mesh_src, vertexCos, numVerts);
+ meshcache_do(mcmd, scene, ctx->object, mesh_src, vertexCos, verts_num);
if (!ELEM(mesh_src, NULL, mesh)) {
BKE_id_free(NULL, mesh_src);
@@ -313,7 +311,7 @@ static void deformVertsEM(ModifierData *md,
struct BMEditMesh *editData,
Mesh *mesh,
float (*vertexCos)[3],
- int numVerts)
+ int verts_num)
{
MeshCacheModifierData *mcmd = (MeshCacheModifierData *)md;
Scene *scene = DEG_get_evaluated_scene(ctx->depsgraph);
@@ -322,13 +320,14 @@ static void deformVertsEM(ModifierData *md,
if (ctx->object->type == OB_MESH && mcmd->defgrp_name[0] != '\0') {
/* `mesh_src` is only needed for vertex groups. */
- mesh_src = MOD_deform_mesh_eval_get(ctx->object, editData, mesh, NULL, numVerts, false, false);
+ mesh_src = MOD_deform_mesh_eval_get(
+ ctx->object, editData, mesh, NULL, verts_num, false, false);
}
if (mesh_src != NULL) {
BKE_mesh_wrapper_ensure_mdata(mesh_src);
}
- meshcache_do(mcmd, scene, ctx->object, mesh_src, vertexCos, numVerts);
+ meshcache_do(mcmd, scene, ctx->object, mesh_src, vertexCos, verts_num);
if (!ELEM(mesh_src, NULL, mesh)) {
BKE_id_free(NULL, mesh_src);
diff --git a/source/blender/modifiers/intern/MOD_meshcache_mdd.c b/source/blender/modifiers/intern/MOD_meshcache_mdd.c
index 66b5f3ff9b2..67a01b1c8d5 100644
--- a/source/blender/modifiers/intern/MOD_meshcache_mdd.c
+++ b/source/blender/modifiers/intern/MOD_meshcache_mdd.c
@@ -96,22 +96,22 @@ static bool meshcache_read_mdd_range_from_time(FILE *fp,
return false;
}
- size_t num_frames_read = 0;
- size_t num_frames_expect = mdd_head.frame_tot;
+ size_t frames_num_read = 0;
+ size_t frames_num_expect = mdd_head.frame_tot;
errno = 0;
for (i = 0; i < mdd_head.frame_tot; i++) {
- num_frames_read += fread(&f_time, sizeof(float), 1, fp);
+ frames_num_read += fread(&f_time, sizeof(float), 1, fp);
#ifdef __LITTLE_ENDIAN__
BLI_endian_switch_float(&f_time);
#endif
if (f_time >= time) {
- num_frames_expect = i + 1;
+ frames_num_expect = i + 1;
break;
}
f_time_prev = f_time;
}
- if (num_frames_read != num_frames_expect) {
+ if (frames_num_read != frames_num_expect) {
*err_str = errno ? strerror(errno) : "Timestamp read failed";
return false;
}
@@ -160,14 +160,14 @@ bool MOD_meshcache_read_mdd_index(FILE *fp,
return false;
}
- size_t num_verts_read = 0;
+ size_t verts_read_num = 0;
errno = 0;
if (factor >= 1.0f) {
#if 1
float *vco = *vertexCos;
uint i;
for (i = mdd_head.verts_tot; i != 0; i--, vco += 3) {
- num_verts_read += fread(vco, sizeof(float[3]), 1, fp);
+ verts_read_num += fread(vco, sizeof(float[3]), 1, fp);
# ifdef __LITTLE_ENDIAN__
BLI_endian_switch_float(vco + 0);
@@ -192,7 +192,7 @@ bool MOD_meshcache_read_mdd_index(FILE *fp,
uint i;
for (i = mdd_head.verts_tot; i != 0; i--, vco += 3) {
float tvec[3];
- num_verts_read += fread(tvec, sizeof(float[3]), 1, fp);
+ verts_read_num += fread(tvec, sizeof(float[3]), 1, fp);
#ifdef __LITTLE_ENDIAN__
BLI_endian_switch_float(tvec + 0);
@@ -206,7 +206,7 @@ bool MOD_meshcache_read_mdd_index(FILE *fp,
}
}
- if (num_verts_read != mdd_head.verts_tot) {
+ if (verts_read_num != mdd_head.verts_tot) {
*err_str = errno ? strerror(errno) : "Vertex coordinate read failed";
return false;
}
diff --git a/source/blender/modifiers/intern/MOD_meshcache_pc2.c b/source/blender/modifiers/intern/MOD_meshcache_pc2.c
index 54ea27d0085..27fea20bb13 100644
--- a/source/blender/modifiers/intern/MOD_meshcache_pc2.c
+++ b/source/blender/modifiers/intern/MOD_meshcache_pc2.c
@@ -137,13 +137,13 @@ bool MOD_meshcache_read_pc2_index(FILE *fp,
return false;
}
- size_t num_verts_read = 0;
+ size_t verts_read_num = 0;
errno = 0;
if (factor >= 1.0f) {
float *vco = *vertexCos;
uint i;
for (i = pc2_head.verts_tot; i != 0; i--, vco += 3) {
- num_verts_read += fread(vco, sizeof(float[3]), 1, fp);
+ verts_read_num += fread(vco, sizeof(float[3]), 1, fp);
#ifdef __BIG_ENDIAN__
BLI_endian_switch_float(vco + 0);
@@ -158,7 +158,7 @@ bool MOD_meshcache_read_pc2_index(FILE *fp,
uint i;
for (i = pc2_head.verts_tot; i != 0; i--, vco += 3) {
float tvec[3];
- num_verts_read += fread(tvec, sizeof(float[3]), 1, fp);
+ verts_read_num += fread(tvec, sizeof(float[3]), 1, fp);
#ifdef __BIG_ENDIAN__
BLI_endian_switch_float(tvec + 0);
@@ -172,7 +172,7 @@ bool MOD_meshcache_read_pc2_index(FILE *fp,
}
}
- if (num_verts_read != pc2_head.verts_tot) {
+ if (verts_read_num != pc2_head.verts_tot) {
*err_str = errno ? strerror(errno) : "Vertex coordinate read failed";
return false;
}
diff --git a/source/blender/modifiers/intern/MOD_meshdeform.c b/source/blender/modifiers/intern/MOD_meshdeform.c
index f15cdfe0c4e..09e6819a2ae 100644
--- a/source/blender/modifiers/intern/MOD_meshdeform.c
+++ b/source/blender/modifiers/intern/MOD_meshdeform.c
@@ -222,7 +222,7 @@ static float meshdeform_dynamic_bind(MeshDeformModifierData *mmd, float (*dco)[3
cell = &mmd->dyngrid[a];
inf = mmd->dyninfluences + cell->offset;
- for (j = 0; j < cell->totinfluence; j++, inf++) {
+ for (j = 0; j < cell->influences_num; j++, inf++) {
cageco = dco[inf->vertex];
cageweight = weight * inf->weight;
#ifdef BLI_HAVE_SSE2
@@ -324,7 +324,7 @@ static void meshdeformModifier_do(ModifierData *md,
const ModifierEvalContext *ctx,
Mesh *mesh,
float (*vertexCos)[3],
- int numVerts)
+ const int verts_num)
{
MeshDeformModifierData *mmd = (MeshDeformModifierData *)md;
Object *ob = ctx->object;
@@ -333,7 +333,7 @@ static void meshdeformModifier_do(ModifierData *md,
MDeformVert *dvert = NULL;
float imat[4][4], cagemat[4][4], iobmat[4][4], icagemat[3][3], cmat[4][4];
float(*dco)[3] = NULL, (*bindcagecos)[3];
- int a, totvert, totcagevert, defgrp_index;
+ int a, cage_verts_num, defgrp_index;
MeshdeformUserdata data;
static int recursive_bind_sentinel = 0;
@@ -375,7 +375,7 @@ static void meshdeformModifier_do(ModifierData *md,
}
if (!recursive_bind_sentinel) {
recursive_bind_sentinel = 1;
- mmd->bindfunc(ob, mmd, cagemesh, (float *)vertexCos, numVerts, cagemat);
+ mmd->bindfunc(ob, mmd, cagemesh, (float *)vertexCos, verts_num, cagemat);
recursive_bind_sentinel = 0;
}
@@ -383,16 +383,15 @@ static void meshdeformModifier_do(ModifierData *md,
}
/* verify we have compatible weights */
- totvert = numVerts;
- totcagevert = BKE_mesh_wrapper_vert_len(cagemesh);
+ cage_verts_num = BKE_mesh_wrapper_vert_len(cagemesh);
- if (mmd->totvert != totvert) {
- BKE_modifier_set_error(ob, md, "Vertices changed from %d to %d", mmd->totvert, totvert);
+ if (mmd->verts_num != verts_num) {
+ BKE_modifier_set_error(ob, md, "Vertices changed from %d to %d", mmd->verts_num, verts_num);
goto finally;
}
- else if (mmd->totcagevert != totcagevert) {
+ else if (mmd->cage_verts_num != cage_verts_num) {
BKE_modifier_set_error(
- ob, md, "Cage vertices changed from %d to %d", mmd->totcagevert, totcagevert);
+ ob, md, "Cage vertices changed from %d to %d", mmd->cage_verts_num, cage_verts_num);
goto finally;
}
else if (mmd->bindcagecos == NULL) {
@@ -403,14 +402,14 @@ static void meshdeformModifier_do(ModifierData *md,
/* We allocate 1 element extra to make it possible to
* load the values to SSE registers, which are float4.
*/
- dco = MEM_calloc_arrayN((totcagevert + 1), sizeof(*dco), "MDefDco");
- zero_v3(dco[totcagevert]);
+ dco = MEM_calloc_arrayN((cage_verts_num + 1), sizeof(*dco), "MDefDco");
+ zero_v3(dco[cage_verts_num]);
/* setup deformation data */
- BKE_mesh_wrapper_vert_coords_copy(cagemesh, dco, totcagevert);
+ BKE_mesh_wrapper_vert_coords_copy(cagemesh, dco, cage_verts_num);
bindcagecos = (float(*)[3])mmd->bindcagecos;
- for (a = 0; a < totcagevert; a++) {
+ for (a = 0; a < cage_verts_num; a++) {
/* Get cage vertex in world-space with binding transform. */
float co[3];
mul_v3_m4v3(co, mmd->bindmat, dco[a]);
@@ -433,7 +432,7 @@ static void meshdeformModifier_do(ModifierData *md,
TaskParallelSettings settings;
BLI_parallel_range_settings_defaults(&settings);
settings.min_iter_per_thread = 16;
- BLI_task_parallel_range(0, totvert, &data, meshdeform_vert_task, &settings);
+ BLI_task_parallel_range(0, verts_num, &data, meshdeform_vert_task, &settings);
finally:
MEM_SAFE_FREE(dco);
@@ -443,13 +442,14 @@ static void deformVerts(ModifierData *md,
const ModifierEvalContext *ctx,
Mesh *mesh,
float (*vertexCos)[3],
- int numVerts)
+ int verts_num)
{
- Mesh *mesh_src = MOD_deform_mesh_eval_get(ctx->object, NULL, mesh, NULL, numVerts, false, false);
+ Mesh *mesh_src = MOD_deform_mesh_eval_get(
+ ctx->object, NULL, mesh, NULL, verts_num, false, false);
MOD_previous_vcos_store(md, vertexCos); /* if next modifier needs original vertices */
- meshdeformModifier_do(md, ctx, mesh_src, vertexCos, numVerts);
+ meshdeformModifier_do(md, ctx, mesh_src, vertexCos, verts_num);
if (!ELEM(mesh_src, NULL, mesh)) {
BKE_id_free(NULL, mesh_src);
@@ -461,17 +461,17 @@ static void deformVertsEM(ModifierData *md,
struct BMEditMesh *editData,
Mesh *mesh,
float (*vertexCos)[3],
- int numVerts)
+ int verts_num)
{
Mesh *mesh_src = MOD_deform_mesh_eval_get(
- ctx->object, editData, mesh, NULL, numVerts, false, false);
+ ctx->object, editData, mesh, NULL, verts_num, false, false);
/* TODO(Campbell): use edit-mode data only (remove this line). */
if (mesh_src != NULL) {
BKE_mesh_wrapper_ensure_mdata(mesh_src);
}
- meshdeformModifier_do(md, ctx, mesh_src, vertexCos, numVerts);
+ meshdeformModifier_do(md, ctx, mesh_src, vertexCos, verts_num);
if (!ELEM(mesh_src, NULL, mesh)) {
BKE_id_free(NULL, mesh_src);
@@ -484,42 +484,42 @@ void BKE_modifier_mdef_compact_influences(ModifierData *md)
{
MeshDeformModifierData *mmd = (MeshDeformModifierData *)md;
float weight, *weights, totweight;
- int totinfluence, totvert, totcagevert, a, b;
+ int influences_num, verts_num, cage_verts_num, a, b;
weights = mmd->bindweights;
if (!weights) {
return;
}
- totvert = mmd->totvert;
- totcagevert = mmd->totcagevert;
+ verts_num = mmd->verts_num;
+ cage_verts_num = mmd->cage_verts_num;
/* count number of influences above threshold */
- for (b = 0; b < totvert; b++) {
- for (a = 0; a < totcagevert; a++) {
- weight = weights[a + b * totcagevert];
+ for (b = 0; b < verts_num; b++) {
+ for (a = 0; a < cage_verts_num; a++) {
+ weight = weights[a + b * cage_verts_num];
if (weight > MESHDEFORM_MIN_INFLUENCE) {
- mmd->totinfluence++;
+ mmd->influences_num++;
}
}
}
/* allocate bind influences */
mmd->bindinfluences = MEM_calloc_arrayN(
- mmd->totinfluence, sizeof(MDefInfluence), "MDefBindInfluence");
- mmd->bindoffsets = MEM_calloc_arrayN((totvert + 1), sizeof(int), "MDefBindOffset");
+ mmd->influences_num, sizeof(MDefInfluence), "MDefBindInfluence");
+ mmd->bindoffsets = MEM_calloc_arrayN((verts_num + 1), sizeof(int), "MDefBindOffset");
/* write influences */
- totinfluence = 0;
+ influences_num = 0;
- for (b = 0; b < totvert; b++) {
- mmd->bindoffsets[b] = totinfluence;
+ for (b = 0; b < verts_num; b++) {
+ mmd->bindoffsets[b] = influences_num;
totweight = 0.0f;
/* sum total weight */
- for (a = 0; a < totcagevert; a++) {
- weight = weights[a + b * totcagevert];
+ for (a = 0; a < cage_verts_num; a++) {
+ weight = weights[a + b * cage_verts_num];
if (weight > MESHDEFORM_MIN_INFLUENCE) {
totweight += weight;
@@ -527,18 +527,18 @@ void BKE_modifier_mdef_compact_influences(ModifierData *md)
}
/* assign weights normalized */
- for (a = 0; a < totcagevert; a++) {
- weight = weights[a + b * totcagevert];
+ for (a = 0; a < cage_verts_num; a++) {
+ weight = weights[a + b * cage_verts_num];
if (weight > MESHDEFORM_MIN_INFLUENCE) {
- mmd->bindinfluences[totinfluence].weight = weight / totweight;
- mmd->bindinfluences[totinfluence].vertex = a;
- totinfluence++;
+ mmd->bindinfluences[influences_num].weight = weight / totweight;
+ mmd->bindinfluences[influences_num].vertex = a;
+ influences_num++;
}
}
}
- mmd->bindoffsets[b] = totinfluence;
+ mmd->bindoffsets[b] = influences_num;
/* free */
MEM_freeN(mmd->bindweights);
@@ -586,12 +586,12 @@ static void blendWrite(BlendWriter *writer, const ModifierData *md)
MeshDeformModifierData *mmd = (MeshDeformModifierData *)md;
int size = mmd->dyngridsize;
- BLO_write_struct_array(writer, MDefInfluence, mmd->totinfluence, mmd->bindinfluences);
- BLO_write_int32_array(writer, mmd->totvert + 1, mmd->bindoffsets);
- BLO_write_float3_array(writer, mmd->totcagevert, mmd->bindcagecos);
+ BLO_write_struct_array(writer, MDefInfluence, mmd->influences_num, mmd->bindinfluences);
+ BLO_write_int32_array(writer, mmd->verts_num + 1, mmd->bindoffsets);
+ BLO_write_float3_array(writer, mmd->cage_verts_num, mmd->bindcagecos);
BLO_write_struct_array(writer, MDefCell, size * size * size, mmd->dyngrid);
- BLO_write_struct_array(writer, MDefInfluence, mmd->totinfluence, mmd->dyninfluences);
- BLO_write_int32_array(writer, mmd->totvert, mmd->dynverts);
+ BLO_write_struct_array(writer, MDefInfluence, mmd->influences_num, mmd->dyninfluences);
+ BLO_write_int32_array(writer, mmd->verts_num, mmd->dynverts);
}
static void blendRead(BlendDataReader *reader, ModifierData *md)
@@ -599,15 +599,15 @@ static void blendRead(BlendDataReader *reader, ModifierData *md)
MeshDeformModifierData *mmd = (MeshDeformModifierData *)md;
BLO_read_data_address(reader, &mmd->bindinfluences);
- BLO_read_int32_array(reader, mmd->totvert + 1, &mmd->bindoffsets);
- BLO_read_float3_array(reader, mmd->totcagevert, &mmd->bindcagecos);
+ BLO_read_int32_array(reader, mmd->verts_num + 1, &mmd->bindoffsets);
+ BLO_read_float3_array(reader, mmd->cage_verts_num, &mmd->bindcagecos);
BLO_read_data_address(reader, &mmd->dyngrid);
BLO_read_data_address(reader, &mmd->dyninfluences);
- BLO_read_int32_array(reader, mmd->totvert, &mmd->dynverts);
+ BLO_read_int32_array(reader, mmd->verts_num, &mmd->dynverts);
/* Deprecated storage. */
- BLO_read_float_array(reader, mmd->totvert, &mmd->bindweights);
- BLO_read_float3_array(reader, mmd->totcagevert, &mmd->bindcos);
+ BLO_read_float_array(reader, mmd->verts_num, &mmd->bindweights);
+ BLO_read_float3_array(reader, mmd->cage_verts_num, &mmd->bindcos);
}
ModifierTypeInfo modifierType_MeshDeform = {
diff --git a/source/blender/modifiers/intern/MOD_meshsequencecache.cc b/source/blender/modifiers/intern/MOD_meshsequencecache.cc
index cfc5b17f37e..eadfdcf5baa 100644
--- a/source/blender/modifiers/intern/MOD_meshsequencecache.cc
+++ b/source/blender/modifiers/intern/MOD_meshsequencecache.cc
@@ -106,7 +106,7 @@ static bool isDisabled(const struct Scene *UNUSED(scene),
static Mesh *generate_bounding_box_mesh(Object *object, Mesh *org_mesh)
{
- BoundBox *bb = BKE_object_boundbox_get(object);
+ const BoundBox *bb = BKE_object_boundbox_get(object);
Mesh *result = BKE_mesh_new_nomain_from_template(org_mesh, 8, 0, 0, 24, 6);
MVert *mvert = result->mvert;
@@ -169,7 +169,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *
/* Do not process data if using a render procedural, return a box instead for displaying in the
* viewport. */
- if (BKE_cache_file_uses_render_procedural(cache_file, scene, DEG_get_mode(ctx->depsgraph))) {
+ if (BKE_cache_file_uses_render_procedural(cache_file, scene)) {
return generate_bounding_box_mesh(ctx->object, org_mesh);
}
@@ -263,15 +263,15 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *
#endif
}
-static bool dependsOnTime(Scene *scene, ModifierData *md, const int dag_eval_mode)
+static bool dependsOnTime(Scene *scene, ModifierData *md)
{
#if defined(WITH_USD) || defined(WITH_ALEMBIC)
MeshSeqCacheModifierData *mcmd = reinterpret_cast<MeshSeqCacheModifierData *>(md);
/* Do not evaluate animations if using the render engine procedural. */
return (mcmd->cache_file != nullptr) &&
- !BKE_cache_file_uses_render_procedural(mcmd->cache_file, scene, dag_eval_mode);
+ !BKE_cache_file_uses_render_procedural(mcmd->cache_file, scene);
#else
- UNUSED_VARS(scene, md, dag_eval_mode);
+ UNUSED_VARS(scene, md);
return false;
#endif
}
diff --git a/source/blender/modifiers/intern/MOD_multires.c b/source/blender/modifiers/intern/MOD_multires.c
index cc6f23073a3..a4c5ddac5c9 100644
--- a/source/blender/modifiers/intern/MOD_multires.c
+++ b/source/blender/modifiers/intern/MOD_multires.c
@@ -281,7 +281,7 @@ static void deformMatrices(ModifierData *md,
Mesh *mesh,
float (*vertex_cos)[3],
float (*deform_matrices)[3][3],
- int num_verts)
+ int verts_num)
{
#if !defined(WITH_OPENSUBDIV)
@@ -313,7 +313,7 @@ static void deformMatrices(ModifierData *md,
return;
}
BKE_subdiv_displacement_attach_from_multires(subdiv, mesh, mmd);
- BKE_subdiv_deform_coarse_vertices(subdiv, mesh, vertex_cos, num_verts);
+ BKE_subdiv_deform_coarse_vertices(subdiv, mesh, vertex_cos, verts_num);
if (subdiv != runtime_data->subdiv) {
BKE_subdiv_free(subdiv);
}
diff --git a/source/blender/modifiers/intern/MOD_nodes.cc b/source/blender/modifiers/intern/MOD_nodes.cc
index e94f8e50fec..7545bae43b3 100644
--- a/source/blender/modifiers/intern/MOD_nodes.cc
+++ b/source/blender/modifiers/intern/MOD_nodes.cc
@@ -36,6 +36,7 @@
#include "BKE_attribute_math.hh"
#include "BKE_customdata.h"
+#include "BKE_geometry_fields.hh"
#include "BKE_geometry_set_instances.hh"
#include "BKE_global.h"
#include "BKE_idprop.h"
@@ -315,9 +316,7 @@ static bool check_tree_for_time_node(const bNodeTree &tree,
return false;
}
-static bool dependsOnTime(struct Scene *UNUSED(scene),
- ModifierData *md,
- const int UNUSED(dag_eval_mode))
+static bool dependsOnTime(struct Scene *UNUSED(scene), ModifierData *md)
{
const NodesModifierData *nmd = reinterpret_cast<NodesModifierData *>(md);
const bNodeTree *tree = nmd->node_group;
@@ -732,33 +731,6 @@ void MOD_nodes_update_interface(Object *object, NodesModifierData *nmd)
DEG_id_tag_update(&object->id, ID_RECALC_GEOMETRY);
}
-void MOD_nodes_init(Main *bmain, NodesModifierData *nmd)
-{
- bNodeTree *ntree = ntreeAddTree(bmain, "Geometry Nodes", ntreeType_Geometry->idname);
- nmd->node_group = ntree;
-
- ntreeAddSocketInterface(ntree, SOCK_IN, "NodeSocketGeometry", "Geometry");
- ntreeAddSocketInterface(ntree, SOCK_OUT, "NodeSocketGeometry", "Geometry");
-
- bNode *group_input_node = nodeAddStaticNode(nullptr, ntree, NODE_GROUP_INPUT);
- bNode *group_output_node = nodeAddStaticNode(nullptr, ntree, NODE_GROUP_OUTPUT);
-
- nodeSetSelected(group_input_node, false);
- nodeSetSelected(group_output_node, false);
-
- group_input_node->locx = -200 - group_input_node->width;
- group_output_node->locx = 200;
- group_output_node->flag |= NODE_DO_OUTPUT;
-
- nodeAddLink(ntree,
- group_output_node,
- (bNodeSocket *)group_output_node->inputs.first,
- group_input_node,
- (bNodeSocket *)group_input_node->outputs.first);
-
- BKE_ntree_update_main_tree(bmain, ntree, nullptr);
-}
-
static void initialize_group_input(NodesModifierData &nmd,
const OutputSocketRef &socket,
void *r_value)
diff --git a/source/blender/modifiers/intern/MOD_nodes_evaluator.cc b/source/blender/modifiers/intern/MOD_nodes_evaluator.cc
index 8e5f9dc429f..68207d84015 100644
--- a/source/blender/modifiers/intern/MOD_nodes_evaluator.cc
+++ b/source/blender/modifiers/intern/MOD_nodes_evaluator.cc
@@ -1662,7 +1662,7 @@ class GeometryNodesEvaluator {
void construct_default_value(const CPPType &type, void *r_value)
{
- type.copy_construct(type.default_value(), r_value);
+ type.value_initialize(r_value);
}
NodeState &get_node_state(const DNode node)
@@ -1915,7 +1915,7 @@ void NodeParamsProvider::set_default_remaining_outputs()
const CPPType *type = get_socket_cpp_type(socket);
BLI_assert(type != nullptr);
void *buffer = allocator.allocate(type->size(), type->alignment());
- type->copy_construct(type->default_value(), buffer);
+ type->value_initialize(buffer);
evaluator_.forward_output(socket, {type, buffer}, run_state_);
output_state.has_been_computed = true;
}
diff --git a/source/blender/modifiers/intern/MOD_normal_edit.c b/source/blender/modifiers/intern/MOD_normal_edit.c
index 94b35c42247..fe05f48a868 100644
--- a/source/blender/modifiers/intern/MOD_normal_edit.c
+++ b/source/blender/modifiers/intern/MOD_normal_edit.c
@@ -43,7 +43,7 @@ static void generate_vert_coordinates(Mesh *mesh,
Object *ob,
Object *ob_center,
const float offset[3],
- const int num_verts,
+ const int verts_num,
float (*r_cos)[3],
float r_size[3])
{
@@ -108,7 +108,7 @@ static void generate_vert_coordinates(Mesh *mesh,
/* Else, no need to change coordinates! */
if (do_diff) {
- int i = num_verts;
+ int i = verts_num;
while (i--) {
add_v3_v3(r_cos[i], diff);
}
@@ -122,11 +122,11 @@ static void mix_normals(const float mix_factor,
const bool use_invert_vgroup,
const float mix_limit,
const short mix_mode,
- const int num_verts,
+ const int verts_num,
MLoop *mloop,
float (*nos_old)[3],
float (*nos_new)[3],
- const int num_loops)
+ const int loops_num)
{
/* Mix with org normals... */
float *facs = NULL, *wfac;
@@ -134,12 +134,12 @@ static void mix_normals(const float mix_factor,
int i;
if (dvert) {
- facs = MEM_malloc_arrayN((size_t)num_loops, sizeof(*facs), __func__);
+ facs = MEM_malloc_arrayN((size_t)loops_num, sizeof(*facs), __func__);
BKE_defvert_extract_vgroup_to_loopweights(
- dvert, defgrp_index, num_verts, mloop, num_loops, facs, use_invert_vgroup);
+ dvert, defgrp_index, verts_num, mloop, loops_num, facs, use_invert_vgroup);
}
- for (i = num_loops, no_new = nos_new, no_old = nos_old, wfac = facs; i--;
+ for (i = loops_num, no_new = nos_new, no_old = nos_old, wfac = facs; i--;
no_new++, no_old++, wfac++) {
const float fac = facs ? *wfac * mix_factor : mix_factor;
@@ -177,14 +177,14 @@ static bool polygons_check_flip(MLoop *mloop,
CustomData *ldata,
MPoly *mpoly,
float (*polynors)[3],
- const int num_polys)
+ const int polys_num)
{
MPoly *mp;
MDisps *mdisp = CustomData_get_layer(ldata, CD_MDISPS);
int i;
bool flipped = false;
- for (i = 0, mp = mpoly; i < num_polys; i++, mp++) {
+ for (i = 0, mp = mpoly; i < polys_num; i++, mp++) {
float norsum[3] = {0.0f};
float(*no)[3];
int j;
@@ -222,26 +222,26 @@ static void normalEditModifier_do_radial(NormalEditModifierData *enmd,
const int defgrp_index,
const bool use_invert_vgroup,
MVert *mvert,
- const int num_verts,
+ const int verts_num,
MEdge *medge,
- const int num_edges,
+ const int edges_num,
MLoop *mloop,
- const int num_loops,
+ const int loops_num,
MPoly *mpoly,
- const int num_polys)
+ const int polys_num)
{
Object *ob_target = enmd->target;
const bool do_polynors_fix = (enmd->flag & MOD_NORMALEDIT_NO_POLYNORS_FIX) == 0;
int i;
- float(*cos)[3] = MEM_malloc_arrayN((size_t)num_verts, sizeof(*cos), __func__);
- float(*nos)[3] = MEM_malloc_arrayN((size_t)num_loops, sizeof(*nos), __func__);
+ float(*cos)[3] = MEM_malloc_arrayN((size_t)verts_num, sizeof(*cos), __func__);
+ float(*nos)[3] = MEM_malloc_arrayN((size_t)loops_num, sizeof(*nos), __func__);
float size[3];
- BLI_bitmap *done_verts = BLI_BITMAP_NEW((size_t)num_verts, __func__);
+ BLI_bitmap *done_verts = BLI_BITMAP_NEW((size_t)verts_num, __func__);
- generate_vert_coordinates(mesh, ob, ob_target, enmd->offset, num_verts, cos, size);
+ generate_vert_coordinates(mesh, ob, ob_target, enmd->offset, verts_num, cos, size);
/**
* size gives us our spheroid coefficients `(A, B, C)`.
@@ -283,7 +283,7 @@ static void normalEditModifier_do_radial(NormalEditModifierData *enmd,
float(*no)[3];
/* We reuse cos to now store the ellipsoid-normal of the verts! */
- for (i = num_loops, ml = mloop, no = nos; i--; ml++, no++) {
+ for (i = loops_num, ml = mloop, no = nos; i--; ml++, no++) {
const int vidx = ml->v;
float *co = cos[vidx];
@@ -313,31 +313,31 @@ static void normalEditModifier_do_radial(NormalEditModifierData *enmd,
use_invert_vgroup,
mix_limit,
mix_mode,
- num_verts,
+ verts_num,
mloop,
loopnors,
nos,
- num_loops);
+ loops_num);
}
if (do_polynors_fix &&
polygons_check_flip(
- mloop, nos, &mesh->ldata, mpoly, BKE_mesh_poly_normals_for_write(mesh), num_polys)) {
+ mloop, nos, &mesh->ldata, mpoly, BKE_mesh_poly_normals_for_write(mesh), polys_num)) {
/* We need to recompute vertex normals! */
BKE_mesh_normals_tag_dirty(mesh);
}
BKE_mesh_normals_loop_custom_set(mvert,
BKE_mesh_vertex_normals_ensure(mesh),
- num_verts,
+ verts_num,
medge,
- num_edges,
+ edges_num,
mloop,
nos,
- num_loops,
+ loops_num,
mpoly,
polynors,
- num_polys,
+ polys_num,
clnors);
MEM_freeN(cos);
@@ -359,20 +359,20 @@ static void normalEditModifier_do_directional(NormalEditModifierData *enmd,
const int defgrp_index,
const bool use_invert_vgroup,
MVert *mvert,
- const int num_verts,
+ const int verts_num,
MEdge *medge,
- const int num_edges,
+ const int edges_num,
MLoop *mloop,
- const int num_loops,
+ const int loops_num,
MPoly *mpoly,
- const int num_polys)
+ const int polys_num)
{
Object *ob_target = enmd->target;
const bool do_polynors_fix = (enmd->flag & MOD_NORMALEDIT_NO_POLYNORS_FIX) == 0;
const bool use_parallel_normals = (enmd->flag & MOD_NORMALEDIT_USE_DIRECTION_PARALLEL) != 0;
- float(*nos)[3] = MEM_malloc_arrayN((size_t)num_loops, sizeof(*nos), __func__);
+ float(*nos)[3] = MEM_malloc_arrayN((size_t)loops_num, sizeof(*nos), __func__);
float target_co[3];
int i;
@@ -390,20 +390,20 @@ static void normalEditModifier_do_directional(NormalEditModifierData *enmd,
sub_v3_v3v3(no, target_co, enmd->offset);
normalize_v3(no);
- for (i = num_loops; i--;) {
+ for (i = loops_num; i--;) {
copy_v3_v3(nos[i], no);
}
}
else {
- float(*cos)[3] = MEM_malloc_arrayN((size_t)num_verts, sizeof(*cos), __func__);
- generate_vert_coordinates(mesh, ob, ob_target, NULL, num_verts, cos, NULL);
+ float(*cos)[3] = MEM_malloc_arrayN((size_t)verts_num, sizeof(*cos), __func__);
+ generate_vert_coordinates(mesh, ob, ob_target, NULL, verts_num, cos, NULL);
- BLI_bitmap *done_verts = BLI_BITMAP_NEW((size_t)num_verts, __func__);
+ BLI_bitmap *done_verts = BLI_BITMAP_NEW((size_t)verts_num, __func__);
MLoop *ml;
float(*no)[3];
/* We reuse cos to now store the 'to target' normal of the verts! */
- for (i = num_loops, no = nos, ml = mloop; i--; no++, ml++) {
+ for (i = loops_num, no = nos, ml = mloop; i--; no++, ml++) {
const int vidx = ml->v;
float *co = cos[vidx];
@@ -428,30 +428,30 @@ static void normalEditModifier_do_directional(NormalEditModifierData *enmd,
use_invert_vgroup,
mix_limit,
mix_mode,
- num_verts,
+ verts_num,
mloop,
loopnors,
nos,
- num_loops);
+ loops_num);
}
if (do_polynors_fix &&
polygons_check_flip(
- mloop, nos, &mesh->ldata, mpoly, BKE_mesh_poly_normals_for_write(mesh), num_polys)) {
+ mloop, nos, &mesh->ldata, mpoly, BKE_mesh_poly_normals_for_write(mesh), polys_num)) {
BKE_mesh_normals_tag_dirty(mesh);
}
BKE_mesh_normals_loop_custom_set(mvert,
BKE_mesh_vertex_normals_ensure(mesh),
- num_verts,
+ verts_num,
medge,
- num_edges,
+ edges_num,
mloop,
nos,
- num_loops,
+ loops_num,
mpoly,
polynors,
- num_polys,
+ polys_num,
clnors);
MEM_freeN(nos);
@@ -519,10 +519,10 @@ static Mesh *normalEditModifier_do(NormalEditModifierData *enmd,
result = mesh;
}
- const int num_verts = result->totvert;
- const int num_edges = result->totedge;
- const int num_loops = result->totloop;
- const int num_polys = result->totpoly;
+ const int verts_num = result->totvert;
+ const int edges_num = result->totedge;
+ const int loops_num = result->totloop;
+ const int polys_num = result->totpoly;
MVert *mvert = result->mvert;
MEdge *medge = result->medge;
MLoop *mloop = result->mloop;
@@ -541,20 +541,20 @@ static Mesh *normalEditModifier_do(NormalEditModifierData *enmd,
clnors = CustomData_get_layer(ldata, CD_CUSTOMLOOPNORMAL);
if (use_current_clnors) {
- clnors = CustomData_duplicate_referenced_layer(ldata, CD_CUSTOMLOOPNORMAL, num_loops);
- loopnors = MEM_malloc_arrayN((size_t)num_loops, sizeof(*loopnors), __func__);
+ clnors = CustomData_duplicate_referenced_layer(ldata, CD_CUSTOMLOOPNORMAL, loops_num);
+ loopnors = MEM_malloc_arrayN((size_t)loops_num, sizeof(*loopnors), __func__);
BKE_mesh_normals_loop_split(mvert,
vert_normals,
- num_verts,
+ verts_num,
medge,
- num_edges,
+ edges_num,
mloop,
loopnors,
- num_loops,
+ loops_num,
mpoly,
poly_normals,
- num_polys,
+ polys_num,
true,
result->smoothresh,
NULL,
@@ -563,7 +563,7 @@ static Mesh *normalEditModifier_do(NormalEditModifierData *enmd,
}
if (clnors == NULL) {
- clnors = CustomData_add_layer(ldata, CD_CUSTOMLOOPNORMAL, CD_CALLOC, NULL, num_loops);
+ clnors = CustomData_add_layer(ldata, CD_CUSTOMLOOPNORMAL, CD_CALLOC, NULL, loops_num);
}
MOD_get_vgroup(ob, result, enmd->defgrp_name, &dvert, &defgrp_index);
@@ -583,13 +583,13 @@ static Mesh *normalEditModifier_do(NormalEditModifierData *enmd,
defgrp_index,
use_invert_vgroup,
mvert,
- num_verts,
+ verts_num,
medge,
- num_edges,
+ edges_num,
mloop,
- num_loops,
+ loops_num,
mpoly,
- num_polys);
+ polys_num);
}
else if (enmd->mode == MOD_NORMALEDIT_MODE_DIRECTIONAL) {
normalEditModifier_do_directional(enmd,
@@ -606,13 +606,13 @@ static Mesh *normalEditModifier_do(NormalEditModifierData *enmd,
defgrp_index,
use_invert_vgroup,
mvert,
- num_verts,
+ verts_num,
medge,
- num_edges,
+ edges_num,
mloop,
- num_loops,
+ loops_num,
mpoly,
- num_polys);
+ polys_num);
}
MEM_SAFE_FREE(loopnors);
diff --git a/source/blender/modifiers/intern/MOD_ocean.c b/source/blender/modifiers/intern/MOD_ocean.c
index c1423347413..6ded702ceda 100644
--- a/source/blender/modifiers/intern/MOD_ocean.c
+++ b/source/blender/modifiers/intern/MOD_ocean.c
@@ -249,8 +249,8 @@ static Mesh *generate_ocean_geometry(OceanModifierData *omd, Mesh *mesh_orig, co
GenerateOceanGeometryData gogd;
- int num_verts;
- int num_polys;
+ int verts_num;
+ int polys_num;
const bool use_threading = resolution > 4;
@@ -259,8 +259,8 @@ static Mesh *generate_ocean_geometry(OceanModifierData *omd, Mesh *mesh_orig, co
gogd.res_x = gogd.rx * omd->repeat_x;
gogd.res_y = gogd.ry * omd->repeat_y;
- num_verts = (gogd.res_x + 1) * (gogd.res_y + 1);
- num_polys = gogd.res_x * gogd.res_y;
+ verts_num = (gogd.res_x + 1) * (gogd.res_y + 1);
+ polys_num = gogd.res_x * gogd.res_y;
gogd.sx = omd->size * omd->spatial_size;
gogd.sy = omd->size * omd->spatial_size;
@@ -270,7 +270,7 @@ static Mesh *generate_ocean_geometry(OceanModifierData *omd, Mesh *mesh_orig, co
gogd.sx /= gogd.rx;
gogd.sy /= gogd.ry;
- result = BKE_mesh_new_nomain(num_verts, 0, 0, num_polys * 4, num_polys);
+ result = BKE_mesh_new_nomain(verts_num, 0, 0, polys_num * 4, polys_num);
BKE_mesh_copy_parameters_for_eval(result, mesh_orig);
gogd.mverts = result->mvert;
@@ -292,7 +292,7 @@ static Mesh *generate_ocean_geometry(OceanModifierData *omd, Mesh *mesh_orig, co
/* add uvs */
if (CustomData_number_of_layers(&result->ldata, CD_MLOOPUV) < MAX_MTFACE) {
gogd.mloopuvs = CustomData_add_layer(
- &result->ldata, CD_MLOOPUV, CD_CALLOC, NULL, num_polys * 4);
+ &result->ldata, CD_MLOOPUV, CD_CALLOC, NULL, polys_num * 4);
if (gogd.mloopuvs) { /* unlikely to fail */
gogd.ix = 1.0 / gogd.rx;
@@ -377,23 +377,23 @@ static Mesh *doOcean(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mes
if (omd->flag & MOD_OCEAN_GENERATE_FOAM) {
if (CustomData_number_of_layers(&result->ldata, CD_MLOOPCOL) < MAX_MCOL) {
- const int num_polys = result->totpoly;
- const int num_loops = result->totloop;
+ const int polys_num = result->totpoly;
+ const int loops_num = result->totloop;
MLoop *mloops = result->mloop;
MLoopCol *mloopcols = CustomData_add_layer_named(
- &result->ldata, CD_MLOOPCOL, CD_CALLOC, NULL, num_loops, omd->foamlayername);
+ &result->ldata, CD_MLOOPCOL, CD_CALLOC, NULL, loops_num, omd->foamlayername);
MLoopCol *mloopcols_spray = NULL;
if (omd->flag & MOD_OCEAN_GENERATE_SPRAY) {
mloopcols_spray = CustomData_add_layer_named(
- &result->ldata, CD_MLOOPCOL, CD_CALLOC, NULL, num_loops, omd->spraylayername);
+ &result->ldata, CD_MLOOPCOL, CD_CALLOC, NULL, loops_num, omd->spraylayername);
}
if (mloopcols) { /* unlikely to fail */
MPoly *mpolys = result->mpoly;
MPoly *mp;
- for (i = 0, mp = mpolys; i < num_polys; i++, mp++) {
+ for (i = 0, mp = mpolys; i < polys_num; i++, mp++) {
MLoop *ml = &mloops[mp->loopstart];
MLoopCol *mlcol = &mloopcols[mp->loopstart];
@@ -449,9 +449,9 @@ static Mesh *doOcean(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mes
/* NOTE: tried to parallelized that one and previous foam loop,
* but gives 20% slower results... odd. */
{
- const int num_verts = result->totvert;
+ const int verts_num = result->totvert;
- for (i = 0; i < num_verts; i++) {
+ for (i = 0; i < verts_num; i++) {
float *vco = mverts[i].co;
const float u = OCEAN_CO(size_co_inv, vco[0]);
const float v = OCEAN_CO(size_co_inv, vco[1]);
diff --git a/source/blender/modifiers/intern/MOD_particlesystem.c b/source/blender/modifiers/intern/MOD_particlesystem.c
index 6c2651bae1f..7df7ba7c1db 100644
--- a/source/blender/modifiers/intern/MOD_particlesystem.c
+++ b/source/blender/modifiers/intern/MOD_particlesystem.c
@@ -100,7 +100,7 @@ static void deformVerts(ModifierData *md,
const ModifierEvalContext *ctx,
Mesh *mesh,
float (*vertexCos)[3],
- int numVerts)
+ int verts_num)
{
Mesh *mesh_src = mesh;
ParticleSystemModifierData *psmd = (ParticleSystemModifierData *)md;
@@ -118,7 +118,8 @@ static void deformVerts(ModifierData *md,
}
if (mesh_src == NULL) {
- mesh_src = MOD_deform_mesh_eval_get(ctx->object, NULL, NULL, vertexCos, numVerts, false, true);
+ mesh_src = MOD_deform_mesh_eval_get(
+ ctx->object, NULL, NULL, vertexCos, verts_num, false, true);
if (mesh_src == NULL) {
return;
}
@@ -235,7 +236,7 @@ static void deformVertsEM(ModifierData *md,
BMEditMesh *editData,
Mesh *mesh,
float (*vertexCos)[3],
- int numVerts)
+ int verts_num)
{
const bool do_temp_mesh = (mesh == NULL);
if (do_temp_mesh) {
@@ -243,7 +244,7 @@ static void deformVertsEM(ModifierData *md,
BM_mesh_bm_to_me(NULL, editData->bm, mesh, &((BMeshToMeshParams){0}));
}
- deformVerts(md, ob, mesh, vertexCos, numVerts);
+ deformVerts(md, ob, mesh, vertexCos, verts_num);
if (derivedData) {
BKE_id_free(NULL, mesh);
diff --git a/source/blender/modifiers/intern/MOD_shapekey.c b/source/blender/modifiers/intern/MOD_shapekey.c
index 5d6be527b2d..6953e89dfc2 100644
--- a/source/blender/modifiers/intern/MOD_shapekey.c
+++ b/source/blender/modifiers/intern/MOD_shapekey.c
@@ -27,14 +27,14 @@ static void deformVerts(ModifierData *UNUSED(md),
const ModifierEvalContext *ctx,
Mesh *UNUSED(mesh),
float (*vertexCos)[3],
- int numVerts)
+ int verts_num)
{
Key *key = BKE_key_from_object(ctx->object);
if (key && key->block.first) {
int deformedVerts_tot;
BKE_key_evaluate_object_ex(
- ctx->object, &deformedVerts_tot, (float *)vertexCos, sizeof(*vertexCos) * numVerts);
+ ctx->object, &deformedVerts_tot, (float *)vertexCos, sizeof(*vertexCos) * verts_num);
}
}
@@ -43,7 +43,7 @@ static void deformMatrices(ModifierData *md,
Mesh *mesh,
float (*vertexCos)[3],
float (*defMats)[3][3],
- int numVerts)
+ int verts_num)
{
Key *key = BKE_key_from_object(ctx->object);
KeyBlock *kb = BKE_keyblock_from_object(ctx->object);
@@ -51,7 +51,7 @@ static void deformMatrices(ModifierData *md,
(void)vertexCos; /* unused */
- if (kb && kb->totelem == numVerts && kb != key->refkey) {
+ if (kb && kb->totelem == verts_num && kb != key->refkey) {
int a;
if (ctx->object->shapeflag & OB_SHAPE_LOCK) {
@@ -61,12 +61,12 @@ static void deformMatrices(ModifierData *md,
scale_m3_fl(scale, kb->curval);
}
- for (a = 0; a < numVerts; a++) {
+ for (a = 0; a < verts_num; a++) {
copy_m3_m3(defMats[a], scale);
}
}
- deformVerts(md, ctx, mesh, vertexCos, numVerts);
+ deformVerts(md, ctx, mesh, vertexCos, verts_num);
}
static void deformVertsEM(ModifierData *md,
@@ -74,12 +74,12 @@ static void deformVertsEM(ModifierData *md,
struct BMEditMesh *UNUSED(editData),
Mesh *mesh,
float (*vertexCos)[3],
- int numVerts)
+ int verts_num)
{
Key *key = BKE_key_from_object(ctx->object);
if (key && key->type == KEY_RELATIVE) {
- deformVerts(md, ctx, mesh, vertexCos, numVerts);
+ deformVerts(md, ctx, mesh, vertexCos, verts_num);
}
}
@@ -89,7 +89,7 @@ static void deformMatricesEM(ModifierData *UNUSED(md),
Mesh *UNUSED(mesh),
float (*vertexCos)[3],
float (*defMats)[3][3],
- int numVerts)
+ int verts_num)
{
Key *key = BKE_key_from_object(ctx->object);
KeyBlock *kb = BKE_keyblock_from_object(ctx->object);
@@ -97,11 +97,11 @@ static void deformMatricesEM(ModifierData *UNUSED(md),
(void)vertexCos; /* unused */
- if (kb && kb->totelem == numVerts && kb != key->refkey) {
+ if (kb && kb->totelem == verts_num && kb != key->refkey) {
int a;
scale_m3_fl(scale, kb->curval);
- for (a = 0; a < numVerts; a++) {
+ for (a = 0; a < verts_num; a++) {
copy_m3_m3(defMats[a], scale);
}
}
diff --git a/source/blender/modifiers/intern/MOD_shrinkwrap.c b/source/blender/modifiers/intern/MOD_shrinkwrap.c
index 21f8f90585d..488df3d6f4c 100644
--- a/source/blender/modifiers/intern/MOD_shrinkwrap.c
+++ b/source/blender/modifiers/intern/MOD_shrinkwrap.c
@@ -98,7 +98,7 @@ static void deformVerts(ModifierData *md,
const ModifierEvalContext *ctx,
Mesh *mesh,
float (*vertexCos)[3],
- int numVerts)
+ int verts_num)
{
ShrinkwrapModifierData *swmd = (ShrinkwrapModifierData *)md;
struct Scene *scene = DEG_get_evaluated_scene(ctx->depsgraph);
@@ -108,7 +108,7 @@ static void deformVerts(ModifierData *md,
(swmd->shrinkType == MOD_SHRINKWRAP_PROJECT)) {
/* mesh_src is needed for vgroups, but also used as ShrinkwrapCalcData.vert when projecting.
* Avoid time-consuming mesh conversion for curves when not projecting. */
- mesh_src = MOD_deform_mesh_eval_get(ctx->object, NULL, mesh, NULL, numVerts, false, false);
+ mesh_src = MOD_deform_mesh_eval_get(ctx->object, NULL, mesh, NULL, verts_num, false, false);
}
struct MDeformVert *dvert = NULL;
@@ -116,7 +116,7 @@ static void deformVerts(ModifierData *md,
MOD_get_vgroup(ctx->object, mesh_src, swmd->vgroup_name, &dvert, &defgrp_index);
shrinkwrapModifier_deform(
- swmd, ctx, scene, ctx->object, mesh_src, dvert, defgrp_index, vertexCos, numVerts);
+ swmd, ctx, scene, ctx->object, mesh_src, dvert, defgrp_index, vertexCos, verts_num);
if (!ELEM(mesh_src, NULL, mesh)) {
BKE_id_free(NULL, mesh_src);
@@ -128,14 +128,15 @@ static void deformVertsEM(ModifierData *md,
struct BMEditMesh *editData,
Mesh *mesh,
float (*vertexCos)[3],
- int numVerts)
+ int verts_num)
{
ShrinkwrapModifierData *swmd = (ShrinkwrapModifierData *)md;
struct Scene *scene = DEG_get_evaluated_scene(ctx->depsgraph);
Mesh *mesh_src = NULL;
if ((swmd->vgroup_name[0] != '\0') || (swmd->shrinkType == MOD_SHRINKWRAP_PROJECT)) {
- mesh_src = MOD_deform_mesh_eval_get(ctx->object, editData, mesh, NULL, numVerts, false, false);
+ mesh_src = MOD_deform_mesh_eval_get(
+ ctx->object, editData, mesh, NULL, verts_num, false, false);
}
/* TODO(Campbell): use edit-mode data only (remove this line). */
@@ -150,7 +151,7 @@ static void deformVertsEM(ModifierData *md,
}
shrinkwrapModifier_deform(
- swmd, ctx, scene, ctx->object, mesh_src, dvert, defgrp_index, vertexCos, numVerts);
+ swmd, ctx, scene, ctx->object, mesh_src, dvert, defgrp_index, vertexCos, verts_num);
if (!ELEM(mesh_src, NULL, mesh)) {
BKE_id_free(NULL, mesh_src);
diff --git a/source/blender/modifiers/intern/MOD_simpledeform.c b/source/blender/modifiers/intern/MOD_simpledeform.c
index 4fbef6f54ae..e3c7f1c423b 100644
--- a/source/blender/modifiers/intern/MOD_simpledeform.c
+++ b/source/blender/modifiers/intern/MOD_simpledeform.c
@@ -288,7 +288,7 @@ static void SimpleDeformModifier_do(SimpleDeformModifierData *smd,
struct Object *ob,
struct Mesh *mesh,
float (*vertexCos)[3],
- int numVerts)
+ int verts_num)
{
int i;
float smd_limit[2], smd_factor;
@@ -355,7 +355,7 @@ static void SimpleDeformModifier_do(SimpleDeformModifierData *smd,
float lower = FLT_MAX;
float upper = -FLT_MAX;
- for (i = 0; i < numVerts; i++) {
+ for (i = 0; i < verts_num; i++) {
float tmp[3];
copy_v3_v3(tmp, vertexCos[i]);
@@ -401,7 +401,7 @@ static void SimpleDeformModifier_do(SimpleDeformModifierData *smd,
/* Do deformation. */
TaskParallelSettings settings;
BLI_parallel_range_settings_defaults(&settings);
- BLI_task_parallel_range(0, numVerts, (void *)&deform_pool_data, simple_helper, &settings);
+ BLI_task_parallel_range(0, verts_num, (void *)&deform_pool_data, simple_helper, &settings);
}
/* SimpleDeform */
@@ -446,17 +446,17 @@ static void deformVerts(ModifierData *md,
const ModifierEvalContext *ctx,
struct Mesh *mesh,
float (*vertexCos)[3],
- int numVerts)
+ int verts_num)
{
SimpleDeformModifierData *sdmd = (SimpleDeformModifierData *)md;
Mesh *mesh_src = NULL;
if (ctx->object->type == OB_MESH && sdmd->vgroup_name[0] != '\0') {
/* mesh_src is only needed for vgroups. */
- mesh_src = MOD_deform_mesh_eval_get(ctx->object, NULL, mesh, NULL, numVerts, false, false);
+ mesh_src = MOD_deform_mesh_eval_get(ctx->object, NULL, mesh, NULL, verts_num, false, false);
}
- SimpleDeformModifier_do(sdmd, ctx, ctx->object, mesh_src, vertexCos, numVerts);
+ SimpleDeformModifier_do(sdmd, ctx, ctx->object, mesh_src, vertexCos, verts_num);
if (!ELEM(mesh_src, NULL, mesh)) {
BKE_id_free(NULL, mesh_src);
@@ -468,14 +468,15 @@ static void deformVertsEM(ModifierData *md,
struct BMEditMesh *editData,
struct Mesh *mesh,
float (*vertexCos)[3],
- int numVerts)
+ int verts_num)
{
SimpleDeformModifierData *sdmd = (SimpleDeformModifierData *)md;
Mesh *mesh_src = NULL;
if (ctx->object->type == OB_MESH && sdmd->vgroup_name[0] != '\0') {
/* mesh_src is only needed for vgroups. */
- mesh_src = MOD_deform_mesh_eval_get(ctx->object, editData, mesh, NULL, numVerts, false, false);
+ mesh_src = MOD_deform_mesh_eval_get(
+ ctx->object, editData, mesh, NULL, verts_num, false, false);
}
/* TODO(Campbell): use edit-mode data only (remove this line). */
@@ -483,7 +484,7 @@ static void deformVertsEM(ModifierData *md,
BKE_mesh_wrapper_ensure_mdata(mesh_src);
}
- SimpleDeformModifier_do(sdmd, ctx, ctx->object, mesh_src, vertexCos, numVerts);
+ SimpleDeformModifier_do(sdmd, ctx, ctx->object, mesh_src, vertexCos, verts_num);
if (!ELEM(mesh_src, NULL, mesh)) {
BKE_id_free(NULL, mesh_src);
diff --git a/source/blender/modifiers/intern/MOD_skin.c b/source/blender/modifiers/intern/MOD_skin.c
index 6ab6dc5d4c8..b950578ff1b 100644
--- a/source/blender/modifiers/intern/MOD_skin.c
+++ b/source/blender/modifiers/intern/MOD_skin.c
@@ -649,14 +649,14 @@ static void connection_node_frames(int v,
}
static SkinNode *build_frames(
- const MVert *mvert, int totvert, const MVertSkin *nodes, const MeshElemMap *emap, EMat *emat)
+ const MVert *mvert, int verts_num, const MVertSkin *nodes, const MeshElemMap *emap, EMat *emat)
{
SkinNode *skin_nodes;
int v;
- skin_nodes = MEM_calloc_arrayN(totvert, sizeof(SkinNode), "build_frames.skin_nodes");
+ skin_nodes = MEM_calloc_arrayN(verts_num, sizeof(SkinNode), "build_frames.skin_nodes");
- for (v = 0; v < totvert; v++) {
+ for (v = 0; v < verts_num; v++) {
if (emap[v].count <= 1) {
end_node_frames(v, skin_nodes, mvert, nodes, emap, emat);
}
@@ -766,10 +766,10 @@ static void build_emats_stack(BLI_Stack *stack,
static EMat *build_edge_mats(const MVertSkin *vs,
const MVert *mvert,
- int totvert,
+ const int verts_num,
const MEdge *medge,
const MeshElemMap *emap,
- int totedge,
+ const int edges_num,
bool *has_valid_root)
{
BLI_Stack *stack;
@@ -780,12 +780,12 @@ static EMat *build_edge_mats(const MVertSkin *vs,
stack = BLI_stack_new(sizeof(stack_elem), "build_edge_mats.stack");
- visited_e = BLI_BITMAP_NEW(totedge, "build_edge_mats.visited_e");
- emat = MEM_calloc_arrayN(totedge, sizeof(EMat), "build_edge_mats.emat");
+ visited_e = BLI_BITMAP_NEW(edges_num, "build_edge_mats.visited_e");
+ emat = MEM_calloc_arrayN(edges_num, sizeof(EMat), "build_edge_mats.emat");
/* Edge matrices are built from the root nodes, add all roots with
* children to the stack */
- for (v = 0; v < totvert; v++) {
+ for (v = 0; v < verts_num; v++) {
if (vs[v].flag & MVERT_SKIN_ROOT) {
if (emap[v].count >= 1) {
const MEdge *e = &medge[emap[v].indices[0]];
@@ -800,7 +800,7 @@ static EMat *build_edge_mats(const MVertSkin *vs,
*has_valid_root = true;
}
- else if (totedge == 0) {
+ else if (edges_num == 0) {
/* Vertex-only mesh is valid, mark valid root as well (will display error otherwise). */
*has_valid_root = true;
break;
@@ -837,7 +837,7 @@ static int calc_edge_subdivisions(const MVert *mvert,
float avg_radius;
const bool v1_branch = degree[e->v1] > 2;
const bool v2_branch = degree[e->v2] > 2;
- int num_subdivisions;
+ int subdivisions_num;
/* If either end is a branch node marked 'loose', don't subdivide
* the edge (or subdivide just twice if both are branches) */
@@ -854,27 +854,27 @@ static int calc_edge_subdivisions(const MVert *mvert,
if (avg_radius != 0.0f) {
/* possible (but unlikely) that we overflow INT_MAX */
- float num_subdivisions_fl;
+ float subdivisions_num_fl;
const float edge_len = len_v3v3(mvert[e->v1].co, mvert[e->v2].co);
- num_subdivisions_fl = (edge_len / avg_radius);
- if (num_subdivisions_fl < NUM_SUBDIVISIONS_MAX) {
- num_subdivisions = (int)num_subdivisions_fl;
+ subdivisions_num_fl = (edge_len / avg_radius);
+ if (subdivisions_num_fl < NUM_SUBDIVISIONS_MAX) {
+ subdivisions_num = (int)subdivisions_num_fl;
}
else {
- num_subdivisions = NUM_SUBDIVISIONS_MAX;
+ subdivisions_num = NUM_SUBDIVISIONS_MAX;
}
}
else {
- num_subdivisions = 0;
+ subdivisions_num = 0;
}
/* If both ends are branch nodes, two intermediate nodes are
* required */
- if (num_subdivisions < 2 && v1_branch && v2_branch) {
- num_subdivisions = 2;
+ if (subdivisions_num < 2 && v1_branch && v2_branch) {
+ subdivisions_num = 2;
}
- return num_subdivisions;
+ return subdivisions_num;
#undef NUM_SUBDIVISIONS_MAX
}
@@ -888,8 +888,8 @@ static Mesh *subdivide_base(Mesh *orig)
MVert *origvert, *outvert;
MEdge *origedge, *outedge, *e;
MDeformVert *origdvert, *outdvert;
- int totorigvert, totorigedge;
- int totsubd, *degree, *edge_subd;
+ int orig_vert_num, orig_edge_num;
+ int subd_num, *degree, *edge_subd;
int i, j, k, u, v;
float radrat;
@@ -897,29 +897,29 @@ static Mesh *subdivide_base(Mesh *orig)
origvert = orig->mvert;
origedge = orig->medge;
origdvert = orig->dvert;
- totorigvert = orig->totvert;
- totorigedge = orig->totedge;
+ orig_vert_num = orig->totvert;
+ orig_edge_num = orig->totedge;
/* Get degree of all vertices */
- degree = MEM_calloc_arrayN(totorigvert, sizeof(int), "degree");
- for (i = 0; i < totorigedge; i++) {
+ degree = MEM_calloc_arrayN(orig_vert_num, sizeof(int), "degree");
+ for (i = 0; i < orig_edge_num; i++) {
degree[origedge[i].v1]++;
degree[origedge[i].v2]++;
}
/* Per edge, store how many subdivisions are needed */
- edge_subd = MEM_calloc_arrayN((uint)totorigedge, sizeof(int), "edge_subd");
- for (i = 0, totsubd = 0; i < totorigedge; i++) {
+ edge_subd = MEM_calloc_arrayN((uint)orig_edge_num, sizeof(int), "edge_subd");
+ for (i = 0, subd_num = 0; i < orig_edge_num; i++) {
edge_subd[i] += calc_edge_subdivisions(origvert, orignode, &origedge[i], degree);
BLI_assert(edge_subd[i] >= 0);
- totsubd += edge_subd[i];
+ subd_num += edge_subd[i];
}
MEM_freeN(degree);
/* Allocate output mesh */
result = BKE_mesh_new_nomain_from_template(
- orig, totorigvert + totsubd, totorigedge + totsubd, 0, 0, 0);
+ orig, orig_vert_num + subd_num, orig_edge_num + subd_num, 0, 0, 0);
outvert = result->mvert;
outedge = result->medge;
@@ -927,16 +927,16 @@ static Mesh *subdivide_base(Mesh *orig)
outdvert = result->dvert;
/* Copy original vertex data */
- CustomData_copy_data(&orig->vdata, &result->vdata, 0, 0, totorigvert);
+ CustomData_copy_data(&orig->vdata, &result->vdata, 0, 0, orig_vert_num);
/* Subdivide edges */
- for (i = 0, v = totorigvert; i < totorigedge; i++) {
+ for (i = 0, v = orig_vert_num; i < orig_edge_num; i++) {
struct {
/* Vertex group number */
int def_nr;
float w1, w2;
} *vgroups = NULL, *vg;
- int totvgroup = 0;
+ int vgroups_num = 0;
e = &origedge[i];
@@ -950,8 +950,8 @@ static Mesh *subdivide_base(Mesh *orig)
vg = NULL;
for (k = 0; k < dv2->totweight; k++) {
if (dv1->dw[j].def_nr == dv2->dw[k].def_nr) {
- vg = &vgroups[totvgroup];
- totvgroup++;
+ vg = &vgroups[vgroups_num];
+ vgroups_num++;
break;
}
}
@@ -986,7 +986,7 @@ static Mesh *subdivide_base(Mesh *orig)
interp_v3_v3v3(outnode[v].radius, orignode[e->v1].radius, orignode[e->v2].radius, t);
/* Interpolate vertex group weights */
- for (k = 0; k < totvgroup; k++) {
+ for (k = 0; k < vgroups_num; k++) {
float weight;
vg = &vgroups[k];
@@ -1561,14 +1561,14 @@ static void hull_merge_triangles(SkinOutput *so, const SkinModifierData *smd)
}
static void skin_merge_close_frame_verts(SkinNode *skin_nodes,
- int totvert,
+ int verts_num,
const MeshElemMap *emap,
const MEdge *medge)
{
Frame **hull_frames;
int v, tothullframe;
- for (v = 0; v < totvert; v++) {
+ for (v = 0; v < verts_num; v++) {
/* Only check branch nodes */
if (!skin_nodes[v].totframe) {
hull_frames = collect_hull_frames(v, skin_nodes, emap, medge, &tothullframe);
@@ -1578,11 +1578,11 @@ static void skin_merge_close_frame_verts(SkinNode *skin_nodes,
}
}
-static void skin_update_merged_vertices(SkinNode *skin_nodes, int totvert)
+static void skin_update_merged_vertices(SkinNode *skin_nodes, int verts_num)
{
int v;
- for (v = 0; v < totvert; v++) {
+ for (v = 0; v < verts_num; v++) {
SkinNode *sn = &skin_nodes[v];
int i, j;
@@ -1601,11 +1601,11 @@ static void skin_update_merged_vertices(SkinNode *skin_nodes, int totvert)
}
}
-static void skin_fix_hull_topology(BMesh *bm, SkinNode *skin_nodes, int totvert)
+static void skin_fix_hull_topology(BMesh *bm, SkinNode *skin_nodes, int verts_num)
{
int v;
- for (v = 0; v < totvert; v++) {
+ for (v = 0; v < verts_num; v++) {
SkinNode *sn = &skin_nodes[v];
int j;
@@ -1626,11 +1626,11 @@ static void skin_fix_hull_topology(BMesh *bm, SkinNode *skin_nodes, int totvert)
}
}
-static void skin_output_end_nodes(SkinOutput *so, SkinNode *skin_nodes, int totvert)
+static void skin_output_end_nodes(SkinOutput *so, SkinNode *skin_nodes, int verts_num)
{
int v;
- for (v = 0; v < totvert; v++) {
+ for (v = 0; v < verts_num; v++) {
SkinNode *sn = &skin_nodes[v];
/* Assuming here just two frames */
if (sn->flag & SEAM_FRAME) {
@@ -1676,11 +1676,11 @@ static void skin_output_end_nodes(SkinOutput *so, SkinNode *skin_nodes, int totv
static void skin_output_connections(SkinOutput *so,
SkinNode *skin_nodes,
const MEdge *medge,
- int totedge)
+ int edges_num)
{
int e;
- for (e = 0; e < totedge; e++) {
+ for (e = 0; e < edges_num; e++) {
SkinNode *a, *b;
a = &skin_nodes[medge[e].v1];
b = &skin_nodes[medge[e].v2];
@@ -1713,7 +1713,7 @@ static void skin_output_connections(SkinOutput *so,
static void skin_smooth_hulls(BMesh *bm,
SkinNode *skin_nodes,
- int totvert,
+ int verts_num,
const SkinModifierData *smd)
{
BMIter iter, eiter;
@@ -1726,7 +1726,7 @@ static void skin_smooth_hulls(BMesh *bm,
/* Mark all frame vertices */
BM_mesh_elem_hflag_disable_all(bm, BM_VERT, BM_ELEM_TAG, false);
- for (i = 0; i < totvert; i++) {
+ for (i = 0; i < verts_num; i++) {
for (j = 0; j < skin_nodes[i].totframe; j++) {
Frame *frame = &skin_nodes[i].frames[j];
@@ -1780,13 +1780,16 @@ static void skin_smooth_hulls(BMesh *bm,
}
/* Returns true if all hulls are successfully built, false otherwise */
-static bool skin_output_branch_hulls(
- SkinOutput *so, SkinNode *skin_nodes, int totvert, const MeshElemMap *emap, const MEdge *medge)
+static bool skin_output_branch_hulls(SkinOutput *so,
+ SkinNode *skin_nodes,
+ int verts_num,
+ const MeshElemMap *emap,
+ const MEdge *medge)
{
bool result = true;
int v;
- for (v = 0; v < totvert; v++) {
+ for (v = 0; v < verts_num; v++) {
SkinNode *sn = &skin_nodes[v];
/* Branch node hulls */
@@ -1812,10 +1815,10 @@ typedef enum eSkinErrorFlag {
} eSkinErrorFlag;
static BMesh *build_skin(SkinNode *skin_nodes,
- int totvert,
+ int verts_num,
const MeshElemMap *emap,
const MEdge *medge,
- int totedge,
+ int edges_num,
const MDeformVert *input_dvert,
SkinModifierData *smd,
eSkinErrorFlag *r_error)
@@ -1841,19 +1844,19 @@ static BMesh *build_skin(SkinNode *skin_nodes,
/* Check for mergeable frame corners around hulls before
* outputting vertices */
- skin_merge_close_frame_verts(skin_nodes, totvert, emap, medge);
+ skin_merge_close_frame_verts(skin_nodes, verts_num, emap, medge);
/* Write out all frame vertices to the mesh */
- for (v = 0; v < totvert; v++) {
+ for (v = 0; v < verts_num; v++) {
if (skin_nodes[v].totframe) {
output_frames(so.bm, &skin_nodes[v], input_dvert ? &input_dvert[v] : NULL);
}
}
/* Update vertex pointers for merged frame corners */
- skin_update_merged_vertices(skin_nodes, totvert);
+ skin_update_merged_vertices(skin_nodes, verts_num);
- if (!skin_output_branch_hulls(&so, skin_nodes, totvert, emap, medge)) {
+ if (!skin_output_branch_hulls(&so, skin_nodes, verts_num, emap, medge)) {
*r_error |= SKIN_ERROR_HULL;
}
@@ -1871,12 +1874,12 @@ static BMesh *build_skin(SkinNode *skin_nodes,
* creating all hull faces, but before creating any other
* faces.
*/
- skin_fix_hull_topology(so.bm, skin_nodes, totvert);
+ skin_fix_hull_topology(so.bm, skin_nodes, verts_num);
- skin_smooth_hulls(so.bm, skin_nodes, totvert, smd);
+ skin_smooth_hulls(so.bm, skin_nodes, verts_num, smd);
- skin_output_end_nodes(&so, skin_nodes, totvert);
- skin_output_connections(&so, skin_nodes, medge, totedge);
+ skin_output_end_nodes(&so, skin_nodes, verts_num);
+ skin_output_connections(&so, skin_nodes, medge, edges_num);
hull_merge_triangles(&so, smd);
bmesh_edit_end(so.bm, 0);
@@ -1912,7 +1915,7 @@ static Mesh *base_skin(Mesh *origmesh, SkinModifierData *smd, eSkinErrorFlag *r_
MVert *mvert;
MEdge *medge;
MDeformVert *dvert;
- int totvert, totedge;
+ int verts_num, edges_num;
bool has_valid_root = false;
nodes = CustomData_get_layer(&origmesh->vdata, CD_MVERT_SKIN);
@@ -1920,17 +1923,17 @@ static Mesh *base_skin(Mesh *origmesh, SkinModifierData *smd, eSkinErrorFlag *r_
mvert = origmesh->mvert;
dvert = origmesh->dvert;
medge = origmesh->medge;
- totvert = origmesh->totvert;
- totedge = origmesh->totedge;
+ verts_num = origmesh->totvert;
+ edges_num = origmesh->totedge;
- BKE_mesh_vert_edge_map_create(&emap, &emapmem, medge, totvert, totedge);
+ BKE_mesh_vert_edge_map_create(&emap, &emapmem, medge, verts_num, edges_num);
- emat = build_edge_mats(nodes, mvert, totvert, medge, emap, totedge, &has_valid_root);
- skin_nodes = build_frames(mvert, totvert, nodes, emap, emat);
+ emat = build_edge_mats(nodes, mvert, verts_num, medge, emap, edges_num, &has_valid_root);
+ skin_nodes = build_frames(mvert, verts_num, nodes, emap, emat);
MEM_freeN(emat);
emat = NULL;
- bm = build_skin(skin_nodes, totvert, emap, medge, totedge, dvert, smd, r_error);
+ bm = build_skin(skin_nodes, verts_num, emap, medge, edges_num, dvert, smd, r_error);
MEM_freeN(skin_nodes);
MEM_freeN(emap);
diff --git a/source/blender/modifiers/intern/MOD_smooth.c b/source/blender/modifiers/intern/MOD_smooth.c
index 4236147c1f3..5439083d9a7 100644
--- a/source/blender/modifiers/intern/MOD_smooth.c
+++ b/source/blender/modifiers/intern/MOD_smooth.c
@@ -76,21 +76,21 @@ static void requiredDataMask(Object *UNUSED(ob),
}
static void smoothModifier_do(
- SmoothModifierData *smd, Object *ob, Mesh *mesh, float (*vertexCos)[3], int numVerts)
+ SmoothModifierData *smd, Object *ob, Mesh *mesh, float (*vertexCos)[3], int verts_num)
{
if (mesh == NULL) {
return;
}
float(*accumulated_vecs)[3] = MEM_calloc_arrayN(
- (size_t)numVerts, sizeof(*accumulated_vecs), __func__);
+ (size_t)verts_num, sizeof(*accumulated_vecs), __func__);
if (!accumulated_vecs) {
return;
}
- uint *num_accumulated_vecs = MEM_calloc_arrayN(
- (size_t)numVerts, sizeof(*num_accumulated_vecs), __func__);
- if (!num_accumulated_vecs) {
+ uint *accumulated_vecs_count = MEM_calloc_arrayN(
+ (size_t)verts_num, sizeof(*accumulated_vecs_count), __func__);
+ if (!accumulated_vecs_count) {
MEM_freeN(accumulated_vecs);
return;
}
@@ -100,7 +100,7 @@ static void smoothModifier_do(
const bool invert_vgroup = (smd->flag & MOD_SMOOTH_INVERT_VGROUP) != 0;
MEdge *medges = mesh->medge;
- const int num_edges = mesh->totedge;
+ const int edges_num = mesh->totedge;
MDeformVert *dvert;
int defgrp_index;
@@ -108,31 +108,31 @@ static void smoothModifier_do(
for (int j = 0; j < smd->repeat; j++) {
if (j != 0) {
- memset(accumulated_vecs, 0, sizeof(*accumulated_vecs) * (size_t)numVerts);
- memset(num_accumulated_vecs, 0, sizeof(*num_accumulated_vecs) * (size_t)numVerts);
+ memset(accumulated_vecs, 0, sizeof(*accumulated_vecs) * (size_t)verts_num);
+ memset(accumulated_vecs_count, 0, sizeof(*accumulated_vecs_count) * (size_t)verts_num);
}
- for (int i = 0; i < num_edges; i++) {
+ for (int i = 0; i < edges_num; i++) {
float fvec[3];
const uint idx1 = medges[i].v1;
const uint idx2 = medges[i].v2;
mid_v3_v3v3(fvec, vertexCos[idx1], vertexCos[idx2]);
- num_accumulated_vecs[idx1]++;
+ accumulated_vecs_count[idx1]++;
add_v3_v3(accumulated_vecs[idx1], fvec);
- num_accumulated_vecs[idx2]++;
+ accumulated_vecs_count[idx2]++;
add_v3_v3(accumulated_vecs[idx2], fvec);
}
const short flag = smd->flag;
if (dvert) {
MDeformVert *dv = dvert;
- for (int i = 0; i < numVerts; i++, dv++) {
+ for (int i = 0; i < verts_num; i++, dv++) {
float *vco_orig = vertexCos[i];
- if (num_accumulated_vecs[i] > 0) {
- mul_v3_fl(accumulated_vecs[i], 1.0f / (float)num_accumulated_vecs[i]);
+ if (accumulated_vecs_count[i] > 0) {
+ mul_v3_fl(accumulated_vecs[i], 1.0f / (float)accumulated_vecs_count[i]);
}
float *vco_new = accumulated_vecs[i];
@@ -156,10 +156,10 @@ static void smoothModifier_do(
}
}
else { /* no vertex group */
- for (int i = 0; i < numVerts; i++) {
+ for (int i = 0; i < verts_num; i++) {
float *vco_orig = vertexCos[i];
- if (num_accumulated_vecs[i] > 0) {
- mul_v3_fl(accumulated_vecs[i], 1.0f / (float)num_accumulated_vecs[i]);
+ if (accumulated_vecs_count[i] > 0) {
+ mul_v3_fl(accumulated_vecs[i], 1.0f / (float)accumulated_vecs_count[i]);
}
float *vco_new = accumulated_vecs[i];
@@ -177,22 +177,22 @@ static void smoothModifier_do(
}
MEM_freeN(accumulated_vecs);
- MEM_freeN(num_accumulated_vecs);
+ MEM_freeN(accumulated_vecs_count);
}
static void deformVerts(ModifierData *md,
const ModifierEvalContext *ctx,
Mesh *mesh,
float (*vertexCos)[3],
- int numVerts)
+ int verts_num)
{
SmoothModifierData *smd = (SmoothModifierData *)md;
Mesh *mesh_src = NULL;
/* mesh_src is needed for vgroups, and taking edges into account. */
- mesh_src = MOD_deform_mesh_eval_get(ctx->object, NULL, mesh, NULL, numVerts, false, false);
+ mesh_src = MOD_deform_mesh_eval_get(ctx->object, NULL, mesh, NULL, verts_num, false, false);
- smoothModifier_do(smd, ctx->object, mesh_src, vertexCos, numVerts);
+ smoothModifier_do(smd, ctx->object, mesh_src, vertexCos, verts_num);
if (!ELEM(mesh_src, NULL, mesh)) {
BKE_id_free(NULL, mesh_src);
@@ -204,18 +204,18 @@ static void deformVertsEM(ModifierData *md,
struct BMEditMesh *editData,
Mesh *mesh,
float (*vertexCos)[3],
- int numVerts)
+ int verts_num)
{
SmoothModifierData *smd = (SmoothModifierData *)md;
Mesh *mesh_src = NULL;
/* mesh_src is needed for vgroups, and taking edges into account. */
- mesh_src = MOD_deform_mesh_eval_get(ctx->object, editData, mesh, NULL, numVerts, false, false);
+ mesh_src = MOD_deform_mesh_eval_get(ctx->object, editData, mesh, NULL, verts_num, false, false);
/* TODO(campbell): use edit-mode data only (remove this line). */
BKE_mesh_wrapper_ensure_mdata(mesh_src);
- smoothModifier_do(smd, ctx->object, mesh_src, vertexCos, numVerts);
+ smoothModifier_do(smd, ctx->object, mesh_src, vertexCos, verts_num);
if (!ELEM(mesh_src, NULL, mesh)) {
BKE_id_free(NULL, mesh_src);
diff --git a/source/blender/modifiers/intern/MOD_softbody.c b/source/blender/modifiers/intern/MOD_softbody.c
index ae90240dd3f..d8379cc870a 100644
--- a/source/blender/modifiers/intern/MOD_softbody.c
+++ b/source/blender/modifiers/intern/MOD_softbody.c
@@ -40,16 +40,14 @@ static void deformVerts(ModifierData *UNUSED(md),
const ModifierEvalContext *ctx,
Mesh *UNUSED(derivedData),
float (*vertexCos)[3],
- int numVerts)
+ int verts_num)
{
Scene *scene = DEG_get_evaluated_scene(ctx->depsgraph);
sbObjectStep(
- ctx->depsgraph, scene, ctx->object, DEG_get_ctime(ctx->depsgraph), vertexCos, numVerts);
+ ctx->depsgraph, scene, ctx->object, DEG_get_ctime(ctx->depsgraph), vertexCos, verts_num);
}
-static bool dependsOnTime(struct Scene *UNUSED(scene),
- ModifierData *UNUSED(md),
- const int UNUSED(dag_eval_mode))
+static bool dependsOnTime(struct Scene *UNUSED(scene), ModifierData *UNUSED(md))
{
return true;
}
diff --git a/source/blender/modifiers/intern/MOD_solidify_extrude.c b/source/blender/modifiers/intern/MOD_solidify_extrude.c
index fdaf7bd41d1..80af23054e4 100644
--- a/source/blender/modifiers/intern/MOD_solidify_extrude.c
+++ b/source/blender/modifiers/intern/MOD_solidify_extrude.c
@@ -55,14 +55,14 @@ BLI_INLINE bool edgeref_is_init(const EdgeFaceRef *edge_ref)
*/
static void mesh_calc_hq_normal(Mesh *mesh, const float (*poly_nors)[3], float (*r_vert_nors)[3])
{
- int i, numVerts, numEdges, numPolys;
+ int i, verts_num, edges_num, polys_num;
MPoly *mpoly, *mp;
MLoop *mloop, *ml;
MEdge *medge, *ed;
- numVerts = mesh->totvert;
- numEdges = mesh->totedge;
- numPolys = mesh->totpoly;
+ verts_num = mesh->totvert;
+ edges_num = mesh->totedge;
+ polys_num = mesh->totpoly;
mpoly = mesh->mpoly;
medge = mesh->medge;
mloop = mesh->mloop;
@@ -71,7 +71,7 @@ static void mesh_calc_hq_normal(Mesh *mesh, const float (*poly_nors)[3], float (
/* Doesn't work here! */
#if 0
- mv = CustomData_duplicate_referenced_layer(&dm->vertData, CD_MVERT, numVerts);
+ mv = CustomData_duplicate_referenced_layer(&dm->vertData, CD_MVERT, verts_num);
cddm->mvert = mv;
#endif
@@ -79,12 +79,12 @@ static void mesh_calc_hq_normal(Mesh *mesh, const float (*poly_nors)[3], float (
{
EdgeFaceRef *edge_ref_array = MEM_calloc_arrayN(
- (size_t)numEdges, sizeof(EdgeFaceRef), "Edge Connectivity");
+ (size_t)edges_num, sizeof(EdgeFaceRef), "Edge Connectivity");
EdgeFaceRef *edge_ref;
float edge_normal[3];
/* Add an edge reference if it's not there, pointing back to the face index. */
- for (i = 0; i < numPolys; i++, mp++) {
+ for (i = 0; i < polys_num; i++, mp++) {
int j;
ml = mloop + mp->loopstart;
@@ -110,7 +110,7 @@ static void mesh_calc_hq_normal(Mesh *mesh, const float (*poly_nors)[3], float (
}
}
- for (i = 0, ed = medge, edge_ref = edge_ref_array; i < numEdges; i++, ed++, edge_ref++) {
+ for (i = 0, ed = medge, edge_ref = edge_ref_array; i < edges_num; i++, ed++, edge_ref++) {
/* Get the edge vert indices, and edge value (the face indices that use it) */
if (edgeref_is_init(edge_ref) && (edge_ref->p1 != -1)) {
@@ -141,7 +141,7 @@ static void mesh_calc_hq_normal(Mesh *mesh, const float (*poly_nors)[3], float (
/* normalize vertex normals and assign */
const float(*vert_normals)[3] = BKE_mesh_vertex_normals_ensure(mesh);
- for (i = 0; i < numVerts; i++) {
+ for (i = 0; i < verts_num; i++) {
if (normalize_v3(r_vert_nors[i]) == 0.0f) {
copy_v3_v3(r_vert_nors[i], vert_normals[i]);
}
@@ -164,10 +164,10 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex
MEdge *ed, *medge, *orig_medge;
MLoop *ml, *mloop, *orig_mloop;
MPoly *mp, *mpoly, *orig_mpoly;
- const uint numVerts = (uint)mesh->totvert;
- const uint numEdges = (uint)mesh->totedge;
- const uint numPolys = (uint)mesh->totpoly;
- const uint numLoops = (uint)mesh->totloop;
+ const uint verts_num = (uint)mesh->totvert;
+ const uint edges_num = (uint)mesh->totedge;
+ const uint polys_num = (uint)mesh->totpoly;
+ const uint loops_num = (uint)mesh->totloop;
uint newLoops = 0, newPolys = 0, newEdges = 0, newVerts = 0, rimVerts = 0;
/* Only use material offsets if we have 2 or more materials. */
@@ -184,7 +184,7 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex
STACK_DECLARE(new_edge_arr);
uint *old_vert_arr = MEM_calloc_arrayN(
- numVerts, sizeof(*old_vert_arr), "old_vert_arr in solidify");
+ verts_num, sizeof(*old_vert_arr), "old_vert_arr in solidify");
uint *edge_users = NULL;
int *edge_order = NULL;
@@ -233,33 +233,34 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex
poly_nors = BKE_mesh_poly_normals_ensure(mesh);
}
- STACK_INIT(new_vert_arr, numVerts * 2);
- STACK_INIT(new_edge_arr, numEdges * 2);
+ STACK_INIT(new_vert_arr, verts_num * 2);
+ STACK_INIT(new_edge_arr, edges_num * 2);
if (do_rim) {
- BLI_bitmap *orig_mvert_tag = BLI_BITMAP_NEW(numVerts, __func__);
+ BLI_bitmap *orig_mvert_tag = BLI_BITMAP_NEW(verts_num, __func__);
uint eidx;
uint i;
#define INVALID_UNUSED ((uint)-1)
#define INVALID_PAIR ((uint)-2)
- new_vert_arr = MEM_malloc_arrayN(numVerts, 2 * sizeof(*new_vert_arr), __func__);
- new_edge_arr = MEM_malloc_arrayN(((numEdges * 2) + numVerts), sizeof(*new_edge_arr), __func__);
+ new_vert_arr = MEM_malloc_arrayN(verts_num, 2 * sizeof(*new_vert_arr), __func__);
+ new_edge_arr = MEM_malloc_arrayN(
+ ((edges_num * 2) + verts_num), sizeof(*new_edge_arr), __func__);
- edge_users = MEM_malloc_arrayN(numEdges, sizeof(*edge_users), "solid_mod edges");
- edge_order = MEM_malloc_arrayN(numEdges, sizeof(*edge_order), "solid_mod order");
+ edge_users = MEM_malloc_arrayN(edges_num, sizeof(*edge_users), "solid_mod edges");
+ edge_order = MEM_malloc_arrayN(edges_num, sizeof(*edge_order), "solid_mod order");
/* save doing 2 loops here... */
#if 0
- copy_vn_i(edge_users, numEdges, INVALID_UNUSED);
+ copy_vn_i(edge_users, edges_num, INVALID_UNUSED);
#endif
- for (eidx = 0, ed = orig_medge; eidx < numEdges; eidx++, ed++) {
+ for (eidx = 0, ed = orig_medge; eidx < edges_num; eidx++, ed++) {
edge_users[eidx] = INVALID_UNUSED;
}
- for (i = 0, mp = orig_mpoly; i < numPolys; i++, mp++) {
+ for (i = 0, mp = orig_mpoly; i < polys_num; i++, mp++) {
MLoop *ml_prev;
int j;
@@ -272,7 +273,7 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex
if (edge_users[eidx] == INVALID_UNUSED) {
ed = orig_medge + eidx;
BLI_assert(ELEM(ml_prev->v, ed->v1, ed->v2) && ELEM(ml->v, ed->v1, ed->v2));
- edge_users[eidx] = (ml_prev->v > ml->v) == (ed->v1 < ed->v2) ? i : (i + numPolys);
+ edge_users[eidx] = (ml_prev->v > ml->v) == (ed->v1 < ed->v2) ? i : (i + polys_num);
edge_order[eidx] = j;
}
else {
@@ -282,7 +283,7 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex
}
}
- for (eidx = 0, ed = orig_medge; eidx < numEdges; eidx++, ed++) {
+ for (eidx = 0, ed = orig_medge; eidx < edges_num; eidx++, ed++) {
if (!ELEM(edge_users[eidx], INVALID_UNUSED, INVALID_PAIR)) {
BLI_BITMAP_ENABLE(orig_mvert_tag, ed->v1);
BLI_BITMAP_ENABLE(orig_mvert_tag, ed->v2);
@@ -292,7 +293,7 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex
}
}
- for (i = 0; i < numVerts; i++) {
+ for (i = 0; i < verts_num; i++) {
if (BLI_BITMAP_TEST(orig_mvert_tag, i)) {
old_vert_arr[i] = STACK_SIZE(new_vert_arr);
STACK_PUSH(new_vert_arr, i);
@@ -319,16 +320,16 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex
}
if (smd->flag & MOD_SOLIDIFY_NORMAL_CALC) {
- vert_nors = MEM_calloc_arrayN(numVerts, sizeof(float[3]), "mod_solid_vno_hq");
+ vert_nors = MEM_calloc_arrayN(verts_num, sizeof(float[3]), "mod_solid_vno_hq");
mesh_calc_hq_normal(mesh, poly_nors, vert_nors);
}
result = BKE_mesh_new_nomain_from_template(mesh,
- (int)((numVerts * stride) + newVerts),
- (int)((numEdges * stride) + newEdges + rimVerts),
+ (int)((verts_num * stride) + newVerts),
+ (int)((edges_num * stride) + newEdges + rimVerts),
0,
- (int)((numLoops * stride) + newLoops),
- (int)((numPolys * stride) + newPolys));
+ (int)((loops_num * stride) + newLoops),
+ (int)((polys_num * stride) + newPolys));
mpoly = result->mpoly;
mloop = result->mloop;
@@ -341,69 +342,69 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex
}
if (do_shell) {
- CustomData_copy_data(&mesh->vdata, &result->vdata, 0, 0, (int)numVerts);
- CustomData_copy_data(&mesh->vdata, &result->vdata, 0, (int)numVerts, (int)numVerts);
+ CustomData_copy_data(&mesh->vdata, &result->vdata, 0, 0, (int)verts_num);
+ CustomData_copy_data(&mesh->vdata, &result->vdata, 0, (int)verts_num, (int)verts_num);
- CustomData_copy_data(&mesh->edata, &result->edata, 0, 0, (int)numEdges);
- CustomData_copy_data(&mesh->edata, &result->edata, 0, (int)numEdges, (int)numEdges);
+ CustomData_copy_data(&mesh->edata, &result->edata, 0, 0, (int)edges_num);
+ CustomData_copy_data(&mesh->edata, &result->edata, 0, (int)edges_num, (int)edges_num);
- CustomData_copy_data(&mesh->ldata, &result->ldata, 0, 0, (int)numLoops);
+ CustomData_copy_data(&mesh->ldata, &result->ldata, 0, 0, (int)loops_num);
/* DO NOT copy here the 'copied' part of loop data, we want to reverse loops
* (so that winding of copied face get reversed, so that normals get reversed
* and point in expected direction...).
* If we also copy data here, then this data get overwritten
* (and allocated memory becomes memleak). */
- CustomData_copy_data(&mesh->pdata, &result->pdata, 0, 0, (int)numPolys);
- CustomData_copy_data(&mesh->pdata, &result->pdata, 0, (int)numPolys, (int)numPolys);
+ CustomData_copy_data(&mesh->pdata, &result->pdata, 0, 0, (int)polys_num);
+ CustomData_copy_data(&mesh->pdata, &result->pdata, 0, (int)polys_num, (int)polys_num);
}
else {
int i, j;
- CustomData_copy_data(&mesh->vdata, &result->vdata, 0, 0, (int)numVerts);
- for (i = 0, j = (int)numVerts; i < numVerts; i++) {
+ CustomData_copy_data(&mesh->vdata, &result->vdata, 0, 0, (int)verts_num);
+ for (i = 0, j = (int)verts_num; i < verts_num; i++) {
if (old_vert_arr[i] != INVALID_UNUSED) {
CustomData_copy_data(&mesh->vdata, &result->vdata, i, j, 1);
j++;
}
}
- CustomData_copy_data(&mesh->edata, &result->edata, 0, 0, (int)numEdges);
+ CustomData_copy_data(&mesh->edata, &result->edata, 0, 0, (int)edges_num);
- for (i = 0, j = (int)numEdges; i < numEdges; i++) {
+ for (i = 0, j = (int)edges_num; i < edges_num; i++) {
if (!ELEM(edge_users[i], INVALID_UNUSED, INVALID_PAIR)) {
MEdge *ed_src, *ed_dst;
CustomData_copy_data(&mesh->edata, &result->edata, i, j, 1);
ed_src = &medge[i];
ed_dst = &medge[j];
- ed_dst->v1 = old_vert_arr[ed_src->v1] + numVerts;
- ed_dst->v2 = old_vert_arr[ed_src->v2] + numVerts;
+ ed_dst->v1 = old_vert_arr[ed_src->v1] + verts_num;
+ ed_dst->v2 = old_vert_arr[ed_src->v2] + verts_num;
j++;
}
}
/* will be created later */
- CustomData_copy_data(&mesh->ldata, &result->ldata, 0, 0, (int)numLoops);
- CustomData_copy_data(&mesh->pdata, &result->pdata, 0, 0, (int)numPolys);
+ CustomData_copy_data(&mesh->ldata, &result->ldata, 0, 0, (int)loops_num);
+ CustomData_copy_data(&mesh->pdata, &result->pdata, 0, 0, (int)polys_num);
}
/* initializes: (i_end, do_shell_align, mv). */
#define INIT_VERT_ARRAY_OFFSETS(test) \
if (((ofs_new >= ofs_orig) == do_flip) == test) { \
- i_end = numVerts; \
+ i_end = verts_num; \
do_shell_align = true; \
mv = mvert; \
} \
else { \
if (do_shell) { \
- i_end = numVerts; \
+ i_end = verts_num; \
do_shell_align = true; \
} \
else { \
i_end = newVerts; \
do_shell_align = false; \
} \
- mv = &mvert[numVerts]; \
+ mv = &mvert[verts_num]; \
} \
(void)0
@@ -412,7 +413,7 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex
if (do_shell) {
uint i;
- mp = mpoly + numPolys;
+ mp = mpoly + polys_num;
for (i = 0; i < mesh->totpoly; i++, mp++) {
const int loop_end = mp->totloop - 1;
MLoop *ml2;
@@ -457,14 +458,14 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex
mp->loopstart += mesh->totloop;
for (j = 0; j < mp->totloop; j++) {
- ml2[j].e += numEdges;
- ml2[j].v += numVerts;
+ ml2[j].e += edges_num;
+ ml2[j].v += verts_num;
}
}
- for (i = 0, ed = medge + numEdges; i < numEdges; i++, ed++) {
- ed->v1 += numVerts;
- ed->v2 += numVerts;
+ for (i = 0, ed = medge + edges_num; i < edges_num; i++, ed++) {
+ ed->v1 += verts_num;
+ ed->v2 += verts_num;
}
}
@@ -483,9 +484,9 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex
float *edge_angs = NULL;
if (do_clamp) {
- vert_lens = MEM_malloc_arrayN(numVerts, sizeof(float), "vert_lens");
- copy_vn_fl(vert_lens, (int)numVerts, FLT_MAX);
- for (uint i = 0; i < numEdges; i++) {
+ vert_lens = MEM_malloc_arrayN(verts_num, sizeof(float), "vert_lens");
+ copy_vn_fl(vert_lens, (int)verts_num, FLT_MAX);
+ for (uint i = 0; i < edges_num; i++) {
const float ed_len_sq = len_squared_v3v3(mvert[medge[i].v1].co, mvert[medge[i].v2].co);
vert_lens[medge[i].v1] = min_ff(vert_lens[medge[i].v1], ed_len_sq);
vert_lens[medge[i].v2] = min_ff(vert_lens[medge[i].v2], ed_len_sq);
@@ -495,23 +496,23 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex
if (do_angle_clamp || do_bevel_convex) {
uint eidx;
if (do_angle_clamp) {
- vert_angs = MEM_malloc_arrayN(numVerts, sizeof(float), "vert_angs");
- copy_vn_fl(vert_angs, (int)numVerts, 0.5f * M_PI);
+ vert_angs = MEM_malloc_arrayN(verts_num, sizeof(float), "vert_angs");
+ copy_vn_fl(vert_angs, (int)verts_num, 0.5f * M_PI);
}
if (do_bevel_convex) {
- edge_angs = MEM_malloc_arrayN(numEdges, sizeof(float), "edge_angs");
+ edge_angs = MEM_malloc_arrayN(edges_num, sizeof(float), "edge_angs");
if (!do_rim) {
- edge_users = MEM_malloc_arrayN(numEdges, sizeof(*edge_users), "solid_mod edges");
+ edge_users = MEM_malloc_arrayN(edges_num, sizeof(*edge_users), "solid_mod edges");
}
}
uint(*edge_user_pairs)[2] = MEM_malloc_arrayN(
- numEdges, sizeof(*edge_user_pairs), "edge_user_pairs");
- for (eidx = 0; eidx < numEdges; eidx++) {
+ edges_num, sizeof(*edge_user_pairs), "edge_user_pairs");
+ for (eidx = 0; eidx < edges_num; eidx++) {
edge_user_pairs[eidx][0] = INVALID_UNUSED;
edge_user_pairs[eidx][1] = INVALID_UNUSED;
}
mp = orig_mpoly;
- for (uint i = 0; i < numPolys; i++, mp++) {
+ for (uint i = 0; i < polys_num; i++, mp++) {
ml = orig_mloop + mp->loopstart;
MLoop *ml_prev = ml + (mp->totloop - 1);
@@ -533,7 +534,7 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex
}
ed = orig_medge;
float e[3];
- for (uint i = 0; i < numEdges; i++, ed++) {
+ for (uint i = 0; i < edges_num; i++, ed++) {
if (!ELEM(edge_user_pairs[i][0], INVALID_UNUSED, INVALID_PAIR) &&
!ELEM(edge_user_pairs[i][1], INVALID_UNUSED, INVALID_PAIR)) {
const float *n0 = poly_nors[edge_user_pairs[i][0]];
@@ -658,7 +659,7 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex
}
if (do_bevel_convex) {
- for (uint i = 0; i < numEdges; i++) {
+ for (uint i = 0; i < edges_num; i++) {
if (edge_users[i] == INVALID_PAIR) {
float angle = edge_angs[i];
medge[i].bweight = (char)clamp_i(
@@ -668,8 +669,8 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex
0,
255);
if (do_shell) {
- medge[i + numEdges].bweight = (char)clamp_i(
- (int)medge[i + numEdges].bweight +
+ medge[i + edges_num].bweight = (char)clamp_i(
+ (int)medge[i + edges_num].bweight +
(int)((angle > M_PI ? clamp_f(bevel_convex, 0.0f, 1.0f) :
clamp_f(bevel_convex, -1.0f, 0.0f)) *
255),
@@ -697,19 +698,19 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex
#endif
/* same as EM_solidify() in editmesh_lib.c */
float *vert_angles = MEM_calloc_arrayN(
- numVerts, sizeof(float[2]), "mod_solid_pair"); /* 2 in 1 */
- float *vert_accum = vert_angles + numVerts;
+ verts_num, sizeof(float[2]), "mod_solid_pair"); /* 2 in 1 */
+ float *vert_accum = vert_angles + verts_num;
uint vidx;
uint i;
if (vert_nors == NULL) {
- vert_nors = MEM_malloc_arrayN(numVerts, sizeof(float[3]), "mod_solid_vno");
- for (i = 0, mv = mvert; i < numVerts; i++, mv++) {
+ vert_nors = MEM_malloc_arrayN(verts_num, sizeof(float[3]), "mod_solid_vno");
+ for (i = 0, mv = mvert; i < verts_num; i++, mv++) {
copy_v3_v3(vert_nors[i], mesh_vert_normals[i]);
}
}
- for (i = 0, mp = mpoly; i < numPolys; i++, mp++) {
+ for (i = 0, mp = mpoly; i < polys_num; i++, mp++) {
/* #BKE_mesh_calc_poly_angles logic is inlined here */
float nor_prev[3];
float nor_next[3];
@@ -765,14 +766,14 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex
float scalar;
if (defgrp_invert) {
- for (i = 0; i < numVerts; i++, dv++) {
+ for (i = 0; i < verts_num; i++, dv++) {
scalar = 1.0f - BKE_defvert_find_weight(dv, defgrp_index);
scalar = offset_fac_vg + (scalar * offset_fac_vg_inv);
vert_angles[i] *= scalar;
}
}
else {
- for (i = 0; i < numVerts; i++, dv++) {
+ for (i = 0; i < verts_num; i++, dv++) {
scalar = BKE_defvert_find_weight(dv, defgrp_index);
scalar = offset_fac_vg + (scalar * offset_fac_vg_inv);
vert_angles[i] *= scalar;
@@ -788,22 +789,22 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex
if (do_angle_clamp || do_bevel_convex) {
uint eidx;
if (do_angle_clamp) {
- vert_angs = MEM_malloc_arrayN(numVerts, sizeof(float), "vert_angs even");
- copy_vn_fl(vert_angs, (int)numVerts, 0.5f * M_PI);
+ vert_angs = MEM_malloc_arrayN(verts_num, sizeof(float), "vert_angs even");
+ copy_vn_fl(vert_angs, (int)verts_num, 0.5f * M_PI);
}
if (do_bevel_convex) {
- edge_angs = MEM_malloc_arrayN(numEdges, sizeof(float), "edge_angs even");
+ edge_angs = MEM_malloc_arrayN(edges_num, sizeof(float), "edge_angs even");
if (!do_rim) {
- edge_users = MEM_malloc_arrayN(numEdges, sizeof(*edge_users), "solid_mod edges");
+ edge_users = MEM_malloc_arrayN(edges_num, sizeof(*edge_users), "solid_mod edges");
}
}
uint(*edge_user_pairs)[2] = MEM_malloc_arrayN(
- numEdges, sizeof(*edge_user_pairs), "edge_user_pairs");
- for (eidx = 0; eidx < numEdges; eidx++) {
+ edges_num, sizeof(*edge_user_pairs), "edge_user_pairs");
+ for (eidx = 0; eidx < edges_num; eidx++) {
edge_user_pairs[eidx][0] = INVALID_UNUSED;
edge_user_pairs[eidx][1] = INVALID_UNUSED;
}
- for (i = 0, mp = orig_mpoly; i < numPolys; i++, mp++) {
+ for (i = 0, mp = orig_mpoly; i < polys_num; i++, mp++) {
ml = orig_mloop + mp->loopstart;
MLoop *ml_prev = ml + (mp->totloop - 1);
@@ -825,7 +826,7 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex
}
ed = orig_medge;
float e[3];
- for (i = 0; i < numEdges; i++, ed++) {
+ for (i = 0; i < edges_num; i++, ed++) {
if (!ELEM(edge_user_pairs[i][0], INVALID_UNUSED, INVALID_PAIR) &&
!ELEM(edge_user_pairs[i][1], INVALID_UNUSED, INVALID_PAIR)) {
const float *n0 = poly_nors[edge_user_pairs[i][0]];
@@ -852,16 +853,16 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex
const float clamp_fac = 1 + (do_angle_clamp ? fabsf(smd->offset_fac) : 0);
const float offset = fabsf(smd->offset) * smd->offset_clamp * clamp_fac;
if (offset > FLT_EPSILON) {
- float *vert_lens_sq = MEM_malloc_arrayN(numVerts, sizeof(float), "vert_lens_sq");
+ float *vert_lens_sq = MEM_malloc_arrayN(verts_num, sizeof(float), "vert_lens_sq");
const float offset_sq = offset * offset;
- copy_vn_fl(vert_lens_sq, (int)numVerts, FLT_MAX);
- for (i = 0; i < numEdges; i++) {
+ copy_vn_fl(vert_lens_sq, (int)verts_num, FLT_MAX);
+ for (i = 0; i < edges_num; i++) {
const float ed_len = len_squared_v3v3(mvert[medge[i].v1].co, mvert[medge[i].v2].co);
vert_lens_sq[medge[i].v1] = min_ff(vert_lens_sq[medge[i].v1], ed_len);
vert_lens_sq[medge[i].v2] = min_ff(vert_lens_sq[medge[i].v2], ed_len);
}
if (do_angle_clamp) {
- for (i = 0; i < numVerts; i++) {
+ for (i = 0; i < verts_num; i++) {
float cos_ang = cosf(vert_angs[i] * 0.5f);
if (cos_ang > 0) {
float max_off = sqrtf(vert_lens_sq[i]) * 0.5f / cos_ang;
@@ -873,7 +874,7 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex
MEM_freeN(vert_angs);
}
else {
- for (i = 0; i < numVerts; i++) {
+ for (i = 0; i < verts_num; i++) {
if (vert_lens_sq[i] < offset_sq) {
float scalar = sqrtf(vert_lens_sq[i]) / offset;
vert_angles[i] *= scalar;
@@ -885,7 +886,7 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex
}
if (do_bevel_convex) {
- for (i = 0; i < numEdges; i++) {
+ for (i = 0; i < edges_num; i++) {
if (edge_users[i] == INVALID_PAIR) {
float angle = edge_angs[i];
medge[i].bweight = (char)clamp_i(
@@ -895,8 +896,8 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex
0,
255);
if (do_shell) {
- medge[i + numEdges].bweight = (char)clamp_i(
- (int)medge[i + numEdges].bweight +
+ medge[i + edges_num].bweight = (char)clamp_i(
+ (int)medge[i + edges_num].bweight +
(int)((angle > M_PI ? clamp_f(bevel_convex, 0, 1) :
clamp_f(bevel_convex, -1, 0)) *
255),
@@ -959,8 +960,8 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex
else if (do_shell) {
uint i;
/* flip vertex normals for copied verts */
- mv = mvert + numVerts;
- for (i = 0; i < numVerts; i++) {
+ mv = mvert + verts_num;
+ for (i = 0; i < verts_num; i++) {
negate_v3((float *)mesh_vert_normals[i]);
}
}
@@ -982,14 +983,14 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex
for (uint i = 0; i < rimVerts; i++) {
BKE_defvert_ensure_index(&result->dvert[new_vert_arr[i]], rim_defgrp_index)->weight =
1.0f;
- BKE_defvert_ensure_index(&result->dvert[(do_shell ? new_vert_arr[i] : i) + numVerts],
+ BKE_defvert_ensure_index(&result->dvert[(do_shell ? new_vert_arr[i] : i) + verts_num],
rim_defgrp_index)
->weight = 1.0f;
}
}
if (shell_defgrp_index != -1) {
- for (uint i = numVerts; i < result->totvert; i++) {
+ for (uint i = verts_num; i < result->totvert; i++) {
BKE_defvert_ensure_index(&result->dvert[i], shell_defgrp_index)->weight = 1.0f;
}
}
@@ -1014,7 +1015,7 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex
const bool do_side_normals = !BKE_mesh_vertex_normals_are_dirty(result);
/* annoying to allocate these since we only need the edge verts, */
float(*edge_vert_nos)[3] = do_side_normals ?
- MEM_calloc_arrayN(numVerts, sizeof(float[3]), __func__) :
+ MEM_calloc_arrayN(verts_num, sizeof(float[3]), __func__) :
NULL;
float nor[3];
#endif
@@ -1032,11 +1033,11 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex
/* add faces & edges */
origindex_edge = CustomData_get_layer(&result->edata, CD_ORIGINDEX);
- orig_ed = (origindex_edge) ? &origindex_edge[(numEdges * stride) + newEdges] : NULL;
- ed = &medge[(numEdges * stride) + newEdges]; /* start after copied edges */
+ orig_ed = (origindex_edge) ? &origindex_edge[(edges_num * stride) + newEdges] : NULL;
+ ed = &medge[(edges_num * stride) + newEdges]; /* start after copied edges */
for (i = 0; i < rimVerts; i++, ed++) {
ed->v1 = new_vert_arr[i];
- ed->v2 = (do_shell ? new_vert_arr[i] : i) + numVerts;
+ ed->v2 = (do_shell ? new_vert_arr[i] : i) + verts_num;
ed->flag |= ME_EDGEDRAW | ME_EDGERENDER;
if (orig_ed) {
@@ -1050,8 +1051,8 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex
}
/* faces */
- mp = mpoly + (numPolys * stride);
- ml = mloop + (numLoops * stride);
+ mp = mpoly + (polys_num * stride);
+ ml = mloop + (loops_num * stride);
j = 0;
for (i = 0; i < newPolys; i++, mp++) {
uint eidx = new_edge_arr[i];
@@ -1059,8 +1060,8 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex
int k1, k2;
bool flip;
- if (pidx >= numPolys) {
- pidx -= numPolys;
+ if (pidx >= polys_num) {
+ pidx -= polys_num;
flip = true;
}
else {
@@ -1071,8 +1072,8 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex
/* copy most of the face settings */
CustomData_copy_data(
- &mesh->pdata, &result->pdata, (int)pidx, (int)((numPolys * stride) + i), 1);
- mp->loopstart = (int)(j + (numLoops * stride));
+ &mesh->pdata, &result->pdata, (int)pidx, (int)((polys_num * stride) + i), 1);
+ mp->loopstart = (int)(j + (loops_num * stride));
mp->flag = mpoly[pidx].flag;
/* notice we use 'mp->totloop' which is later overwritten,
@@ -1087,39 +1088,39 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex
mp->totloop = 4;
CustomData_copy_data(
- &mesh->ldata, &result->ldata, k2, (int)((numLoops * stride) + j + 0), 1);
+ &mesh->ldata, &result->ldata, k2, (int)((loops_num * stride) + j + 0), 1);
CustomData_copy_data(
- &mesh->ldata, &result->ldata, k1, (int)((numLoops * stride) + j + 1), 1);
+ &mesh->ldata, &result->ldata, k1, (int)((loops_num * stride) + j + 1), 1);
CustomData_copy_data(
- &mesh->ldata, &result->ldata, k1, (int)((numLoops * stride) + j + 2), 1);
+ &mesh->ldata, &result->ldata, k1, (int)((loops_num * stride) + j + 2), 1);
CustomData_copy_data(
- &mesh->ldata, &result->ldata, k2, (int)((numLoops * stride) + j + 3), 1);
+ &mesh->ldata, &result->ldata, k2, (int)((loops_num * stride) + j + 3), 1);
if (flip == false) {
ml[j].v = ed->v1;
ml[j++].e = eidx;
ml[j].v = ed->v2;
- ml[j++].e = (numEdges * stride) + old_vert_arr[ed->v2] + newEdges;
+ ml[j++].e = (edges_num * stride) + old_vert_arr[ed->v2] + newEdges;
- ml[j].v = (do_shell ? ed->v2 : old_vert_arr[ed->v2]) + numVerts;
- ml[j++].e = (do_shell ? eidx : i) + numEdges;
+ ml[j].v = (do_shell ? ed->v2 : old_vert_arr[ed->v2]) + verts_num;
+ ml[j++].e = (do_shell ? eidx : i) + edges_num;
- ml[j].v = (do_shell ? ed->v1 : old_vert_arr[ed->v1]) + numVerts;
- ml[j++].e = (numEdges * stride) + old_vert_arr[ed->v1] + newEdges;
+ ml[j].v = (do_shell ? ed->v1 : old_vert_arr[ed->v1]) + verts_num;
+ ml[j++].e = (edges_num * stride) + old_vert_arr[ed->v1] + newEdges;
}
else {
ml[j].v = ed->v2;
ml[j++].e = eidx;
ml[j].v = ed->v1;
- ml[j++].e = (numEdges * stride) + old_vert_arr[ed->v1] + newEdges;
+ ml[j++].e = (edges_num * stride) + old_vert_arr[ed->v1] + newEdges;
- ml[j].v = (do_shell ? ed->v1 : old_vert_arr[ed->v1]) + numVerts;
- ml[j++].e = (do_shell ? eidx : i) + numEdges;
+ ml[j].v = (do_shell ? ed->v1 : old_vert_arr[ed->v1]) + verts_num;
+ ml[j++].e = (do_shell ? eidx : i) + edges_num;
- ml[j].v = (do_shell ? ed->v2 : old_vert_arr[ed->v2]) + numVerts;
- ml[j++].e = (numEdges * stride) + old_vert_arr[ed->v2] + newEdges;
+ ml[j].v = (do_shell ? ed->v2 : old_vert_arr[ed->v2]) + verts_num;
+ ml[j++].e = (edges_num * stride) + old_vert_arr[ed->v2] + newEdges;
}
if (origindex_edge) {
@@ -1141,7 +1142,7 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex
if (crease_inner) {
/* crease += crease_inner; without wrapping */
- char *cr = &(medge[numEdges + (do_shell ? eidx : i)].crease);
+ char *cr = &(medge[edges_num + (do_shell ? eidx : i)].crease);
int tcr = *cr + crease_inner;
*cr = tcr > 255 ? 255 : tcr;
}
@@ -1163,13 +1164,13 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex
#ifdef SOLIDIFY_SIDE_NORMALS
if (do_side_normals) {
const MEdge *ed_orig = medge;
- ed = medge + (numEdges * stride);
+ ed = medge + (edges_num * stride);
for (i = 0; i < rimVerts; i++, ed++, ed_orig++) {
float nor_cpy[3];
int k;
/* NOTE: only the first vertex (lower half of the index) is calculated. */
- BLI_assert(ed->v1 < numVerts);
+ BLI_assert(ed->v1 < verts_num);
normalize_v3_v3(nor_cpy, edge_vert_nos[ed_orig->v1]);
for (k = 0; k < 2; k++) { /* loop over both verts of the edge */
diff --git a/source/blender/modifiers/intern/MOD_solidify_nonmanifold.c b/source/blender/modifiers/intern/MOD_solidify_nonmanifold.c
index d896cab4688..8a84cd0a3bf 100644
--- a/source/blender/modifiers/intern/MOD_solidify_nonmanifold.c
+++ b/source/blender/modifiers/intern/MOD_solidify_nonmanifold.c
@@ -141,11 +141,11 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md,
MEdge *ed, *medge, *orig_medge;
MLoop *ml, *mloop, *orig_mloop;
MPoly *mp, *mpoly, *orig_mpoly;
- const uint numVerts = (uint)mesh->totvert;
- const uint numEdges = (uint)mesh->totedge;
- const uint numPolys = (uint)mesh->totpoly;
+ const uint verts_num = (uint)mesh->totvert;
+ const uint edges_num = (uint)mesh->totedge;
+ const uint polys_num = (uint)mesh->totpoly;
- if (numPolys == 0 && numVerts != 0) {
+ if (polys_num == 0 && verts_num != 0) {
return mesh;
}
@@ -193,28 +193,28 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md,
orig_mloop = mesh->mloop;
orig_mpoly = mesh->mpoly;
- uint numNewVerts = 0;
- uint numNewEdges = 0;
- uint numNewLoops = 0;
- uint numNewPolys = 0;
+ uint new_verts_num = 0;
+ uint new_edges_num = 0;
+ uint new_loops_num = 0;
+ uint new_polys_num = 0;
#define MOD_SOLIDIFY_EMPTY_TAG ((uint)-1)
/* Calculate only face normals. Copied because they are modified directly below. */
- float(*poly_nors)[3] = MEM_malloc_arrayN(numPolys, sizeof(float[3]), __func__);
- memcpy(poly_nors, BKE_mesh_poly_normals_ensure(mesh), sizeof(float[3]) * numPolys);
+ float(*poly_nors)[3] = MEM_malloc_arrayN(polys_num, sizeof(float[3]), __func__);
+ memcpy(poly_nors, BKE_mesh_poly_normals_ensure(mesh), sizeof(float[3]) * polys_num);
NewFaceRef *face_sides_arr = MEM_malloc_arrayN(
- numPolys * 2, sizeof(*face_sides_arr), "face_sides_arr in solidify");
+ polys_num * 2, sizeof(*face_sides_arr), "face_sides_arr in solidify");
bool *null_faces =
(smd->nonmanifold_offset_mode == MOD_SOLIDIFY_NONMANIFOLD_OFFSET_MODE_CONSTRAINTS) ?
- MEM_calloc_arrayN(numPolys, sizeof(*null_faces), "null_faces in solidify") :
+ MEM_calloc_arrayN(polys_num, sizeof(*null_faces), "null_faces in solidify") :
NULL;
uint largest_ngon = 3;
/* Calculate face to #NewFaceRef map. */
{
mp = orig_mpoly;
- for (uint i = 0; i < numPolys; i++, mp++) {
+ for (uint i = 0; i < polys_num; i++, mp++) {
/* Make normals for faces without area (should really be avoided though). */
if (len_squared_v3(poly_nors[i]) < 0.5f) {
MEdge *e = orig_medge + orig_mloop[mp->loopstart].e;
@@ -244,18 +244,18 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md,
}
/* add to final mesh face count */
if (do_shell) {
- numNewPolys += 2;
- numNewLoops += (uint)mp->totloop * 2;
+ new_polys_num += 2;
+ new_loops_num += (uint)mp->totloop * 2;
}
}
}
uint *edge_adj_faces_len = MEM_calloc_arrayN(
- numEdges, sizeof(*edge_adj_faces_len), "edge_adj_faces_len in solidify");
+ edges_num, sizeof(*edge_adj_faces_len), "edge_adj_faces_len in solidify");
/* Count for each edge how many faces it has adjacent. */
{
mp = orig_mpoly;
- for (uint i = 0; i < numPolys; i++, mp++) {
+ for (uint i = 0; i < polys_num; i++, mp++) {
ml = orig_mloop + mp->loopstart;
for (uint j = 0; j < mp->totloop; j++, ml++) {
edge_adj_faces_len[ml->e]++;
@@ -265,16 +265,16 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md,
/* Original edge to #NewEdgeRef map. */
NewEdgeRef ***orig_edge_data_arr = MEM_calloc_arrayN(
- numEdges, sizeof(*orig_edge_data_arr), "orig_edge_data_arr in solidify");
+ edges_num, sizeof(*orig_edge_data_arr), "orig_edge_data_arr in solidify");
/* Original edge length cache. */
float *orig_edge_lengths = MEM_calloc_arrayN(
- numEdges, sizeof(*orig_edge_lengths), "orig_edge_lengths in solidify");
+ edges_num, sizeof(*orig_edge_lengths), "orig_edge_lengths in solidify");
/* Edge groups for every original vert. */
EdgeGroup **orig_vert_groups_arr = MEM_calloc_arrayN(
- numVerts, sizeof(*orig_vert_groups_arr), "orig_vert_groups_arr in solidify");
+ verts_num, sizeof(*orig_vert_groups_arr), "orig_vert_groups_arr in solidify");
/* vertex map used to map duplicates. */
- uint *vm = MEM_malloc_arrayN(numVerts, sizeof(*vm), "orig_vert_map in solidify");
- for (uint i = 0; i < numVerts; i++) {
+ uint *vm = MEM_malloc_arrayN(verts_num, sizeof(*vm), "orig_vert_map in solidify");
+ for (uint i = 0; i < verts_num; i++) {
vm[i] = i;
}
@@ -286,12 +286,12 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md,
/* Vert edge adjacent map. */
OldVertEdgeRef **vert_adj_edges = MEM_calloc_arrayN(
- numVerts, sizeof(*vert_adj_edges), "vert_adj_edges in solidify");
+ verts_num, sizeof(*vert_adj_edges), "vert_adj_edges in solidify");
/* Original vertex positions (changed for degenerated geometry). */
float(*orig_mvert_co)[3] = MEM_malloc_arrayN(
- numVerts, sizeof(*orig_mvert_co), "orig_mvert_co in solidify");
+ verts_num, sizeof(*orig_mvert_co), "orig_mvert_co in solidify");
/* Fill in the original vertex positions. */
- for (uint i = 0; i < numVerts; i++) {
+ for (uint i = 0; i < verts_num; i++) {
orig_mvert_co[i][0] = orig_mvert[i].co[0];
orig_mvert_co[i][1] = orig_mvert[i].co[1];
orig_mvert_co[i][2] = orig_mvert[i].co[2];
@@ -300,12 +300,12 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md,
/* Create edge to #NewEdgeRef map. */
{
OldEdgeFaceRef **edge_adj_faces = MEM_calloc_arrayN(
- numEdges, sizeof(*edge_adj_faces), "edge_adj_faces in solidify");
+ edges_num, sizeof(*edge_adj_faces), "edge_adj_faces in solidify");
/* Create link_faces for edges. */
{
mp = orig_mpoly;
- for (uint i = 0; i < numPolys; i++, mp++) {
+ for (uint i = 0; i < polys_num; i++, mp++) {
ml = orig_mloop + mp->loopstart;
for (uint j = 0; j < mp->totloop; j++, ml++) {
const uint edge = ml->e;
@@ -342,19 +342,19 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md,
float edgedir[3] = {0, 0, 0};
uint *vert_adj_edges_len = MEM_calloc_arrayN(
- numVerts, sizeof(*vert_adj_edges_len), "vert_adj_edges_len in solidify");
+ verts_num, sizeof(*vert_adj_edges_len), "vert_adj_edges_len in solidify");
/* Calculate edge lengths and len vert_adj edges. */
{
bool *face_singularity = MEM_calloc_arrayN(
- numPolys, sizeof(*face_singularity), "face_sides_arr in solidify");
+ polys_num, sizeof(*face_singularity), "face_sides_arr in solidify");
const float merge_tolerance_sqr = smd->merge_tolerance * smd->merge_tolerance;
uint *combined_verts = MEM_calloc_arrayN(
- numVerts, sizeof(*combined_verts), "combined_verts in solidify");
+ verts_num, sizeof(*combined_verts), "combined_verts in solidify");
ed = orig_medge;
- for (uint i = 0; i < numEdges; i++, ed++) {
+ for (uint i = 0; i < edges_num; i++, ed++) {
if (edge_adj_faces_len[i] > 0) {
uint v1 = vm[ed->v1];
uint v2 = vm[ed->v2];
@@ -373,7 +373,7 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md,
/* This check is very slow. It would need the vertex edge links to get
* accelerated that are not yet available at this point. */
bool can_merge = true;
- for (uint k = 0; k < numEdges && can_merge; k++) {
+ for (uint k = 0; k < edges_num && can_merge; k++) {
if (k != i && edge_adj_faces_len[k] > 0 &&
(ELEM(vm[orig_medge[k].v1], v1, v2) != ELEM(vm[orig_medge[k].v2], v1, v2))) {
for (uint j = 0; j < edge_adj_faces[k]->faces_len && can_merge; j++) {
@@ -402,7 +402,7 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md,
(combined_verts[v2] + 1) /
(float)(combined_verts[v1] + combined_verts[v2] + 2));
add_v3_v3(orig_mvert_co[v1], edgedir);
- for (uint j = v2; j < numVerts; j++) {
+ for (uint j = v2; j < verts_num; j++) {
if (vm[j] == v2) {
vm[j] = v1;
}
@@ -412,7 +412,7 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md,
combined_verts[v1] += combined_verts[v2] + 1;
if (do_shell) {
- numNewLoops -= edge_adj_faces_len[i] * 2;
+ new_loops_num -= edge_adj_faces_len[i] * 2;
}
edge_adj_faces_len[i] = 0;
@@ -430,7 +430,7 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md,
}
/* remove zero faces in a second pass */
ed = orig_medge;
- for (uint i = 0; i < numEdges; i++, ed++) {
+ for (uint i = 0; i < edges_num; i++, ed++) {
const uint v1 = vm[ed->v1];
const uint v2 = vm[ed->v2];
if (v1 == v2 && edge_adj_faces[i]) {
@@ -449,14 +449,14 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md,
face_singularity[face] = true;
/* remove from final mesh poly count */
if (do_shell) {
- numNewPolys -= 2;
+ new_polys_num -= 2;
}
}
}
}
if (do_shell) {
- numNewLoops -= edge_adj_faces_len[i] * 2;
+ new_loops_num -= edge_adj_faces_len[i] * 2;
}
edge_adj_faces_len[i] = 0;
@@ -474,7 +474,7 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md,
/* Create vert_adj_edges for verts. */
{
ed = orig_medge;
- for (uint i = 0; i < numEdges; i++, ed++) {
+ for (uint i = 0; i < edges_num; i++, ed++) {
if (edge_adj_faces_len[i] > 0) {
const uint vs[2] = {vm[ed->v1], vm[ed->v2]};
uint invalid_edge_index = 0;
@@ -545,8 +545,8 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md,
}
/* remove from final face count */
if (do_shell) {
- numNewPolys -= 2 * j;
- numNewLoops -= 4 * j;
+ new_polys_num -= 2 * j;
+ new_loops_num -= 4 * j;
}
const uint len = i_adj_faces->faces_len + invalid_adj_faces->faces_len - 2 * j;
uint *adj_faces = MEM_malloc_arrayN(
@@ -595,7 +595,7 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md,
ed = orig_medge;
/* Iterate over edges and only check the faces around an edge for duplicates
* (performance optimization). */
- for (uint i = 0; i < numEdges; i++, ed++) {
+ for (uint i = 0; i < edges_num; i++, ed++) {
if (edge_adj_faces_len[i] > 0) {
const OldEdgeFaceRef *adj_faces = edge_adj_faces[i];
uint adj_len = adj_faces->faces_len;
@@ -674,7 +674,7 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md,
}
}
else if (e_adj_faces->used > 1) {
- for (uint n = 0; n < numEdges; n++) {
+ for (uint n = 0; n < edges_num; n++) {
if (edge_adj_faces[n] == e_adj_faces && edge_adj_faces_len[n] > 0) {
edge_adj_faces_len[n]--;
if (edge_adj_faces_len[n] == 0) {
@@ -689,8 +689,8 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md,
}
}
if (do_shell) {
- numNewPolys -= 2;
- numNewLoops -= 2 * (uint)del_loops;
+ new_polys_num -= 2;
+ new_loops_num -= 2 * (uint)del_loops;
}
break;
}
@@ -704,7 +704,7 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md,
/* Create #NewEdgeRef array. */
{
ed = orig_medge;
- for (uint i = 0; i < numEdges; i++, ed++) {
+ for (uint i = 0; i < edges_num; i++, ed++) {
const uint v1 = vm[ed->v1];
const uint v2 = vm[ed->v2];
if (edge_adj_faces_len[i] > 0) {
@@ -807,8 +807,8 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md,
(adj_faces_reversed[0] ? 1 : 0);
if (do_rim) {
/* Only add the loops parallel to the edge for now. */
- numNewLoops += 2;
- numNewPolys++;
+ new_loops_num += 2;
+ new_polys_num++;
}
}
@@ -864,13 +864,13 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md,
MEM_freeN(sorted_faces);
orig_edge_data_arr[i] = new_edges;
if (do_shell || (adj_len == 1 && do_rim)) {
- numNewEdges += new_edges_len;
+ new_edges_num += new_edges_len;
}
}
}
}
- for (uint i = 0; i < numEdges; i++) {
+ for (uint i = 0; i < edges_num; i++) {
if (edge_adj_faces[i]) {
if (edge_adj_faces[i]->used > 1) {
edge_adj_faces[i]->used--;
@@ -888,7 +888,7 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md,
/* Create sorted edge groups for every vert. */
{
OldVertEdgeRef **adj_edges_ptr = vert_adj_edges;
- for (uint i = 0; i < numVerts; i++, adj_edges_ptr++) {
+ for (uint i = 0; i < verts_num; i++, adj_edges_ptr++) {
if (*adj_edges_ptr != NULL && (*adj_edges_ptr)->edges_len >= 2) {
EdgeGroup *edge_groups;
@@ -1305,7 +1305,7 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md,
uint added = 0;
if (do_shell || (do_rim && !g->is_orig_closed)) {
BLI_assert(g->new_vert == MOD_SOLIDIFY_EMPTY_TAG);
- g->new_vert = numNewVerts++;
+ g->new_vert = new_verts_num++;
if (do_rim || (do_shell && g->split)) {
new_verts++;
contains_splits += (g->split != 0);
@@ -1321,23 +1321,23 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md,
last_added = added;
if (!(g + 1)->valid || g->topo_group != (g + 1)->topo_group) {
if (new_verts > 2) {
- numNewPolys++;
- numNewEdges += new_verts;
+ new_polys_num++;
+ new_edges_num += new_verts;
open_edges += (uint)(first_added < last_added);
open_edges -= (uint)(open_edges && !contains_open_splits);
if (do_shell && do_rim) {
- numNewLoops += new_verts * 2;
+ new_loops_num += new_verts * 2;
}
else if (do_shell) {
- numNewLoops += new_verts * 2 - open_edges;
+ new_loops_num += new_verts * 2 - open_edges;
}
else { // do_rim
- numNewLoops += new_verts * 2 + open_edges - contains_splits;
+ new_loops_num += new_verts * 2 + open_edges - contains_splits;
}
}
else if (new_verts == 2) {
- numNewEdges++;
- numNewLoops += 2u - (uint)(!(do_rim && do_shell) && contains_open_splits);
+ new_edges_num++;
+ new_loops_num += 2u - (uint)(!(do_rim && do_shell) && contains_open_splits);
}
new_verts = 0;
contains_open_splits = false;
@@ -1356,7 +1356,7 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md,
/* Free vert_adj_edges memory. */
{
uint i = 0;
- for (OldVertEdgeRef **p = vert_adj_edges; i < numVerts; i++, p++) {
+ for (OldVertEdgeRef **p = vert_adj_edges; i < verts_num; i++, p++) {
if (*p) {
MEM_freeN((*p)->edges);
MEM_freeN(*p);
@@ -1375,10 +1375,10 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md,
float *face_weight = NULL;
if (do_flat_faces) {
- face_weight = MEM_malloc_arrayN(numPolys, sizeof(*face_weight), "face_weight in solidify");
+ face_weight = MEM_malloc_arrayN(polys_num, sizeof(*face_weight), "face_weight in solidify");
mp = orig_mpoly;
- for (uint i = 0; i < numPolys; i++, mp++) {
+ for (uint i = 0; i < polys_num; i++, mp++) {
float scalar_vgroup = 1.0f;
int loopend = mp->loopstart + mp->totloop;
ml = orig_mloop + mp->loopstart;
@@ -1399,7 +1399,7 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md,
mv = orig_mvert;
gs_ptr = orig_vert_groups_arr;
- for (uint i = 0; i < numVerts; i++, mv++, gs_ptr++) {
+ for (uint i = 0; i < verts_num; i++, mv++, gs_ptr++) {
if (*gs_ptr) {
EdgeGroup *g = *gs_ptr;
for (uint j = 0; g->valid; j++, g++) {
@@ -1912,7 +1912,7 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md,
uint singularity_edges_len = 1;
singularity_edges = MEM_malloc_arrayN(
singularity_edges_len, sizeof(*singularity_edges), "singularity_edges in solidify");
- for (NewEdgeRef ***new_edges = orig_edge_data_arr; i < numEdges; i++, new_edges++) {
+ for (NewEdgeRef ***new_edges = orig_edge_data_arr; i < edges_num; i++, new_edges++) {
if (*new_edges && (do_shell || edge_adj_faces_len[i] == 1) && (**new_edges)->old_edge == i) {
for (NewEdgeRef **l = *new_edges; *l; l++) {
if ((*l)->link_edge_groups[0]->is_singularity &&
@@ -1940,12 +1940,12 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md,
singularity_edges[totsingularity][1] = v2;
totsingularity++;
if (edge_adj_faces_len[i] == 1 && do_rim) {
- numNewLoops -= 2;
- numNewPolys--;
+ new_loops_num -= 2;
+ new_polys_num--;
}
}
else {
- numNewEdges--;
+ new_edges_num--;
}
}
}
@@ -1954,8 +1954,12 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md,
}
/* Create Mesh *result with proper capacity. */
- result = BKE_mesh_new_nomain_from_template(
- mesh, (int)(numNewVerts), (int)(numNewEdges), 0, (int)(numNewLoops), (int)(numNewPolys));
+ result = BKE_mesh_new_nomain_from_template(mesh,
+ (int)(new_verts_num),
+ (int)(new_edges_num),
+ 0,
+ (int)(new_loops_num),
+ (int)(new_polys_num));
mpoly = result->mpoly;
mloop = result->mloop;
@@ -1997,7 +2001,7 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md,
/* Make_new_verts. */
{
gs_ptr = orig_vert_groups_arr;
- for (uint i = 0; i < numVerts; i++, gs_ptr++) {
+ for (uint i = 0; i < verts_num; i++, gs_ptr++) {
EdgeGroup *gs = *gs_ptr;
if (gs) {
EdgeGroup *g = gs;
@@ -2018,7 +2022,7 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md,
{
uint i = 0;
edge_index += totsingularity;
- for (NewEdgeRef ***new_edges = orig_edge_data_arr; i < numEdges; i++, new_edges++) {
+ for (NewEdgeRef ***new_edges = orig_edge_data_arr; i < edges_num; i++, new_edges++) {
if (*new_edges && (do_shell || edge_adj_faces_len[i] == 1) && (**new_edges)->old_edge == i) {
for (NewEdgeRef **l = *new_edges; *l; l++) {
if ((*l)->new_edge != MOD_SOLIDIFY_EMPTY_TAG) {
@@ -2089,7 +2093,7 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md,
* }
*/
gs_ptr = orig_vert_groups_arr;
- for (uint i = 0; i < numVerts; i++, gs_ptr++) {
+ for (uint i = 0; i < verts_num; i++, gs_ptr++) {
EdgeGroup *gs = *gs_ptr;
/* check if the vertex is present (may be dissolved because of proximity) */
if (gs) {
@@ -2110,7 +2114,7 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md,
{
gs_ptr = orig_vert_groups_arr;
mv = orig_mvert;
- for (uint i = 0; i < numVerts; i++, gs_ptr++, mv++) {
+ for (uint i = 0; i < verts_num; i++, gs_ptr++, mv++) {
EdgeGroup *gs = *gs_ptr;
if (gs) {
EdgeGroup *g = gs;
@@ -2317,7 +2321,7 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md,
/* Make boundary faces. */
if (do_rim) {
- for (uint i = 0; i < numEdges; i++) {
+ for (uint i = 0; i < edges_num; i++) {
if (edge_adj_faces_len[i] == 1 && orig_edge_data_arr[i] &&
(*orig_edge_data_arr[i])->old_edge == i) {
NewEdgeRef **new_edges = orig_edge_data_arr[i];
@@ -2473,7 +2477,7 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md,
largest_ngon * 2, sizeof(*face_verts), "face_verts in solidify");
uint *face_edges = MEM_malloc_arrayN(
largest_ngon * 2, sizeof(*face_edges), "face_edges in solidify");
- for (uint i = 0; i < numPolys * 2; i++, fr++) {
+ for (uint i = 0; i < polys_num * 2; i++, fr++) {
const uint loopstart = (uint)fr->face->loopstart;
uint totloop = (uint)fr->face->totloop;
uint valid_edges = 0;
@@ -2561,37 +2565,37 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md,
MEM_freeN(face_verts);
MEM_freeN(face_edges);
}
- if (edge_index != numNewEdges) {
+ if (edge_index != new_edges_num) {
BKE_modifier_set_error(ctx->object,
md,
"Internal Error: edges array wrong size: %u instead of %u",
- numNewEdges,
+ new_edges_num,
edge_index);
}
- if (poly_index != numNewPolys) {
+ if (poly_index != new_polys_num) {
BKE_modifier_set_error(ctx->object,
md,
"Internal Error: polys array wrong size: %u instead of %u",
- numNewPolys,
+ new_polys_num,
poly_index);
}
- if (loop_index != numNewLoops) {
+ if (loop_index != new_loops_num) {
BKE_modifier_set_error(ctx->object,
md,
"Internal Error: loops array wrong size: %u instead of %u",
- numNewLoops,
+ new_loops_num,
loop_index);
}
- BLI_assert(edge_index == numNewEdges);
- BLI_assert(poly_index == numNewPolys);
- BLI_assert(loop_index == numNewLoops);
+ BLI_assert(edge_index == new_edges_num);
+ BLI_assert(poly_index == new_polys_num);
+ BLI_assert(loop_index == new_loops_num);
/* Free remaining memory */
{
MEM_freeN(vm);
MEM_freeN(edge_adj_faces_len);
uint i = 0;
- for (EdgeGroup **p = orig_vert_groups_arr; i < numVerts; i++, p++) {
+ for (EdgeGroup **p = orig_vert_groups_arr; i < verts_num; i++, p++) {
if (*p) {
for (EdgeGroup *eg = *p; eg->valid; eg++) {
MEM_freeN(eg->edges);
@@ -2600,8 +2604,8 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md,
}
}
MEM_freeN(orig_vert_groups_arr);
- i = numEdges;
- for (NewEdgeRef ***p = orig_edge_data_arr + (numEdges - 1); i > 0; i--, p--) {
+ i = edges_num;
+ for (NewEdgeRef ***p = orig_edge_data_arr + (edges_num - 1); i > 0; i--, p--) {
if (*p && (**p)->old_edge == i - 1) {
for (NewEdgeRef **l = *p; *l; l++) {
MEM_freeN(*l);
@@ -2612,7 +2616,7 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md,
MEM_freeN(orig_edge_data_arr);
MEM_freeN(orig_edge_lengths);
i = 0;
- for (NewFaceRef *p = face_sides_arr; i < numPolys * 2; i++, p++) {
+ for (NewFaceRef *p = face_sides_arr; i < polys_num * 2; i++, p++) {
MEM_freeN(p->link_edges);
}
MEM_freeN(face_sides_arr);
diff --git a/source/blender/modifiers/intern/MOD_subsurf.c b/source/blender/modifiers/intern/MOD_subsurf.c
index 973009236ec..249d09e5d2e 100644
--- a/source/blender/modifiers/intern/MOD_subsurf.c
+++ b/source/blender/modifiers/intern/MOD_subsurf.c
@@ -283,7 +283,7 @@ static void deformMatrices(ModifierData *md,
Mesh *mesh,
float (*vertex_cos)[3],
float (*deform_matrices)[3][3],
- int num_verts)
+ int verts_num)
{
#if !defined(WITH_OPENSUBDIV)
BKE_modifier_set_error(ctx->object, md, "Disabled, built without OpenSubdiv");
@@ -307,7 +307,7 @@ static void deformMatrices(ModifierData *md,
/* Happens on bad topology, but also on empty input mesh. */
return;
}
- BKE_subdiv_deform_coarse_vertices(subdiv, mesh, vertex_cos, num_verts);
+ BKE_subdiv_deform_coarse_vertices(subdiv, mesh, vertex_cos, verts_num);
if (subdiv != runtime_data->subdiv) {
BKE_subdiv_free(subdiv);
}
diff --git a/source/blender/modifiers/intern/MOD_surface.c b/source/blender/modifiers/intern/MOD_surface.c
index 4ca2e67c334..3e75e325e44 100644
--- a/source/blender/modifiers/intern/MOD_surface.c
+++ b/source/blender/modifiers/intern/MOD_surface.c
@@ -83,9 +83,7 @@ static void freeData(ModifierData *md)
}
}
-static bool dependsOnTime(struct Scene *UNUSED(scene),
- ModifierData *UNUSED(md),
- const int UNUSED(dag_eval_mode))
+static bool dependsOnTime(struct Scene *UNUSED(scene), ModifierData *UNUSED(md))
{
return true;
}
@@ -94,7 +92,7 @@ static void deformVerts(ModifierData *md,
const ModifierEvalContext *ctx,
Mesh *mesh,
float (*vertexCos)[3],
- int numVerts)
+ int verts_num)
{
SurfaceModifierData *surmd = (SurfaceModifierData *)md;
const int cfra = (int)DEG_get_ctime(ctx->depsgraph);
@@ -116,7 +114,7 @@ static void deformVerts(ModifierData *md,
surmd->mesh = (Mesh *)BKE_id_copy_ex(NULL, (ID *)mesh, NULL, LIB_ID_COPY_LOCALIZE);
}
else {
- surmd->mesh = MOD_deform_mesh_eval_get(ctx->object, NULL, NULL, NULL, numVerts, false, false);
+ surmd->mesh = MOD_deform_mesh_eval_get(ctx->object, NULL, NULL, NULL, verts_num, false, false);
}
if (!ctx->object->pd) {
@@ -125,7 +123,7 @@ static void deformVerts(ModifierData *md,
}
if (surmd->mesh) {
- uint numverts = 0, i = 0;
+ uint mesh_verts_num = 0, i = 0;
int init = 0;
float *vec;
MVert *x, *v;
@@ -133,9 +131,9 @@ static void deformVerts(ModifierData *md,
BKE_mesh_vert_coords_apply(surmd->mesh, vertexCos);
BKE_mesh_calc_normals(surmd->mesh);
- numverts = surmd->mesh->totvert;
+ mesh_verts_num = surmd->mesh->totvert;
- if (numverts != surmd->numverts || surmd->x == NULL || surmd->v == NULL ||
+ if (mesh_verts_num != surmd->verts_num || surmd->x == NULL || surmd->v == NULL ||
cfra != surmd->cfra + 1) {
if (surmd->x) {
MEM_freeN(surmd->x);
@@ -146,16 +144,16 @@ static void deformVerts(ModifierData *md,
surmd->v = NULL;
}
- surmd->x = MEM_calloc_arrayN(numverts, sizeof(MVert), "MVert");
- surmd->v = MEM_calloc_arrayN(numverts, sizeof(MVert), "MVert");
+ surmd->x = MEM_calloc_arrayN(mesh_verts_num, sizeof(MVert), "MVert");
+ surmd->v = MEM_calloc_arrayN(mesh_verts_num, sizeof(MVert), "MVert");
- surmd->numverts = numverts;
+ surmd->verts_num = mesh_verts_num;
init = 1;
}
/* convert to global coordinates and calculate velocity */
- for (i = 0, x = surmd->x, v = surmd->v; i < numverts; i++, x++, v++) {
+ for (i = 0, x = surmd->x, v = surmd->v; i < mesh_verts_num; i++, x++, v++) {
vec = surmd->mesh->mvert[i].co;
mul_m4_v3(ctx->object->obmat, vec);
@@ -210,7 +208,7 @@ static void blendRead(BlendDataReader *UNUSED(reader), ModifierData *md)
surmd->bvhtree = NULL;
surmd->x = NULL;
surmd->v = NULL;
- surmd->numverts = 0;
+ surmd->verts_num = 0;
}
ModifierTypeInfo modifierType_Surface = {
diff --git a/source/blender/modifiers/intern/MOD_surfacedeform.c b/source/blender/modifiers/intern/MOD_surfacedeform.c
index 6926893e188..a80918b8d2b 100644
--- a/source/blender/modifiers/intern/MOD_surfacedeform.c
+++ b/source/blender/modifiers/intern/MOD_surfacedeform.c
@@ -135,7 +135,7 @@ typedef struct SDefBindPoly {
/** Index of the input polygon. */
uint index;
/** Number of vertices in this face. */
- uint numverts;
+ uint verts_num;
/**
* This polygons loop-start.
* \note that we could look this up from the polygon.
@@ -152,8 +152,8 @@ typedef struct SDefBindPoly {
typedef struct SDefBindWeightData {
SDefBindPoly *bind_polys;
- uint numpoly;
- uint numbinds;
+ uint polys_num;
+ uint binds_num;
} SDefBindWeightData;
typedef struct SDefDeformData {
@@ -209,9 +209,9 @@ static void freeData(ModifierData *md)
SurfaceDeformModifierData *smd = (SurfaceDeformModifierData *)md;
if (smd->verts) {
- for (int i = 0; i < smd->num_bind_verts; i++) {
+ for (int i = 0; i < smd->bind_verts_num; i++) {
if (smd->verts[i].binds) {
- for (int j = 0; j < smd->verts[i].numbinds; j++) {
+ for (int j = 0; j < smd->verts[i].binds_num; j++) {
MEM_SAFE_FREE(smd->verts[i].binds[j].vert_inds);
MEM_SAFE_FREE(smd->verts[i].binds[j].vert_weights);
}
@@ -234,11 +234,11 @@ static void copyData(const ModifierData *md, ModifierData *target, const int fla
if (smd->verts) {
tsmd->verts = MEM_dupallocN(smd->verts);
- for (int i = 0; i < smd->num_bind_verts; i++) {
+ for (int i = 0; i < smd->bind_verts_num; i++) {
if (smd->verts[i].binds) {
tsmd->verts[i].binds = MEM_dupallocN(smd->verts[i].binds);
- for (int j = 0; j < smd->verts[i].numbinds; j++) {
+ for (int j = 0; j < smd->verts[i].binds_num; j++) {
if (smd->verts[i].binds[j].vert_inds) {
tsmd->verts[i].binds[j].vert_inds = MEM_dupallocN(smd->verts[i].binds[j].vert_inds);
}
@@ -283,8 +283,8 @@ static void freeAdjacencyMap(SDefAdjacencyArray *const vert_edges,
static int buildAdjacencyMap(const MPoly *poly,
const MEdge *edge,
const MLoop *const mloop,
- const uint numpoly,
- const uint numedges,
+ const uint polys_num,
+ const uint edges_num,
SDefAdjacencyArray *const vert_edges,
SDefAdjacency *adj,
SDefEdgePolys *const edge_polys)
@@ -292,7 +292,7 @@ static int buildAdjacencyMap(const MPoly *poly,
const MLoop *loop;
/* Find polygons adjacent to edges. */
- for (int i = 0; i < numpoly; i++, poly++) {
+ for (int i = 0; i < polys_num; i++, poly++) {
loop = &mloop[poly->loopstart];
for (int j = 0; j < poly->totloop; j++, loop++) {
@@ -312,7 +312,7 @@ static int buildAdjacencyMap(const MPoly *poly,
}
/* Find edges adjacent to vertices */
- for (int i = 0; i < numedges; i++, edge++) {
+ for (int i = 0; i < edges_num; i++, edge++) {
adj->next = vert_edges[edge->v1].first;
adj->index = i;
vert_edges[edge->v1].first = adj;
@@ -457,7 +457,7 @@ static void freeBindData(SDefBindWeightData *const bwdata)
SDefBindPoly *bpoly = bwdata->bind_polys;
if (bwdata->bind_polys) {
- for (int i = 0; i < bwdata->numpoly; bpoly++, i++) {
+ for (int i = 0; i < bwdata->polys_num; bpoly++, i++) {
MEM_SAFE_FREE(bpoly->coords);
MEM_SAFE_FREE(bpoly->coords_v2);
}
@@ -498,9 +498,9 @@ BLI_INLINE SDefBindWeightData *computeBindWeights(SDefBindCalcData *const data,
return NULL;
}
- bwdata->numpoly = data->vert_edges[nearest].num / 2;
+ bwdata->polys_num = data->vert_edges[nearest].num / 2;
- bpoly = MEM_calloc_arrayN(bwdata->numpoly, sizeof(*bpoly), "SDefBindPoly");
+ bpoly = MEM_calloc_arrayN(bwdata->polys_num, sizeof(*bpoly), "SDefBindPoly");
if (bpoly == NULL) {
freeBindData(bwdata);
data->success = MOD_SDEF_BIND_RESULT_MEM_ERR;
@@ -518,7 +518,7 @@ BLI_INLINE SDefBindWeightData *computeBindWeights(SDefBindCalcData *const data,
{
bpoly = bwdata->bind_polys;
- for (int j = 0; j < bwdata->numpoly; bpoly++, j++) {
+ for (int j = 0; j < bwdata->polys_num; bpoly++, j++) {
/* If coords isn't allocated, we have reached the first uninitialized `bpoly`. */
if ((bpoly->index == edge_polys[edge_ind].polys[i]) || (!bpoly->coords)) {
break;
@@ -541,7 +541,7 @@ BLI_INLINE SDefBindWeightData *computeBindWeights(SDefBindCalcData *const data,
poly = &data->mpoly[bpoly->index];
loop = &data->mloop[poly->loopstart];
- bpoly->numverts = poly->totloop;
+ bpoly->verts_num = poly->totloop;
bpoly->loopstart = poly->loopstart;
bpoly->coords = MEM_malloc_arrayN(
@@ -719,7 +719,7 @@ BLI_INLINE SDefBindWeightData *computeBindWeights(SDefBindCalcData *const data,
}
}
- avg_point_dist /= bwdata->numpoly;
+ avg_point_dist /= bwdata->polys_num;
/* If weights 1 and 2 are not infinite, loop over all adjacent edges again,
* and build adjacency dependent angle data (depends on all polygons having been computed) */
@@ -736,7 +736,7 @@ BLI_INLINE SDefBindWeightData *computeBindWeights(SDefBindCalcData *const data,
/* Find bind polys corresponding to the edge's adjacent polys */
bpoly = bwdata->bind_polys;
- for (int i = 0, j = 0; (i < bwdata->numpoly) && (j < epolys->num); bpoly++, i++) {
+ for (int i = 0, j = 0; (i < bwdata->polys_num) && (j < epolys->num); bpoly++, i++) {
if (ELEM(bpoly->index, epolys->polys[0], epolys->polys[1])) {
bpolys[j] = bpoly;
@@ -776,7 +776,7 @@ BLI_INLINE SDefBindWeightData *computeBindWeights(SDefBindCalcData *const data,
if (!inf_weight_flags) {
bpoly = bwdata->bind_polys;
- for (int i = 0; i < bwdata->numpoly; bpoly++, i++) {
+ for (int i = 0; i < bwdata->polys_num; bpoly++, i++) {
float corner_angle_weights[2];
float scale_weight, sqr, inv_sqr;
@@ -856,7 +856,7 @@ BLI_INLINE SDefBindWeightData *computeBindWeights(SDefBindCalcData *const data,
else if (!(inf_weight_flags & MOD_SDEF_INFINITE_WEIGHT_DIST)) {
bpoly = bwdata->bind_polys;
- for (int i = 0; i < bwdata->numpoly; bpoly++, i++) {
+ for (int i = 0; i < bwdata->polys_num; bpoly++, i++) {
/* Scale the point distance weight by average point distance, and introduce falloff */
bpoly->weight_dist /= avg_point_dist;
bpoly->weight_dist = powf(bpoly->weight_dist, data->falloff);
@@ -871,7 +871,7 @@ BLI_INLINE SDefBindWeightData *computeBindWeights(SDefBindCalcData *const data,
/* Final loop, to compute actual weights */
bpoly = bwdata->bind_polys;
- for (int i = 0; i < bwdata->numpoly; bpoly++, i++) {
+ for (int i = 0; i < bwdata->polys_num; bpoly++, i++) {
/* Weight computation from components */
if (inf_weight_flags & MOD_SDEF_INFINITE_WEIGHT_DIST) {
bpoly->weight = bpoly->weight_dist < FLT_EPSILON ? 1.0f : 0.0f;
@@ -898,7 +898,7 @@ BLI_INLINE SDefBindWeightData *computeBindWeights(SDefBindCalcData *const data,
bpoly = bwdata->bind_polys;
- for (int i = 0; i < bwdata->numpoly; bpoly++, i++) {
+ for (int i = 0; i < bwdata->polys_num; bpoly++, i++) {
bpoly->weight /= tot_weight;
/* Evaluate if this poly is relevant to bind */
@@ -907,15 +907,15 @@ BLI_INLINE SDefBindWeightData *computeBindWeights(SDefBindCalcData *const data,
* should be negligible... */
if (bpoly->weight >= FLT_EPSILON) {
if (bpoly->inside) {
- bwdata->numbinds += 1;
+ bwdata->binds_num += 1;
}
else {
if (bpoly->dominant_angle_weight < FLT_EPSILON ||
1.0f - bpoly->dominant_angle_weight < FLT_EPSILON) {
- bwdata->numbinds += 1;
+ bwdata->binds_num += 1;
}
else {
- bwdata->numbinds += 2;
+ bwdata->binds_num += 2;
}
}
}
@@ -958,7 +958,7 @@ static void bindVert(void *__restrict userdata,
if (data->success != MOD_SDEF_BIND_RESULT_SUCCESS) {
sdvert->binds = NULL;
- sdvert->numbinds = 0;
+ sdvert->binds_num = 0;
return;
}
@@ -975,7 +975,7 @@ static void bindVert(void *__restrict userdata,
if (weight <= 0) {
sdvert->binds = NULL;
- sdvert->numbinds = 0;
+ sdvert->binds_num = 0;
return;
}
}
@@ -985,53 +985,53 @@ static void bindVert(void *__restrict userdata,
if (bwdata == NULL) {
sdvert->binds = NULL;
- sdvert->numbinds = 0;
+ sdvert->binds_num = 0;
return;
}
- sdvert->binds = MEM_calloc_arrayN(bwdata->numbinds, sizeof(*sdvert->binds), "SDefVertBindData");
+ sdvert->binds = MEM_calloc_arrayN(bwdata->binds_num, sizeof(*sdvert->binds), "SDefVertBindData");
if (sdvert->binds == NULL) {
data->success = MOD_SDEF_BIND_RESULT_MEM_ERR;
- sdvert->numbinds = 0;
+ sdvert->binds_num = 0;
return;
}
- sdvert->numbinds = bwdata->numbinds;
+ sdvert->binds_num = bwdata->binds_num;
sdbind = sdvert->binds;
bpoly = bwdata->bind_polys;
- for (int i = 0; i < bwdata->numbinds; bpoly++) {
+ for (int i = 0; i < bwdata->binds_num; bpoly++) {
if (bpoly->weight >= FLT_EPSILON) {
if (bpoly->inside) {
const MLoop *loop = &data->mloop[bpoly->loopstart];
sdbind->influence = bpoly->weight;
- sdbind->numverts = bpoly->numverts;
+ sdbind->verts_num = bpoly->verts_num;
sdbind->mode = MOD_SDEF_MODE_NGON;
sdbind->vert_weights = MEM_malloc_arrayN(
- bpoly->numverts, sizeof(*sdbind->vert_weights), "SDefNgonVertWeights");
+ bpoly->verts_num, sizeof(*sdbind->vert_weights), "SDefNgonVertWeights");
if (sdbind->vert_weights == NULL) {
data->success = MOD_SDEF_BIND_RESULT_MEM_ERR;
return;
}
sdbind->vert_inds = MEM_malloc_arrayN(
- bpoly->numverts, sizeof(*sdbind->vert_inds), "SDefNgonVertInds");
+ bpoly->verts_num, sizeof(*sdbind->vert_inds), "SDefNgonVertInds");
if (sdbind->vert_inds == NULL) {
data->success = MOD_SDEF_BIND_RESULT_MEM_ERR;
return;
}
interp_weights_poly_v2(
- sdbind->vert_weights, bpoly->coords_v2, bpoly->numverts, bpoly->point_v2);
+ sdbind->vert_weights, bpoly->coords_v2, bpoly->verts_num, bpoly->point_v2);
/* Re-project vert based on weights and original poly verts,
* to reintroduce poly non-planarity */
zero_v3(point_co_proj);
- for (int j = 0; j < bpoly->numverts; j++, loop++) {
+ for (int j = 0; j < bpoly->verts_num; j++, loop++) {
madd_v3_v3fl(point_co_proj, bpoly->coords[j], sdbind->vert_weights[j]);
sdbind->vert_inds[j] = loop->v;
}
@@ -1048,7 +1048,7 @@ static void bindVert(void *__restrict userdata,
if (1.0f - bpoly->dominant_angle_weight >= FLT_EPSILON) {
sdbind->influence = bpoly->weight * (1.0f - bpoly->dominant_angle_weight);
- sdbind->numverts = bpoly->numverts;
+ sdbind->verts_num = bpoly->verts_num;
sdbind->mode = MOD_SDEF_MODE_CENTROID;
sdbind->vert_weights = MEM_malloc_arrayN(
@@ -1059,7 +1059,7 @@ static void bindVert(void *__restrict userdata,
}
sdbind->vert_inds = MEM_malloc_arrayN(
- bpoly->numverts, sizeof(*sdbind->vert_inds), "SDefCentVertInds");
+ bpoly->verts_num, sizeof(*sdbind->vert_inds), "SDefCentVertInds");
if (sdbind->vert_inds == NULL) {
data->success = MOD_SDEF_BIND_RESULT_MEM_ERR;
return;
@@ -1068,7 +1068,7 @@ static void bindVert(void *__restrict userdata,
sortPolyVertsEdge(sdbind->vert_inds,
&data->mloop[bpoly->loopstart],
bpoly->edge_inds[bpoly->dominant_edge],
- bpoly->numverts);
+ bpoly->verts_num);
copy_v3_v3(v1, data->targetCos[sdbind->vert_inds[0]]);
copy_v3_v3(v2, data->targetCos[sdbind->vert_inds[1]]);
@@ -1095,7 +1095,7 @@ static void bindVert(void *__restrict userdata,
if (bpoly->dominant_angle_weight >= FLT_EPSILON) {
sdbind->influence = bpoly->weight * bpoly->dominant_angle_weight;
- sdbind->numverts = bpoly->numverts;
+ sdbind->verts_num = bpoly->verts_num;
sdbind->mode = MOD_SDEF_MODE_LOOPTRI;
sdbind->vert_weights = MEM_malloc_arrayN(
@@ -1106,7 +1106,7 @@ static void bindVert(void *__restrict userdata,
}
sdbind->vert_inds = MEM_malloc_arrayN(
- bpoly->numverts, sizeof(*sdbind->vert_inds), "SDefTriVertInds");
+ bpoly->verts_num, sizeof(*sdbind->vert_inds), "SDefTriVertInds");
if (sdbind->vert_inds == NULL) {
data->success = MOD_SDEF_BIND_RESULT_MEM_ERR;
return;
@@ -1115,7 +1115,7 @@ static void bindVert(void *__restrict userdata,
sortPolyVertsTri(sdbind->vert_inds,
&data->mloop[bpoly->loopstart],
bpoly->edge_vert_inds[0],
- bpoly->numverts);
+ bpoly->verts_num);
copy_v3_v3(v1, data->targetCos[sdbind->vert_inds[0]]);
copy_v3_v3(v2, data->targetCos[sdbind->vert_inds[1]]);
@@ -1149,25 +1149,25 @@ static void bindVert(void *__restrict userdata,
/* Remove vertices without bind data from the bind array. */
static void compactSparseBinds(SurfaceDeformModifierData *smd)
{
- smd->num_bind_verts = 0;
+ smd->bind_verts_num = 0;
- for (uint i = 0; i < smd->num_mesh_verts; i++) {
- if (smd->verts[i].numbinds > 0) {
- smd->verts[smd->num_bind_verts++] = smd->verts[i];
+ for (uint i = 0; i < smd->mesh_verts_num; i++) {
+ if (smd->verts[i].binds_num > 0) {
+ smd->verts[smd->bind_verts_num++] = smd->verts[i];
}
}
smd->verts = MEM_reallocN_id(
- smd->verts, sizeof(*smd->verts) * smd->num_bind_verts, "SDefBindVerts (sparse)");
+ smd->verts, sizeof(*smd->verts) * smd->bind_verts_num, "SDefBindVerts (sparse)");
}
static bool surfacedeformBind(Object *ob,
SurfaceDeformModifierData *smd_orig,
SurfaceDeformModifierData *smd_eval,
float (*vertexCos)[3],
- uint numverts,
- uint tnumpoly,
- uint tnumverts,
+ uint verts_num,
+ uint tpolys_num,
+ uint tverts_num,
Mesh *target,
Mesh *mesh)
{
@@ -1176,26 +1176,26 @@ static bool surfacedeformBind(Object *ob,
const MPoly *mpoly = target->mpoly;
const MEdge *medge = target->medge;
const MLoop *mloop = target->mloop;
- uint tnumedges = target->totedge;
+ uint tedges_num = target->totedge;
int adj_result;
SDefAdjacencyArray *vert_edges;
SDefAdjacency *adj_array;
SDefEdgePolys *edge_polys;
- vert_edges = MEM_calloc_arrayN(tnumverts, sizeof(*vert_edges), "SDefVertEdgeMap");
+ vert_edges = MEM_calloc_arrayN(tverts_num, sizeof(*vert_edges), "SDefVertEdgeMap");
if (vert_edges == NULL) {
BKE_modifier_set_error(ob, (ModifierData *)smd_eval, "Out of memory");
return false;
}
- adj_array = MEM_malloc_arrayN(tnumedges, 2 * sizeof(*adj_array), "SDefVertEdge");
+ adj_array = MEM_malloc_arrayN(tedges_num, 2 * sizeof(*adj_array), "SDefVertEdge");
if (adj_array == NULL) {
BKE_modifier_set_error(ob, (ModifierData *)smd_eval, "Out of memory");
MEM_freeN(vert_edges);
return false;
}
- edge_polys = MEM_calloc_arrayN(tnumedges, sizeof(*edge_polys), "SDefEdgeFaceMap");
+ edge_polys = MEM_calloc_arrayN(tedges_num, sizeof(*edge_polys), "SDefEdgeFaceMap");
if (edge_polys == NULL) {
BKE_modifier_set_error(ob, (ModifierData *)smd_eval, "Out of memory");
MEM_freeN(vert_edges);
@@ -1203,7 +1203,7 @@ static bool surfacedeformBind(Object *ob,
return false;
}
- smd_orig->verts = MEM_malloc_arrayN(numverts, sizeof(*smd_orig->verts), "SDefBindVerts");
+ smd_orig->verts = MEM_malloc_arrayN(verts_num, sizeof(*smd_orig->verts), "SDefBindVerts");
if (smd_orig->verts == NULL) {
BKE_modifier_set_error(ob, (ModifierData *)smd_eval, "Out of memory");
freeAdjacencyMap(vert_edges, adj_array, edge_polys);
@@ -1220,7 +1220,7 @@ static bool surfacedeformBind(Object *ob,
}
adj_result = buildAdjacencyMap(
- mpoly, medge, mloop, tnumpoly, tnumedges, vert_edges, adj_array, edge_polys);
+ mpoly, medge, mloop, tpolys_num, tedges_num, vert_edges, adj_array, edge_polys);
if (adj_result == MOD_SDEF_BIND_RESULT_NONMANY_ERR) {
BKE_modifier_set_error(
@@ -1232,8 +1232,8 @@ static bool surfacedeformBind(Object *ob,
return false;
}
- smd_orig->num_mesh_verts = numverts;
- smd_orig->numpoly = tnumpoly;
+ smd_orig->mesh_verts_num = verts_num;
+ smd_orig->polys_num = tpolys_num;
int defgrp_index;
MDeformVert *dvert;
@@ -1249,7 +1249,7 @@ static bool surfacedeformBind(Object *ob,
.medge = medge,
.mloop = mloop,
.looptri = BKE_mesh_runtime_looptri_ensure(target),
- .targetCos = MEM_malloc_arrayN(tnumverts, sizeof(float[3]), "SDefTargetBindVertArray"),
+ .targetCos = MEM_malloc_arrayN(tverts_num, sizeof(float[3]), "SDefTargetBindVertArray"),
.bind_verts = smd_orig->verts,
.vertexCos = vertexCos,
.falloff = smd_orig->falloff,
@@ -1268,14 +1268,14 @@ static bool surfacedeformBind(Object *ob,
invert_m4_m4(data.imat, smd_orig->mat);
- for (int i = 0; i < tnumverts; i++) {
+ for (int i = 0; i < tverts_num; i++) {
mul_v3_m4v3(data.targetCos[i], smd_orig->mat, mvert[i].co);
}
TaskParallelSettings settings;
BLI_parallel_range_settings_defaults(&settings);
- settings.use_threading = (numverts > 10000);
- BLI_task_parallel_range(0, numverts, &data, bindVert, &settings);
+ settings.use_threading = (verts_num > 10000);
+ BLI_task_parallel_range(0, verts_num, &data, bindVert, &settings);
MEM_freeN(data.targetCos);
@@ -1283,7 +1283,7 @@ static bool surfacedeformBind(Object *ob,
compactSparseBinds(smd_orig);
}
else {
- smd_orig->num_bind_verts = numverts;
+ smd_orig->bind_verts_num = verts_num;
}
if (data.success == MOD_SDEF_BIND_RESULT_MEM_ERR) {
@@ -1311,7 +1311,7 @@ static bool surfacedeformBind(Object *ob,
BKE_modifier_set_error(ob, (ModifierData *)smd_eval, "Target contains invalid polygons");
freeData((ModifierData *)smd_orig);
}
- else if (smd_orig->num_bind_verts == 0 || !smd_orig->verts) {
+ else if (smd_orig->bind_verts_num == 0 || !smd_orig->verts) {
data.success = MOD_SDEF_BIND_RESULT_GENERIC_ERR;
BKE_modifier_set_error(ob, (ModifierData *)smd_eval, "No vertices were bound");
freeData((ModifierData *)smd_orig);
@@ -1329,7 +1329,7 @@ static void deformVert(void *__restrict userdata,
{
const SDefDeformData *const data = (SDefDeformData *)userdata;
const SDefBind *sdbind = data->bind_verts[index].binds;
- const int num_binds = data->bind_verts[index].numbinds;
+ const int sdbind_num = data->bind_verts[index].binds_num;
const unsigned int vertex_idx = data->bind_verts[index].vertex_idx;
float *const vertexCos = data->vertexCos[vertex_idx];
float norm[3], temp[3], offset[3];
@@ -1355,8 +1355,8 @@ static void deformVert(void *__restrict userdata,
/* Allocate a `coords_buffer` that fits all the temp-data. */
int max_verts = 0;
- for (int j = 0; j < num_binds; j++) {
- max_verts = MAX2(max_verts, sdbind[j].numverts);
+ for (int j = 0; j < sdbind_num; j++) {
+ max_verts = MAX2(max_verts, sdbind[j].verts_num);
}
const bool big_buffer = max_verts > 256;
@@ -1369,12 +1369,12 @@ static void deformVert(void *__restrict userdata,
coords_buffer = BLI_array_alloca(coords_buffer, max_verts);
}
- for (int j = 0; j < num_binds; j++, sdbind++) {
- for (int k = 0; k < sdbind->numverts; k++) {
+ for (int j = 0; j < sdbind_num; j++, sdbind++) {
+ for (int k = 0; k < sdbind->verts_num; k++) {
copy_v3_v3(coords_buffer[k], data->targetCos[sdbind->vert_inds[k]]);
}
- normal_poly_v3(norm, coords_buffer, sdbind->numverts);
+ normal_poly_v3(norm, coords_buffer, sdbind->verts_num);
zero_v3(temp);
switch (sdbind->mode) {
@@ -1388,7 +1388,7 @@ static void deformVert(void *__restrict userdata,
/* ---------- ngon mode ---------- */
case MOD_SDEF_MODE_NGON: {
- for (int k = 0; k < sdbind->numverts; k++) {
+ for (int k = 0; k < sdbind->verts_num; k++) {
madd_v3_v3fl(temp, coords_buffer[k], sdbind->vert_weights[k]);
}
break;
@@ -1397,7 +1397,7 @@ static void deformVert(void *__restrict userdata,
/* ---------- centroid mode ---------- */
case MOD_SDEF_MODE_CENTROID: {
float cent[3];
- mid_v3_v3_array(cent, coords_buffer, sdbind->numverts);
+ mid_v3_v3_array(cent, coords_buffer, sdbind->verts_num);
madd_v3_v3fl(temp, data->targetCos[sdbind->vert_inds[0]], sdbind->vert_weights[0]);
madd_v3_v3fl(temp, data->targetCos[sdbind->vert_inds[1]], sdbind->vert_weights[1]);
@@ -1425,13 +1425,13 @@ static void deformVert(void *__restrict userdata,
static void surfacedeformModifier_do(ModifierData *md,
const ModifierEvalContext *ctx,
float (*vertexCos)[3],
- uint numverts,
+ uint verts_num,
Object *ob,
Mesh *mesh)
{
SurfaceDeformModifierData *smd = (SurfaceDeformModifierData *)md;
Mesh *target;
- uint tnumverts, tnumpoly;
+ uint tverts_num, tpolys_num;
/* Exit function if bind flag is not set (free bind data if any). */
if (!(smd->flags & MOD_SDEF_BIND)) {
@@ -1453,8 +1453,8 @@ static void surfacedeformModifier_do(ModifierData *md,
return;
}
- tnumverts = BKE_mesh_wrapper_vert_len(target);
- tnumpoly = BKE_mesh_wrapper_poly_len(target);
+ tverts_num = BKE_mesh_wrapper_vert_len(target);
+ tpolys_num = BKE_mesh_wrapper_poly_len(target);
/* If not bound, execute bind. */
if (smd->verts == NULL) {
@@ -1474,7 +1474,7 @@ static void surfacedeformModifier_do(ModifierData *md,
BKE_mesh_wrapper_ensure_mdata(target);
if (!surfacedeformBind(
- ob, smd_orig, smd, vertexCos, numverts, tnumpoly, tnumverts, target, mesh)) {
+ ob, smd_orig, smd, vertexCos, verts_num, tpolys_num, tverts_num, target, mesh)) {
smd->flags &= ~MOD_SDEF_BIND;
}
/* Early abort, this is binding 'call', no need to perform whole evaluation. */
@@ -1482,14 +1482,14 @@ static void surfacedeformModifier_do(ModifierData *md,
}
/* Poly count checks */
- if (smd->num_mesh_verts != numverts) {
+ if (smd->mesh_verts_num != verts_num) {
BKE_modifier_set_error(
- ob, md, "Vertices changed from %u to %u", smd->num_mesh_verts, numverts);
+ ob, md, "Vertices changed from %u to %u", smd->mesh_verts_num, verts_num);
return;
}
- if (smd->numpoly != tnumpoly) {
+ if (smd->polys_num != tpolys_num) {
BKE_modifier_set_error(
- ob, md, "Target polygons changed from %u to %u", smd->numpoly, tnumpoly);
+ ob, md, "Target polygons changed from %u to %u", smd->polys_num, tpolys_num);
return;
}
@@ -1507,7 +1507,7 @@ static void surfacedeformModifier_do(ModifierData *md,
/* Actual vertex location update starts here */
SDefDeformData data = {
.bind_verts = smd->verts,
- .targetCos = MEM_malloc_arrayN(tnumverts, sizeof(float[3]), "SDefTargetVertArray"),
+ .targetCos = MEM_malloc_arrayN(tverts_num, sizeof(float[3]), "SDefTargetVertArray"),
.vertexCos = vertexCos,
.dvert = dvert,
.defgrp_index = defgrp_index,
@@ -1516,12 +1516,12 @@ static void surfacedeformModifier_do(ModifierData *md,
};
if (data.targetCos != NULL) {
- BKE_mesh_wrapper_vert_coords_copy_with_mat4(target, data.targetCos, tnumverts, smd->mat);
+ BKE_mesh_wrapper_vert_coords_copy_with_mat4(target, data.targetCos, tverts_num, smd->mat);
TaskParallelSettings settings;
BLI_parallel_range_settings_defaults(&settings);
- settings.use_threading = (smd->num_bind_verts > 10000);
- BLI_task_parallel_range(0, smd->num_bind_verts, &data, deformVert, &settings);
+ settings.use_threading = (smd->bind_verts_num > 10000);
+ BLI_task_parallel_range(0, smd->bind_verts_num, &data, deformVert, &settings);
MEM_freeN(data.targetCos);
}
@@ -1531,17 +1531,17 @@ static void deformVerts(ModifierData *md,
const ModifierEvalContext *ctx,
Mesh *mesh,
float (*vertexCos)[3],
- int numVerts)
+ int verts_num)
{
SurfaceDeformModifierData *smd = (SurfaceDeformModifierData *)md;
Mesh *mesh_src = NULL;
if (smd->defgrp_name[0] != '\0') {
/* Only need to use mesh_src when a vgroup is used. */
- mesh_src = MOD_deform_mesh_eval_get(ctx->object, NULL, mesh, NULL, numVerts, false, false);
+ mesh_src = MOD_deform_mesh_eval_get(ctx->object, NULL, mesh, NULL, verts_num, false, false);
}
- surfacedeformModifier_do(md, ctx, vertexCos, numVerts, ctx->object, mesh_src);
+ surfacedeformModifier_do(md, ctx, vertexCos, verts_num, ctx->object, mesh_src);
if (!ELEM(mesh_src, NULL, mesh)) {
BKE_id_free(NULL, mesh_src);
@@ -1553,17 +1553,17 @@ static void deformVertsEM(ModifierData *md,
struct BMEditMesh *em,
Mesh *mesh,
float (*vertexCos)[3],
- int numVerts)
+ int verts_num)
{
SurfaceDeformModifierData *smd = (SurfaceDeformModifierData *)md;
Mesh *mesh_src = NULL;
if (smd->defgrp_name[0] != '\0') {
/* Only need to use mesh_src when a vgroup is used. */
- mesh_src = MOD_deform_mesh_eval_get(ctx->object, em, mesh, NULL, numVerts, false, false);
+ mesh_src = MOD_deform_mesh_eval_get(ctx->object, em, mesh, NULL, verts_num, false, false);
}
- surfacedeformModifier_do(md, ctx, vertexCos, numVerts, ctx->object, mesh_src);
+ surfacedeformModifier_do(md, ctx, vertexCos, verts_num, ctx->object, mesh_src);
if (!ELEM(mesh_src, NULL, mesh)) {
BKE_id_free(NULL, mesh_src);
@@ -1633,23 +1633,23 @@ static void blendWrite(BlendWriter *writer, const ModifierData *md)
{
const SurfaceDeformModifierData *smd = (const SurfaceDeformModifierData *)md;
- BLO_write_struct_array(writer, SDefVert, smd->num_bind_verts, smd->verts);
+ BLO_write_struct_array(writer, SDefVert, smd->bind_verts_num, smd->verts);
if (smd->verts) {
- for (int i = 0; i < smd->num_bind_verts; i++) {
- BLO_write_struct_array(writer, SDefBind, smd->verts[i].numbinds, smd->verts[i].binds);
+ for (int i = 0; i < smd->bind_verts_num; i++) {
+ BLO_write_struct_array(writer, SDefBind, smd->verts[i].binds_num, smd->verts[i].binds);
if (smd->verts[i].binds) {
- for (int j = 0; j < smd->verts[i].numbinds; j++) {
+ for (int j = 0; j < smd->verts[i].binds_num; j++) {
BLO_write_uint32_array(
- writer, smd->verts[i].binds[j].numverts, smd->verts[i].binds[j].vert_inds);
+ writer, smd->verts[i].binds[j].verts_num, smd->verts[i].binds[j].vert_inds);
if (ELEM(smd->verts[i].binds[j].mode, MOD_SDEF_MODE_CENTROID, MOD_SDEF_MODE_LOOPTRI)) {
BLO_write_float3_array(writer, 1, smd->verts[i].binds[j].vert_weights);
}
else {
BLO_write_float_array(
- writer, smd->verts[i].binds[j].numverts, smd->verts[i].binds[j].vert_weights);
+ writer, smd->verts[i].binds[j].verts_num, smd->verts[i].binds[j].vert_weights);
}
}
}
@@ -1664,20 +1664,20 @@ static void blendRead(BlendDataReader *reader, ModifierData *md)
BLO_read_data_address(reader, &smd->verts);
if (smd->verts) {
- for (int i = 0; i < smd->num_bind_verts; i++) {
+ for (int i = 0; i < smd->bind_verts_num; i++) {
BLO_read_data_address(reader, &smd->verts[i].binds);
if (smd->verts[i].binds) {
- for (int j = 0; j < smd->verts[i].numbinds; j++) {
+ for (int j = 0; j < smd->verts[i].binds_num; j++) {
BLO_read_uint32_array(
- reader, smd->verts[i].binds[j].numverts, &smd->verts[i].binds[j].vert_inds);
+ reader, smd->verts[i].binds[j].verts_num, &smd->verts[i].binds[j].vert_inds);
if (ELEM(smd->verts[i].binds[j].mode, MOD_SDEF_MODE_CENTROID, MOD_SDEF_MODE_LOOPTRI)) {
BLO_read_float3_array(reader, 1, &smd->verts[i].binds[j].vert_weights);
}
else {
BLO_read_float_array(
- reader, smd->verts[i].binds[j].numverts, &smd->verts[i].binds[j].vert_weights);
+ reader, smd->verts[i].binds[j].verts_num, &smd->verts[i].binds[j].vert_weights);
}
}
}
diff --git a/source/blender/modifiers/intern/MOD_triangulate.c b/source/blender/modifiers/intern/MOD_triangulate.c
index e560a859735..d7e57c1f6e5 100644
--- a/source/blender/modifiers/intern/MOD_triangulate.c
+++ b/source/blender/modifiers/intern/MOD_triangulate.c
@@ -43,7 +43,7 @@ static Mesh *triangulate_mesh(Mesh *mesh,
{
Mesh *result;
BMesh *bm;
- int total_edges, i;
+ int edges_num, i;
MEdge *me;
CustomData_MeshMasks cd_mask_extra = {
.vmask = CD_MASK_ORIGINDEX, .emask = CD_MASK_ORIGINDEX, .pmask = CD_MASK_ORIGINDEX};
@@ -81,11 +81,11 @@ static Mesh *triangulate_mesh(Mesh *mesh,
CustomData_set_layer_flag(&result->ldata, CD_NORMAL, CD_FLAG_TEMPORARY);
}
- total_edges = result->totedge;
+ edges_num = result->totedge;
me = result->medge;
/* force drawing of all edges (seems to be omitted in CDDM_from_bmesh) */
- for (i = 0; i < total_edges; i++, me++) {
+ for (i = 0; i < edges_num; i++, me++) {
me->flag |= ME_EDGEDRAW | ME_EDGERENDER;
}
diff --git a/source/blender/modifiers/intern/MOD_util.c b/source/blender/modifiers/intern/MOD_util.c
index a8c52108cc0..a58e8e23147 100644
--- a/source/blender/modifiers/intern/MOD_util.c
+++ b/source/blender/modifiers/intern/MOD_util.c
@@ -63,7 +63,7 @@ void MOD_get_texture_coords(MappingInfoModifierData *dmd,
float (*cos)[3],
float (*r_texco)[3])
{
- const int numVerts = mesh->totvert;
+ const int verts_num = mesh->totvert;
int i;
int texmapping = dmd->texmapping;
float mapref_imat[4][4];
@@ -97,8 +97,8 @@ void MOD_get_texture_coords(MappingInfoModifierData *dmd,
MPoly *mpoly = mesh->mpoly;
MPoly *mp;
MLoop *mloop = mesh->mloop;
- BLI_bitmap *done = BLI_BITMAP_NEW(numVerts, __func__);
- const int numPolys = mesh->totpoly;
+ BLI_bitmap *done = BLI_BITMAP_NEW(verts_num, __func__);
+ const int polys_num = mesh->totpoly;
char uvname[MAX_CUSTOMDATA_LAYER_NAME];
MLoopUV *mloop_uv;
@@ -106,7 +106,7 @@ void MOD_get_texture_coords(MappingInfoModifierData *dmd,
mloop_uv = CustomData_get_layer_named(&mesh->ldata, CD_MLOOPUV, uvname);
/* verts are given the UV from the first face that uses them */
- for (i = 0, mp = mpoly; i < numPolys; i++, mp++) {
+ for (i = 0, mp = mpoly; i < polys_num; i++, mp++) {
uint fidx = mp->totloop - 1;
do {
@@ -132,7 +132,7 @@ void MOD_get_texture_coords(MappingInfoModifierData *dmd,
}
MVert *mv = mesh->mvert;
- for (i = 0; i < numVerts; i++, mv++, r_texco++) {
+ for (i = 0; i < verts_num; i++, mv++, r_texco++) {
switch (texmapping) {
case MOD_DISP_MAP_LOCAL:
copy_v3_v3(*r_texco, cos != NULL ? *cos : mv->co);
@@ -169,7 +169,7 @@ Mesh *MOD_deform_mesh_eval_get(Object *ob,
struct BMEditMesh *em,
Mesh *mesh,
const float (*vertexCos)[3],
- const int num_verts,
+ const int verts_num,
const bool use_normals,
const bool use_orco)
{
@@ -212,7 +212,7 @@ Mesh *MOD_deform_mesh_eval_get(Object *ob,
/* Currently, that may not be the case every time
* (texts e.g. tend to give issues,
* also when deforming curve points instead of generated curve geometry... ). */
- if (mesh != NULL && mesh->totvert != num_verts) {
+ if (mesh != NULL && mesh->totvert != verts_num) {
BKE_id_free(NULL, mesh);
mesh = NULL;
}
@@ -227,7 +227,7 @@ Mesh *MOD_deform_mesh_eval_get(Object *ob,
}
if (mesh && mesh->runtime.wrapper_type == ME_WRAPPER_TYPE_MDATA) {
- BLI_assert(mesh->totvert == num_verts);
+ BLI_assert(mesh->totvert == verts_num);
}
return mesh;
diff --git a/source/blender/modifiers/intern/MOD_util.h b/source/blender/modifiers/intern/MOD_util.h
index 4578d2c4862..aef254b1103 100644
--- a/source/blender/modifiers/intern/MOD_util.h
+++ b/source/blender/modifiers/intern/MOD_util.h
@@ -37,7 +37,7 @@ struct Mesh *MOD_deform_mesh_eval_get(struct Object *ob,
struct BMEditMesh *em,
struct Mesh *mesh,
const float (*vertexCos)[3],
- int num_verts,
+ int verts_num,
bool use_normals,
bool use_orco);
diff --git a/source/blender/modifiers/intern/MOD_uvproject.c b/source/blender/modifiers/intern/MOD_uvproject.c
index 642aac17efd..d4d7ecef283 100644
--- a/source/blender/modifiers/intern/MOD_uvproject.c
+++ b/source/blender/modifiers/intern/MOD_uvproject.c
@@ -72,7 +72,7 @@ static void updateDepsgraph(ModifierData *md, const ModifierUpdateDepsgraphConte
{
UVProjectModifierData *umd = (UVProjectModifierData *)md;
bool do_add_own_transform = false;
- for (int i = 0; i < umd->num_projectors; i++) {
+ for (int i = 0; i < umd->projectors_num; i++) {
if (umd->projectors[i] != NULL) {
DEG_add_object_relation(
ctx->node, umd->projectors[i], DEG_OB_COMP_TRANSFORM, "UV Project Modifier");
@@ -98,11 +98,11 @@ static Mesh *uvprojectModifier_do(UVProjectModifierData *umd,
{
float(*coords)[3], (*co)[3];
MLoopUV *mloop_uv;
- int i, numVerts, numPolys, numLoops;
+ int i, verts_num, polys_num, loops_num;
MPoly *mpoly, *mp;
MLoop *mloop;
Projector projectors[MOD_UVPROJECT_MAXPROJECTORS];
- int num_projectors = 0;
+ int projectors_num = 0;
char uvname[MAX_CUSTOMDATA_LAYER_NAME];
float aspx = umd->aspectx ? umd->aspectx : 1.0f;
float aspy = umd->aspecty ? umd->aspecty : 1.0f;
@@ -110,13 +110,13 @@ static Mesh *uvprojectModifier_do(UVProjectModifierData *umd,
float scay = umd->scaley ? umd->scaley : 1.0f;
int free_uci = 0;
- for (i = 0; i < umd->num_projectors; i++) {
+ for (i = 0; i < umd->projectors_num; i++) {
if (umd->projectors[i] != NULL) {
- projectors[num_projectors++].ob = umd->projectors[i];
+ projectors[projectors_num++].ob = umd->projectors[i];
}
}
- if (num_projectors == 0) {
+ if (projectors_num == 0) {
return mesh;
}
@@ -131,7 +131,7 @@ static Mesh *uvprojectModifier_do(UVProjectModifierData *umd,
CustomData_validate_layer_name(&mesh->ldata, CD_MLOOPUV, umd->uvlayer_name, uvname);
/* calculate a projection matrix and normal for each projector */
- for (i = 0; i < num_projectors; i++) {
+ for (i = 0; i < projectors_num; i++) {
float tmpmat[4][4];
float offsetmat[4][4];
Camera *cam = NULL;
@@ -184,23 +184,23 @@ static Mesh *uvprojectModifier_do(UVProjectModifierData *umd,
mul_mat3_m4_v3(projectors[i].ob->obmat, projectors[i].normal);
}
- numPolys = mesh->totpoly;
- numLoops = mesh->totloop;
+ polys_num = mesh->totpoly;
+ loops_num = mesh->totloop;
/* make sure we are not modifying the original UV map */
mloop_uv = CustomData_duplicate_referenced_layer_named(
- &mesh->ldata, CD_MLOOPUV, uvname, numLoops);
+ &mesh->ldata, CD_MLOOPUV, uvname, loops_num);
- coords = BKE_mesh_vert_coords_alloc(mesh, &numVerts);
+ coords = BKE_mesh_vert_coords_alloc(mesh, &verts_num);
/* Convert coords to world-space. */
- for (i = 0, co = coords; i < numVerts; i++, co++) {
+ for (i = 0, co = coords; i < verts_num; i++, co++) {
mul_m4_v3(ob->obmat, *co);
}
/* if only one projector, project coords to UVs */
- if (num_projectors == 1 && projectors[0].uci == NULL) {
- for (i = 0, co = coords; i < numVerts; i++, co++) {
+ if (projectors_num == 1 && projectors[0].uci == NULL) {
+ for (i = 0, co = coords; i < verts_num; i++, co++) {
mul_project_m4_v3(projectors[0].projmat, *co);
}
}
@@ -209,8 +209,8 @@ static Mesh *uvprojectModifier_do(UVProjectModifierData *umd,
mloop = mesh->mloop;
/* apply coords as UVs */
- for (i = 0, mp = mpoly; i < numPolys; i++, mp++) {
- if (num_projectors == 1) {
+ for (i = 0, mp = mpoly; i < polys_num; i++, mp++) {
+ if (projectors_num == 1) {
if (projectors[0].uci) {
uint fidx = mp->totloop - 1;
do {
@@ -246,7 +246,7 @@ static Mesh *uvprojectModifier_do(UVProjectModifierData *umd,
best_dot = dot_v3v3(projectors[0].normal, face_no);
best_projector = &projectors[0];
- for (j = 1; j < num_projectors; j++) {
+ for (j = 1; j < projectors_num; j++) {
float tmp_dot = dot_v3v3(projectors[j].normal, face_no);
if (tmp_dot > best_dot) {
best_dot = tmp_dot;
@@ -277,7 +277,7 @@ static Mesh *uvprojectModifier_do(UVProjectModifierData *umd,
if (free_uci) {
int j;
- for (j = 0; j < num_projectors; j++) {
+ for (j = 0; j < projectors_num; j++) {
if (projectors[j].uci) {
MEM_freeN(projectors[j].uci);
}
diff --git a/source/blender/modifiers/intern/MOD_uvwarp.c b/source/blender/modifiers/intern/MOD_uvwarp.c
index 0574b1897de..a15efdaa381 100644
--- a/source/blender/modifiers/intern/MOD_uvwarp.c
+++ b/source/blender/modifiers/intern/MOD_uvwarp.c
@@ -130,7 +130,7 @@ static void uv_warp_compute(void *__restrict userdata,
static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh)
{
UVWarpModifierData *umd = (UVWarpModifierData *)md;
- int numPolys, numLoops;
+ int polys_num, loops_num;
MPoly *mpoly;
MLoop *mloop;
MLoopUV *mloopuv;
@@ -196,14 +196,14 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *
/* make sure we're using an existing layer */
CustomData_validate_layer_name(&mesh->ldata, CD_MLOOPUV, umd->uvlayer_name, uvname);
- numPolys = mesh->totpoly;
- numLoops = mesh->totloop;
+ polys_num = mesh->totpoly;
+ loops_num = mesh->totloop;
mpoly = mesh->mpoly;
mloop = mesh->mloop;
/* make sure we are not modifying the original UV map */
mloopuv = CustomData_duplicate_referenced_layer_named(
- &mesh->ldata, CD_MLOOPUV, uvname, numLoops);
+ &mesh->ldata, CD_MLOOPUV, uvname, loops_num);
MOD_get_vgroup(ctx->object, mesh, umd->vgroup_name, &dvert, &defgrp_index);
UVWarpData data = {
@@ -217,8 +217,8 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *
};
TaskParallelSettings settings;
BLI_parallel_range_settings_defaults(&settings);
- settings.use_threading = (numPolys > 1000);
- BLI_task_parallel_range(0, numPolys, &data, uv_warp_compute, &settings);
+ settings.use_threading = (polys_num > 1000);
+ BLI_task_parallel_range(0, polys_num, &data, uv_warp_compute, &settings);
mesh->runtime.is_original = false;
diff --git a/source/blender/modifiers/intern/MOD_volume_displace.cc b/source/blender/modifiers/intern/MOD_volume_displace.cc
index c4a822125ba..059cfdbdd4e 100644
--- a/source/blender/modifiers/intern/MOD_volume_displace.cc
+++ b/source/blender/modifiers/intern/MOD_volume_displace.cc
@@ -82,9 +82,7 @@ static void foreachTexLink(ModifierData *md, Object *ob, TexWalkFunc walk, void
walk(userData, ob, md, "texture");
}
-static bool dependsOnTime(struct Scene *UNUSED(scene),
- ModifierData *md,
- const int UNUSED(dag_eval_mode))
+static bool dependsOnTime(struct Scene *UNUSED(scene), ModifierData *md)
{
VolumeDisplaceModifierData *vdmd = reinterpret_cast<VolumeDisplaceModifierData *>(md);
if (vdmd->texture) {
diff --git a/source/blender/modifiers/intern/MOD_warp.c b/source/blender/modifiers/intern/MOD_warp.c
index 045b8e16736..e95d2983639 100644
--- a/source/blender/modifiers/intern/MOD_warp.c
+++ b/source/blender/modifiers/intern/MOD_warp.c
@@ -103,9 +103,7 @@ static void matrix_from_obj_pchan(float mat[4][4],
}
}
-static bool dependsOnTime(struct Scene *UNUSED(scene),
- ModifierData *md,
- const int UNUSED(dag_eval_mode))
+static bool dependsOnTime(struct Scene *UNUSED(scene), ModifierData *md)
{
WarpModifierData *wmd = (WarpModifierData *)md;
@@ -181,7 +179,7 @@ static void warpModifier_do(WarpModifierData *wmd,
const ModifierEvalContext *ctx,
Mesh *mesh,
float (*vertexCos)[3],
- int numVerts)
+ int verts_num)
{
Object *ob = ctx->object;
float obinv[4][4];
@@ -245,13 +243,13 @@ static void warpModifier_do(WarpModifierData *wmd,
Tex *tex_target = wmd->texture;
if (mesh != NULL && tex_target != NULL) {
- tex_co = MEM_malloc_arrayN(numVerts, sizeof(*tex_co), "warpModifier_do tex_co");
+ tex_co = MEM_malloc_arrayN(verts_num, sizeof(*tex_co), "warpModifier_do tex_co");
MOD_get_texture_coords((MappingInfoModifierData *)wmd, ctx, ob, mesh, vertexCos, tex_co);
MOD_init_texture((MappingInfoModifierData *)wmd, ctx);
}
- for (i = 0; i < numVerts; i++) {
+ for (i = 0; i < verts_num; i++) {
float *co = vertexCos[i];
if (wmd->falloff_type == eWarp_Falloff_None ||
@@ -344,17 +342,17 @@ static void deformVerts(ModifierData *md,
const ModifierEvalContext *ctx,
Mesh *mesh,
float (*vertexCos)[3],
- int numVerts)
+ int verts_num)
{
WarpModifierData *wmd = (WarpModifierData *)md;
Mesh *mesh_src = NULL;
if (wmd->defgrp_name[0] != '\0' || wmd->texture != NULL) {
/* mesh_src is only needed for vgroups and textures. */
- mesh_src = MOD_deform_mesh_eval_get(ctx->object, NULL, mesh, NULL, numVerts, false, false);
+ mesh_src = MOD_deform_mesh_eval_get(ctx->object, NULL, mesh, NULL, verts_num, false, false);
}
- warpModifier_do(wmd, ctx, mesh_src, vertexCos, numVerts);
+ warpModifier_do(wmd, ctx, mesh_src, vertexCos, verts_num);
if (!ELEM(mesh_src, NULL, mesh)) {
BKE_id_free(NULL, mesh_src);
@@ -366,14 +364,14 @@ static void deformVertsEM(ModifierData *md,
struct BMEditMesh *em,
Mesh *mesh,
float (*vertexCos)[3],
- int numVerts)
+ int verts_num)
{
WarpModifierData *wmd = (WarpModifierData *)md;
Mesh *mesh_src = NULL;
if (wmd->defgrp_name[0] != '\0' || wmd->texture != NULL) {
/* mesh_src is only needed for vgroups and textures. */
- mesh_src = MOD_deform_mesh_eval_get(ctx->object, em, mesh, NULL, numVerts, false, false);
+ mesh_src = MOD_deform_mesh_eval_get(ctx->object, em, mesh, NULL, verts_num, false, false);
}
/* TODO(Campbell): use edit-mode data only (remove this line). */
@@ -381,7 +379,7 @@ static void deformVertsEM(ModifierData *md,
BKE_mesh_wrapper_ensure_mdata(mesh_src);
}
- warpModifier_do(wmd, ctx, mesh_src, vertexCos, numVerts);
+ warpModifier_do(wmd, ctx, mesh_src, vertexCos, verts_num);
if (!ELEM(mesh_src, NULL, mesh)) {
BKE_id_free(NULL, mesh_src);
diff --git a/source/blender/modifiers/intern/MOD_wave.c b/source/blender/modifiers/intern/MOD_wave.c
index 9518cc253e7..73b26dc29cd 100644
--- a/source/blender/modifiers/intern/MOD_wave.c
+++ b/source/blender/modifiers/intern/MOD_wave.c
@@ -55,9 +55,7 @@ static void initData(ModifierData *md)
MEMCPY_STRUCT_AFTER(wmd, DNA_struct_default_get(WaveModifierData), modifier);
}
-static bool dependsOnTime(struct Scene *UNUSED(scene),
- ModifierData *UNUSED(md),
- const int UNUSED(dag_eval_mode))
+static bool dependsOnTime(struct Scene *UNUSED(scene), ModifierData *UNUSED(md))
{
return true;
}
@@ -133,7 +131,7 @@ static void waveModifier_do(WaveModifierData *md,
Object *ob,
Mesh *mesh,
float (*vertexCos)[3],
- int numVerts)
+ int verts_num)
{
WaveModifierData *wmd = (WaveModifierData *)md;
MVert *mvert = NULL;
@@ -188,7 +186,7 @@ static void waveModifier_do(WaveModifierData *md,
Tex *tex_target = wmd->texture;
if (mesh != NULL && tex_target != NULL) {
- tex_co = MEM_malloc_arrayN(numVerts, sizeof(*tex_co), "waveModifier_do tex_co");
+ tex_co = MEM_malloc_arrayN(verts_num, sizeof(*tex_co), "waveModifier_do tex_co");
MOD_get_texture_coords((MappingInfoModifierData *)wmd, ctx, ob, mesh, vertexCos, tex_co);
MOD_init_texture((MappingInfoModifierData *)wmd, ctx);
@@ -199,7 +197,7 @@ static void waveModifier_do(WaveModifierData *md,
float falloff_inv = falloff != 0.0f ? 1.0f / falloff : 1.0f;
int i;
- for (i = 0; i < numVerts; i++) {
+ for (i = 0; i < verts_num; i++) {
float *co = vertexCos[i];
float x = co[0] - wmd->startx;
float y = co[1] - wmd->starty;
@@ -299,19 +297,20 @@ static void deformVerts(ModifierData *md,
const ModifierEvalContext *ctx,
Mesh *mesh,
float (*vertexCos)[3],
- int numVerts)
+ int verts_num)
{
WaveModifierData *wmd = (WaveModifierData *)md;
Mesh *mesh_src = NULL;
if (wmd->flag & MOD_WAVE_NORM) {
- mesh_src = MOD_deform_mesh_eval_get(ctx->object, NULL, mesh, vertexCos, numVerts, true, false);
+ mesh_src = MOD_deform_mesh_eval_get(
+ ctx->object, NULL, mesh, vertexCos, verts_num, true, false);
}
else if (wmd->texture != NULL || wmd->defgrp_name[0] != '\0') {
- mesh_src = MOD_deform_mesh_eval_get(ctx->object, NULL, mesh, NULL, numVerts, false, false);
+ mesh_src = MOD_deform_mesh_eval_get(ctx->object, NULL, mesh, NULL, verts_num, false, false);
}
- waveModifier_do(wmd, ctx, ctx->object, mesh_src, vertexCos, numVerts);
+ waveModifier_do(wmd, ctx, ctx->object, mesh_src, vertexCos, verts_num);
if (!ELEM(mesh_src, NULL, mesh)) {
BKE_id_free(NULL, mesh_src);
@@ -323,17 +322,18 @@ static void deformVertsEM(ModifierData *md,
struct BMEditMesh *editData,
Mesh *mesh,
float (*vertexCos)[3],
- int numVerts)
+ int verts_num)
{
WaveModifierData *wmd = (WaveModifierData *)md;
Mesh *mesh_src = NULL;
if (wmd->flag & MOD_WAVE_NORM) {
mesh_src = MOD_deform_mesh_eval_get(
- ctx->object, editData, mesh, vertexCos, numVerts, true, false);
+ ctx->object, editData, mesh, vertexCos, verts_num, true, false);
}
else if (wmd->texture != NULL || wmd->defgrp_name[0] != '\0') {
- mesh_src = MOD_deform_mesh_eval_get(ctx->object, editData, mesh, NULL, numVerts, false, false);
+ mesh_src = MOD_deform_mesh_eval_get(
+ ctx->object, editData, mesh, NULL, verts_num, false, false);
}
/* TODO(Campbell): use edit-mode data only (remove this line). */
@@ -341,7 +341,7 @@ static void deformVertsEM(ModifierData *md,
BKE_mesh_wrapper_ensure_mdata(mesh_src);
}
- waveModifier_do(wmd, ctx, ctx->object, mesh_src, vertexCos, numVerts);
+ waveModifier_do(wmd, ctx, ctx->object, mesh_src, vertexCos, verts_num);
if (!ELEM(mesh_src, NULL, mesh)) {
BKE_id_free(NULL, mesh_src);
diff --git a/source/blender/modifiers/intern/MOD_weighted_normal.c b/source/blender/modifiers/intern/MOD_weighted_normal.c
index 873372a35b8..c79dbdb0b1a 100644
--- a/source/blender/modifiers/intern/MOD_weighted_normal.c
+++ b/source/blender/modifiers/intern/MOD_weighted_normal.c
@@ -58,7 +58,7 @@ static int modepair_cmp_by_val_inverse(const void *p1, const void *p2)
typedef struct WeightedNormalDataAggregateItem {
float normal[3];
- int num_loops; /* Count number of loops using this item so far. */
+ int loops_num; /* Count number of loops using this item so far. */
float curr_val; /* Current max val for this item. */
int curr_strength; /* Current max strength encountered for this item. */
} WeightedNormalDataAggregateItem;
@@ -66,10 +66,10 @@ typedef struct WeightedNormalDataAggregateItem {
#define NUM_CACHED_INVERSE_POWERS_OF_WEIGHT 128
typedef struct WeightedNormalData {
- const int numVerts;
- const int numEdges;
- const int numLoops;
- const int numPolys;
+ const int verts_num;
+ const int edges_num;
+ const int loops_num;
+ const int polys_num;
MVert *mvert;
const float (*vert_normals)[3];
@@ -116,7 +116,7 @@ static bool check_item_poly_strength(WeightedNormalData *wn_data,
if (mp_strength > item_data->curr_strength) {
item_data->curr_strength = mp_strength;
item_data->curr_val = 0.0f;
- item_data->num_loops = 0;
+ item_data->loops_num = 0;
zero_v3(item_data->normal);
}
@@ -160,20 +160,20 @@ static void aggregate_item_normal(WeightedNormalModifierData *wnmd,
}
if (!compare_ff(item_data->curr_val, curr_val, wnmd->thresh)) {
/* item's curr_val and present value differ more than threshold, update. */
- item_data->num_loops++;
+ item_data->loops_num++;
item_data->curr_val = curr_val;
}
/* Exponentially divided weight for each normal
* (since a few values will be used by most cases, we cache those). */
- const int num_loops = item_data->num_loops;
- if (num_loops < NUM_CACHED_INVERSE_POWERS_OF_WEIGHT &&
- cached_inverse_powers_of_weight[num_loops] == 0.0f) {
- cached_inverse_powers_of_weight[num_loops] = 1.0f / powf(weight, num_loops);
+ const int loops_num = item_data->loops_num;
+ if (loops_num < NUM_CACHED_INVERSE_POWERS_OF_WEIGHT &&
+ cached_inverse_powers_of_weight[loops_num] == 0.0f) {
+ cached_inverse_powers_of_weight[loops_num] = 1.0f / powf(weight, loops_num);
}
- const float inverted_n_weight = num_loops < NUM_CACHED_INVERSE_POWERS_OF_WEIGHT ?
- cached_inverse_powers_of_weight[num_loops] :
- 1.0f / powf(weight, num_loops);
+ const float inverted_n_weight = loops_num < NUM_CACHED_INVERSE_POWERS_OF_WEIGHT ?
+ cached_inverse_powers_of_weight[loops_num] :
+ 1.0f / powf(weight, loops_num);
madd_v3_v3fl(item_data->normal, polynors[mp_index], curr_val * inverted_n_weight);
}
@@ -181,10 +181,10 @@ static void aggregate_item_normal(WeightedNormalModifierData *wnmd,
static void apply_weights_vertex_normal(WeightedNormalModifierData *wnmd,
WeightedNormalData *wn_data)
{
- const int numVerts = wn_data->numVerts;
- const int numEdges = wn_data->numEdges;
- const int numLoops = wn_data->numLoops;
- const int numPolys = wn_data->numPolys;
+ const int verts_num = wn_data->verts_num;
+ const int edges_num = wn_data->edges_num;
+ const int loops_num = wn_data->loops_num;
+ const int polys_num = wn_data->polys_num;
MVert *mvert = wn_data->mvert;
MEdge *medge = wn_data->medge;
@@ -214,39 +214,39 @@ static void apply_weights_vertex_normal(WeightedNormalModifierData *wnmd,
float(*loop_normals)[3] = NULL;
WeightedNormalDataAggregateItem *items_data = NULL;
- int num_items = 0;
+ int items_num = 0;
if (keep_sharp) {
- BLI_bitmap *done_loops = BLI_BITMAP_NEW(numLoops, __func__);
+ BLI_bitmap *done_loops = BLI_BITMAP_NEW(loops_num, __func__);
/* This will give us loop normal spaces,
* we do not actually care about computed loop_normals for now... */
- loop_normals = MEM_calloc_arrayN((size_t)numLoops, sizeof(*loop_normals), __func__);
+ loop_normals = MEM_calloc_arrayN((size_t)loops_num, sizeof(*loop_normals), __func__);
BKE_mesh_normals_loop_split(mvert,
wn_data->vert_normals,
- numVerts,
+ verts_num,
medge,
- numEdges,
+ edges_num,
mloop,
loop_normals,
- numLoops,
+ loops_num,
mpoly,
polynors,
- numPolys,
+ polys_num,
true,
split_angle,
&lnors_spacearr,
has_clnors ? clnors : NULL,
loop_to_poly);
- num_items = lnors_spacearr.num_spaces;
- items_data = MEM_calloc_arrayN((size_t)num_items, sizeof(*items_data), __func__);
+ items_num = lnors_spacearr.spaces_num;
+ items_data = MEM_calloc_arrayN((size_t)items_num, sizeof(*items_data), __func__);
/* In this first loop, we assign each WeightedNormalDataAggregateItem
* to its smooth fan of loops (aka lnor space). */
MPoly *mp;
int mp_index;
int item_index;
- for (mp = mpoly, mp_index = 0, item_index = 0; mp_index < numPolys; mp++, mp_index++) {
+ for (mp = mpoly, mp_index = 0, item_index = 0; mp_index < polys_num; mp++, mp_index++) {
int ml_index = mp->loopstart;
const int ml_end_index = ml_index + mp->totloop;
@@ -255,7 +255,7 @@ static void apply_weights_vertex_normal(WeightedNormalModifierData *wnmd,
/* Smooth fan of this loop has already been processed, skip it. */
continue;
}
- BLI_assert(item_index < num_items);
+ BLI_assert(item_index < items_num);
WeightedNormalDataAggregateItem *itdt = &items_data[item_index];
itdt->curr_strength = FACE_STRENGTH_WEAK;
@@ -280,10 +280,10 @@ static void apply_weights_vertex_normal(WeightedNormalModifierData *wnmd,
MEM_freeN(done_loops);
}
else {
- num_items = numVerts;
- items_data = MEM_calloc_arrayN((size_t)num_items, sizeof(*items_data), __func__);
+ items_num = verts_num;
+ items_data = MEM_calloc_arrayN((size_t)items_num, sizeof(*items_data), __func__);
if (use_face_influence) {
- for (int item_index = 0; item_index < num_items; item_index++) {
+ for (int item_index = 0; item_index < items_num; item_index++) {
items_data[item_index].curr_strength = FACE_STRENGTH_WEAK;
}
}
@@ -292,7 +292,7 @@ static void apply_weights_vertex_normal(WeightedNormalModifierData *wnmd,
switch (mode) {
case MOD_WEIGHTEDNORMAL_MODE_FACE:
- for (int i = 0; i < numPolys; i++) {
+ for (int i = 0; i < polys_num; i++) {
const int mp_index = mode_pair[i].index;
const float mp_val = mode_pair[i].val;
@@ -312,7 +312,7 @@ static void apply_weights_vertex_normal(WeightedNormalModifierData *wnmd,
case MOD_WEIGHTEDNORMAL_MODE_FACE_ANGLE:
BLI_assert(loop_to_poly != NULL);
- for (int i = 0; i < numLoops; i++) {
+ for (int i = 0; i < loops_num; i++) {
const int ml_index = mode_pair[i].index;
const float ml_val = mode_pair[i].val;
@@ -330,7 +330,7 @@ static void apply_weights_vertex_normal(WeightedNormalModifierData *wnmd,
}
/* Validate computed weighted normals. */
- for (int item_index = 0; item_index < num_items; item_index++) {
+ for (int item_index = 0; item_index < items_num; item_index++) {
if (normalize_v3(items_data[item_index].normal) < CLNORS_VALID_VEC_LEN) {
zero_v3(items_data[item_index].normal);
}
@@ -341,7 +341,7 @@ static void apply_weights_vertex_normal(WeightedNormalModifierData *wnmd,
* Note that loop_normals is already populated with clnors
* (before this modifier is applied, at start of this function),
* so no need to recompute them here. */
- for (int ml_index = 0; ml_index < numLoops; ml_index++) {
+ for (int ml_index = 0; ml_index < loops_num; ml_index++) {
WeightedNormalDataAggregateItem *item_data = lnors_spacearr.lspacearr[ml_index]->user_data;
if (!is_zero_v3(item_data->normal)) {
copy_v3_v3(loop_normals[ml_index], item_data->normal);
@@ -350,15 +350,15 @@ static void apply_weights_vertex_normal(WeightedNormalModifierData *wnmd,
BKE_mesh_normals_loop_custom_set(mvert,
wn_data->vert_normals,
- numVerts,
+ verts_num,
medge,
- numEdges,
+ edges_num,
mloop,
loop_normals,
- numLoops,
+ loops_num,
mpoly,
polynors,
- numPolys,
+ polys_num,
clnors);
}
else {
@@ -372,9 +372,9 @@ static void apply_weights_vertex_normal(WeightedNormalModifierData *wnmd,
* But think we can live with it for now,
* and it makes code simpler & cleaner. */
float(*vert_normals)[3] = MEM_calloc_arrayN(
- (size_t)numVerts, sizeof(*loop_normals), __func__);
+ (size_t)verts_num, sizeof(*loop_normals), __func__);
- for (int ml_index = 0; ml_index < numLoops; ml_index++) {
+ for (int ml_index = 0; ml_index < loops_num; ml_index++) {
const int mv_index = mloop[ml_index].v;
copy_v3_v3(vert_normals[mv_index], items_data[mv_index].normal);
}
@@ -382,39 +382,39 @@ static void apply_weights_vertex_normal(WeightedNormalModifierData *wnmd,
BKE_mesh_normals_loop_custom_from_vertices_set(mvert,
wn_data->vert_normals,
vert_normals,
- numVerts,
+ verts_num,
medge,
- numEdges,
+ edges_num,
mloop,
- numLoops,
+ loops_num,
mpoly,
polynors,
- numPolys,
+ polys_num,
clnors);
MEM_freeN(vert_normals);
}
else {
- loop_normals = MEM_calloc_arrayN((size_t)numLoops, sizeof(*loop_normals), __func__);
+ loop_normals = MEM_calloc_arrayN((size_t)loops_num, sizeof(*loop_normals), __func__);
BKE_mesh_normals_loop_split(mvert,
wn_data->vert_normals,
- numVerts,
+ verts_num,
medge,
- numEdges,
+ edges_num,
mloop,
loop_normals,
- numLoops,
+ loops_num,
mpoly,
polynors,
- numPolys,
+ polys_num,
true,
split_angle,
NULL,
has_clnors ? clnors : NULL,
loop_to_poly);
- for (int ml_index = 0; ml_index < numLoops; ml_index++) {
+ for (int ml_index = 0; ml_index < loops_num; ml_index++) {
const int item_index = mloop[ml_index].v;
if (!is_zero_v3(items_data[item_index].normal)) {
copy_v3_v3(loop_normals[ml_index], items_data[item_index].normal);
@@ -423,15 +423,15 @@ static void apply_weights_vertex_normal(WeightedNormalModifierData *wnmd,
BKE_mesh_normals_loop_custom_set(mvert,
wn_data->vert_normals,
- numVerts,
+ verts_num,
medge,
- numEdges,
+ edges_num,
mloop,
loop_normals,
- numLoops,
+ loops_num,
mpoly,
polynors,
- numPolys,
+ polys_num,
clnors);
}
}
@@ -444,7 +444,7 @@ static void apply_weights_vertex_normal(WeightedNormalModifierData *wnmd,
static void wn_face_area(WeightedNormalModifierData *wnmd, WeightedNormalData *wn_data)
{
- const int numPolys = wn_data->numPolys;
+ const int polys_num = wn_data->polys_num;
MVert *mvert = wn_data->mvert;
MLoop *mloop = wn_data->mloop;
@@ -453,15 +453,15 @@ static void wn_face_area(WeightedNormalModifierData *wnmd, WeightedNormalData *w
MPoly *mp;
int mp_index;
- ModePair *face_area = MEM_malloc_arrayN((size_t)numPolys, sizeof(*face_area), __func__);
+ ModePair *face_area = MEM_malloc_arrayN((size_t)polys_num, sizeof(*face_area), __func__);
ModePair *f_area = face_area;
- for (mp_index = 0, mp = mpoly; mp_index < numPolys; mp_index++, mp++, f_area++) {
+ for (mp_index = 0, mp = mpoly; mp_index < polys_num; mp_index++, mp++, f_area++) {
f_area->val = BKE_mesh_calc_poly_area(mp, &mloop[mp->loopstart], mvert);
f_area->index = mp_index;
}
- qsort(face_area, numPolys, sizeof(*face_area), modepair_cmp_by_val_inverse);
+ qsort(face_area, polys_num, sizeof(*face_area), modepair_cmp_by_val_inverse);
wn_data->mode_pair = face_area;
apply_weights_vertex_normal(wnmd, wn_data);
@@ -469,8 +469,8 @@ static void wn_face_area(WeightedNormalModifierData *wnmd, WeightedNormalData *w
static void wn_corner_angle(WeightedNormalModifierData *wnmd, WeightedNormalData *wn_data)
{
- const int numLoops = wn_data->numLoops;
- const int numPolys = wn_data->numPolys;
+ const int loops_num = wn_data->loops_num;
+ const int polys_num = wn_data->polys_num;
MVert *mvert = wn_data->mvert;
MLoop *mloop = wn_data->mloop;
@@ -479,11 +479,11 @@ static void wn_corner_angle(WeightedNormalModifierData *wnmd, WeightedNormalData
MPoly *mp;
int mp_index;
- int *loop_to_poly = MEM_malloc_arrayN((size_t)numLoops, sizeof(*loop_to_poly), __func__);
+ int *loop_to_poly = MEM_malloc_arrayN((size_t)loops_num, sizeof(*loop_to_poly), __func__);
- ModePair *corner_angle = MEM_malloc_arrayN((size_t)numLoops, sizeof(*corner_angle), __func__);
+ ModePair *corner_angle = MEM_malloc_arrayN((size_t)loops_num, sizeof(*corner_angle), __func__);
- for (mp_index = 0, mp = mpoly; mp_index < numPolys; mp_index++, mp++) {
+ for (mp_index = 0, mp = mpoly; mp_index < polys_num; mp_index++, mp++) {
MLoop *ml_start = &mloop[mp->loopstart];
float *index_angle = MEM_malloc_arrayN((size_t)mp->totloop, sizeof(*index_angle), __func__);
@@ -501,7 +501,7 @@ static void wn_corner_angle(WeightedNormalModifierData *wnmd, WeightedNormalData
MEM_freeN(index_angle);
}
- qsort(corner_angle, numLoops, sizeof(*corner_angle), modepair_cmp_by_val_inverse);
+ qsort(corner_angle, loops_num, sizeof(*corner_angle), modepair_cmp_by_val_inverse);
wn_data->loop_to_poly = loop_to_poly;
wn_data->mode_pair = corner_angle;
@@ -510,8 +510,8 @@ static void wn_corner_angle(WeightedNormalModifierData *wnmd, WeightedNormalData
static void wn_face_with_angle(WeightedNormalModifierData *wnmd, WeightedNormalData *wn_data)
{
- const int numLoops = wn_data->numLoops;
- const int numPolys = wn_data->numPolys;
+ const int loops_num = wn_data->loops_num;
+ const int polys_num = wn_data->polys_num;
MVert *mvert = wn_data->mvert;
MLoop *mloop = wn_data->mloop;
@@ -520,11 +520,11 @@ static void wn_face_with_angle(WeightedNormalModifierData *wnmd, WeightedNormalD
MPoly *mp;
int mp_index;
- int *loop_to_poly = MEM_malloc_arrayN((size_t)numLoops, sizeof(*loop_to_poly), __func__);
+ int *loop_to_poly = MEM_malloc_arrayN((size_t)loops_num, sizeof(*loop_to_poly), __func__);
- ModePair *combined = MEM_malloc_arrayN((size_t)numLoops, sizeof(*combined), __func__);
+ ModePair *combined = MEM_malloc_arrayN((size_t)loops_num, sizeof(*combined), __func__);
- for (mp_index = 0, mp = mpoly; mp_index < numPolys; mp_index++, mp++) {
+ for (mp_index = 0, mp = mpoly; mp_index < polys_num; mp_index++, mp++) {
MLoop *ml_start = &mloop[mp->loopstart];
float face_area = BKE_mesh_calc_poly_area(mp, ml_start, mvert);
@@ -544,7 +544,7 @@ static void wn_face_with_angle(WeightedNormalModifierData *wnmd, WeightedNormalD
MEM_freeN(index_angle);
}
- qsort(combined, numLoops, sizeof(*combined), modepair_cmp_by_val_inverse);
+ qsort(combined, loops_num, sizeof(*combined), modepair_cmp_by_val_inverse);
wn_data->loop_to_poly = loop_to_poly;
wn_data->mode_pair = combined;
@@ -575,10 +575,10 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *
Mesh *result;
result = (Mesh *)BKE_id_copy_ex(NULL, &mesh->id, NULL, LIB_ID_COPY_LOCALIZE);
- const int numVerts = result->totvert;
- const int numEdges = result->totedge;
- const int numLoops = result->totloop;
- const int numPolys = result->totpoly;
+ const int verts_num = result->totvert;
+ const int edges_num = result->totedge;
+ const int loops_num = result->totloop;
+ const int polys_num = result->totpoly;
MEdge *medge = result->medge;
MPoly *mpoly = result->mpoly;
@@ -611,7 +611,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *
* it helps when generating clnor spaces and default normals. */
const bool has_clnors = clnors != NULL;
if (!clnors) {
- clnors = CustomData_add_layer(ldata, CD_CUSTOMLOOPNORMAL, CD_CALLOC, NULL, numLoops);
+ clnors = CustomData_add_layer(ldata, CD_CUSTOMLOOPNORMAL, CD_CALLOC, NULL, loops_num);
}
MDeformVert *dvert;
@@ -619,10 +619,10 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *
MOD_get_vgroup(ctx->object, mesh, wnmd->defgrp_name, &dvert, &defgrp_index);
WeightedNormalData wn_data = {
- .numVerts = numVerts,
- .numEdges = numEdges,
- .numLoops = numLoops,
- .numPolys = numPolys,
+ .verts_num = verts_num,
+ .edges_num = edges_num,
+ .loops_num = loops_num,
+ .polys_num = polys_num,
.mvert = mvert,
.vert_normals = BKE_mesh_vertex_normals_ensure(result),
diff --git a/source/blender/modifiers/intern/MOD_weightvg_util.c b/source/blender/modifiers/intern/MOD_weightvg_util.c
index a5c901dbe7a..b251825cd95 100644
--- a/source/blender/modifiers/intern/MOD_weightvg_util.c
+++ b/source/blender/modifiers/intern/MOD_weightvg_util.c
@@ -135,7 +135,7 @@ void weightvg_do_mask(const ModifierEvalContext *ctx,
float(*tex_co)[3];
/* See mapping note below... */
MappingInfoModifierData t_map;
- const int numVerts = mesh->totvert;
+ const int verts_num = mesh->totvert;
/* Use new generic get_texture_coords, but do not modify our DNA struct for it...
* XXX Why use a ModifierData stuff here ? Why not a simple, generic struct for parameters?
@@ -148,7 +148,7 @@ void weightvg_do_mask(const ModifierEvalContext *ctx,
BLI_strncpy(t_map.uvlayer_name, tex_uvlayer_name, sizeof(t_map.uvlayer_name));
t_map.texmapping = tex_mapping;
- tex_co = MEM_calloc_arrayN(numVerts, sizeof(*tex_co), "WeightVG Modifier, TEX mode, tex_co");
+ tex_co = MEM_calloc_arrayN(verts_num, sizeof(*tex_co), "WeightVG Modifier, TEX mode, tex_co");
MOD_get_texture_coords(&t_map, ctx, ob, mesh, NULL, tex_co);
MOD_init_texture(&t_map, ctx);
diff --git a/source/blender/modifiers/intern/MOD_weightvgedit.c b/source/blender/modifiers/intern/MOD_weightvgedit.c
index bce8ce82423..2c733542e51 100644
--- a/source/blender/modifiers/intern/MOD_weightvgedit.c
+++ b/source/blender/modifiers/intern/MOD_weightvgedit.c
@@ -97,9 +97,7 @@ static void requiredDataMask(Object *UNUSED(ob),
/* No need to ask for CD_PREVIEW_MLOOPCOL... */
}
-static bool dependsOnTime(struct Scene *UNUSED(scene),
- ModifierData *md,
- const int UNUSED(dag_eval_mode))
+static bool dependsOnTime(struct Scene *UNUSED(scene), ModifierData *md)
{
WeightVGEditModifierData *wmd = (WeightVGEditModifierData *)md;
@@ -176,12 +174,12 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *
#endif
/* Get number of verts. */
- const int numVerts = mesh->totvert;
+ const int verts_num = mesh->totvert;
/* Check if we can just return the original mesh.
* Must have verts and therefore verts assigned to vgroups to do anything useful!
*/
- if ((numVerts == 0) || BLI_listbase_is_empty(&mesh->vertex_group_names)) {
+ if ((verts_num == 0) || BLI_listbase_is_empty(&mesh->vertex_group_names)) {
return mesh;
}
@@ -201,11 +199,11 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *
}
if (has_mdef) {
- dvert = CustomData_duplicate_referenced_layer(&mesh->vdata, CD_MDEFORMVERT, numVerts);
+ dvert = CustomData_duplicate_referenced_layer(&mesh->vdata, CD_MDEFORMVERT, verts_num);
}
else {
/* Add a valid data layer! */
- dvert = CustomData_add_layer(&mesh->vdata, CD_MDEFORMVERT, CD_CALLOC, NULL, numVerts);
+ dvert = CustomData_add_layer(&mesh->vdata, CD_MDEFORMVERT, CD_CALLOC, NULL, verts_num);
}
/* Ultimate security check. */
if (!dvert) {
@@ -214,10 +212,10 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *
mesh->dvert = dvert;
/* Get org weights, assuming 0.0 for vertices not in given vgroup. */
- org_w = MEM_malloc_arrayN(numVerts, sizeof(float), "WeightVGEdit Modifier, org_w");
- new_w = MEM_malloc_arrayN(numVerts, sizeof(float), "WeightVGEdit Modifier, new_w");
- dw = MEM_malloc_arrayN(numVerts, sizeof(MDeformWeight *), "WeightVGEdit Modifier, dw");
- for (i = 0; i < numVerts; i++) {
+ org_w = MEM_malloc_arrayN(verts_num, sizeof(float), "WeightVGEdit Modifier, org_w");
+ new_w = MEM_malloc_arrayN(verts_num, sizeof(float), "WeightVGEdit Modifier, new_w");
+ dw = MEM_malloc_arrayN(verts_num, sizeof(MDeformWeight *), "WeightVGEdit Modifier, dw");
+ for (i = 0; i < verts_num; i++) {
dw[i] = BKE_defvert_find_index(&dvert[i], defgrp_index);
if (dw[i]) {
org_w[i] = new_w[i] = dw[i]->weight;
@@ -237,7 +235,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *
rng = BLI_rng_new_srandom(BLI_ghashutil_strhash(ctx->object->id.name + 2));
}
- weightvg_do_map(numVerts, new_w, wmd->falloff_type, do_invert_mapping, wmd->cmap_curve, rng);
+ weightvg_do_map(verts_num, new_w, wmd->falloff_type, do_invert_mapping, wmd->cmap_curve, rng);
if (rng) {
BLI_rng_free(rng);
@@ -247,7 +245,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *
/* Do masking. */
struct Scene *scene = DEG_get_evaluated_scene(ctx->depsgraph);
weightvg_do_mask(ctx,
- numVerts,
+ verts_num,
NULL,
org_w,
new_w,
@@ -268,7 +266,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *
weightvg_update_vg(dvert,
defgrp_index,
dw,
- numVerts,
+ verts_num,
NULL,
org_w,
do_add,
diff --git a/source/blender/modifiers/intern/MOD_weightvgmix.c b/source/blender/modifiers/intern/MOD_weightvgmix.c
index 7f9bf9d1e80..b827d41e80a 100644
--- a/source/blender/modifiers/intern/MOD_weightvgmix.c
+++ b/source/blender/modifiers/intern/MOD_weightvgmix.c
@@ -145,9 +145,7 @@ static void requiredDataMask(Object *UNUSED(ob),
/* No need to ask for CD_PREVIEW_MLOOPCOL... */
}
-static bool dependsOnTime(struct Scene *UNUSED(scene),
- ModifierData *md,
- const int UNUSED(dag_eval_mode))
+static bool dependsOnTime(struct Scene *UNUSED(scene), ModifierData *md)
{
WeightVGMixModifierData *wmd = (WeightVGMixModifierData *)md;
@@ -213,7 +211,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *
float *org_w;
float *new_w;
int *tidx, *indices = NULL;
- int numIdx = 0;
+ int index_num = 0;
int i;
const bool invert_vgroup_mask = (wmd->flag & MOD_WVG_MIX_INVERT_VGROUP_MASK) != 0;
const bool do_normalize = (wmd->flag & MOD_WVG_MIX_WEIGHTS_NORMALIZE) != 0;
@@ -233,12 +231,12 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *
#endif
/* Get number of verts. */
- const int numVerts = mesh->totvert;
+ const int verts_num = mesh->totvert;
/* Check if we can just return the original mesh.
* Must have verts and therefore verts assigned to vgroups to do anything useful!
*/
- if ((numVerts == 0) || BLI_listbase_is_empty(&mesh->vertex_group_names)) {
+ if ((verts_num == 0) || BLI_listbase_is_empty(&mesh->vertex_group_names)) {
return mesh;
}
@@ -266,11 +264,11 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *
}
if (has_mdef) {
- dvert = CustomData_duplicate_referenced_layer(&mesh->vdata, CD_MDEFORMVERT, numVerts);
+ dvert = CustomData_duplicate_referenced_layer(&mesh->vdata, CD_MDEFORMVERT, verts_num);
}
else {
/* Add a valid data layer! */
- dvert = CustomData_add_layer(&mesh->vdata, CD_MDEFORMVERT, CD_CALLOC, NULL, numVerts);
+ dvert = CustomData_add_layer(&mesh->vdata, CD_MDEFORMVERT, CD_CALLOC, NULL, verts_num);
}
/* Ultimate security check. */
if (!dvert) {
@@ -279,107 +277,107 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *
mesh->dvert = dvert;
/* Find out which vertices to work on. */
- tidx = MEM_malloc_arrayN(numVerts, sizeof(int), "WeightVGMix Modifier, tidx");
- tdw1 = MEM_malloc_arrayN(numVerts, sizeof(MDeformWeight *), "WeightVGMix Modifier, tdw1");
- tdw2 = MEM_malloc_arrayN(numVerts, sizeof(MDeformWeight *), "WeightVGMix Modifier, tdw2");
+ tidx = MEM_malloc_arrayN(verts_num, sizeof(int), "WeightVGMix Modifier, tidx");
+ tdw1 = MEM_malloc_arrayN(verts_num, sizeof(MDeformWeight *), "WeightVGMix Modifier, tdw1");
+ tdw2 = MEM_malloc_arrayN(verts_num, sizeof(MDeformWeight *), "WeightVGMix Modifier, tdw2");
switch (wmd->mix_set) {
case MOD_WVG_SET_A:
/* All vertices in first vgroup. */
- for (i = 0; i < numVerts; i++) {
+ for (i = 0; i < verts_num; i++) {
MDeformWeight *dw = BKE_defvert_find_index(&dvert[i], defgrp_index);
if (dw) {
- tdw1[numIdx] = dw;
- tdw2[numIdx] = (defgrp_index_other >= 0) ?
- BKE_defvert_find_index(&dvert[i], defgrp_index_other) :
- NULL;
- tidx[numIdx++] = i;
+ tdw1[index_num] = dw;
+ tdw2[index_num] = (defgrp_index_other >= 0) ?
+ BKE_defvert_find_index(&dvert[i], defgrp_index_other) :
+ NULL;
+ tidx[index_num++] = i;
}
}
break;
case MOD_WVG_SET_B:
/* All vertices in second vgroup. */
- for (i = 0; i < numVerts; i++) {
+ for (i = 0; i < verts_num; i++) {
MDeformWeight *dw = (defgrp_index_other >= 0) ?
BKE_defvert_find_index(&dvert[i], defgrp_index_other) :
NULL;
if (dw) {
- tdw1[numIdx] = BKE_defvert_find_index(&dvert[i], defgrp_index);
- tdw2[numIdx] = dw;
- tidx[numIdx++] = i;
+ tdw1[index_num] = BKE_defvert_find_index(&dvert[i], defgrp_index);
+ tdw2[index_num] = dw;
+ tidx[index_num++] = i;
}
}
break;
case MOD_WVG_SET_OR:
/* All vertices in one vgroup or the other. */
- for (i = 0; i < numVerts; i++) {
+ for (i = 0; i < verts_num; i++) {
MDeformWeight *adw = BKE_defvert_find_index(&dvert[i], defgrp_index);
MDeformWeight *bdw = (defgrp_index_other >= 0) ?
BKE_defvert_find_index(&dvert[i], defgrp_index_other) :
NULL;
if (adw || bdw) {
- tdw1[numIdx] = adw;
- tdw2[numIdx] = bdw;
- tidx[numIdx++] = i;
+ tdw1[index_num] = adw;
+ tdw2[index_num] = bdw;
+ tidx[index_num++] = i;
}
}
break;
case MOD_WVG_SET_AND:
/* All vertices in both vgroups. */
- for (i = 0; i < numVerts; i++) {
+ for (i = 0; i < verts_num; i++) {
MDeformWeight *adw = BKE_defvert_find_index(&dvert[i], defgrp_index);
MDeformWeight *bdw = (defgrp_index_other >= 0) ?
BKE_defvert_find_index(&dvert[i], defgrp_index_other) :
NULL;
if (adw && bdw) {
- tdw1[numIdx] = adw;
- tdw2[numIdx] = bdw;
- tidx[numIdx++] = i;
+ tdw1[index_num] = adw;
+ tdw2[index_num] = bdw;
+ tidx[index_num++] = i;
}
}
break;
case MOD_WVG_SET_ALL:
default:
/* Use all vertices. */
- for (i = 0; i < numVerts; i++) {
+ for (i = 0; i < verts_num; i++) {
tdw1[i] = BKE_defvert_find_index(&dvert[i], defgrp_index);
tdw2[i] = (defgrp_index_other >= 0) ?
BKE_defvert_find_index(&dvert[i], defgrp_index_other) :
NULL;
}
- numIdx = -1;
+ index_num = -1;
break;
}
- if (numIdx == 0) {
+ if (index_num == 0) {
/* Use no vertices! Hence, return org data. */
MEM_freeN(tdw1);
MEM_freeN(tdw2);
MEM_freeN(tidx);
return mesh;
}
- if (numIdx != -1) {
- indices = MEM_malloc_arrayN(numIdx, sizeof(int), "WeightVGMix Modifier, indices");
- memcpy(indices, tidx, sizeof(int) * numIdx);
- dw1 = MEM_malloc_arrayN(numIdx, sizeof(MDeformWeight *), "WeightVGMix Modifier, dw1");
- memcpy(dw1, tdw1, sizeof(MDeformWeight *) * numIdx);
+ if (index_num != -1) {
+ indices = MEM_malloc_arrayN(index_num, sizeof(int), "WeightVGMix Modifier, indices");
+ memcpy(indices, tidx, sizeof(int) * index_num);
+ dw1 = MEM_malloc_arrayN(index_num, sizeof(MDeformWeight *), "WeightVGMix Modifier, dw1");
+ memcpy(dw1, tdw1, sizeof(MDeformWeight *) * index_num);
MEM_freeN(tdw1);
- dw2 = MEM_malloc_arrayN(numIdx, sizeof(MDeformWeight *), "WeightVGMix Modifier, dw2");
- memcpy(dw2, tdw2, sizeof(MDeformWeight *) * numIdx);
+ dw2 = MEM_malloc_arrayN(index_num, sizeof(MDeformWeight *), "WeightVGMix Modifier, dw2");
+ memcpy(dw2, tdw2, sizeof(MDeformWeight *) * index_num);
MEM_freeN(tdw2);
}
else {
/* Use all vertices. */
- numIdx = numVerts;
+ index_num = verts_num;
/* Just copy MDeformWeight pointers arrays, they will be freed at the end. */
dw1 = tdw1;
dw2 = tdw2;
}
MEM_freeN(tidx);
- org_w = MEM_malloc_arrayN(numIdx, sizeof(float), "WeightVGMix Modifier, org_w");
- new_w = MEM_malloc_arrayN(numIdx, sizeof(float), "WeightVGMix Modifier, new_w");
+ org_w = MEM_malloc_arrayN(index_num, sizeof(float), "WeightVGMix Modifier, org_w");
+ new_w = MEM_malloc_arrayN(index_num, sizeof(float), "WeightVGMix Modifier, new_w");
/* Mix weights. */
- for (i = 0; i < numIdx; i++) {
+ for (i = 0; i < index_num; i++) {
float weight2;
if (invert_vgroup_a) {
org_w[i] = 1.0f - (dw1[i] ? dw1[i]->weight : wmd->default_weight_a);
@@ -400,7 +398,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *
/* Do masking. */
struct Scene *scene = DEG_get_evaluated_scene(ctx->depsgraph);
weightvg_do_mask(ctx,
- numIdx,
+ index_num,
indices,
org_w,
new_w,
@@ -420,13 +418,22 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *
/* Update (add to) vgroup.
* XXX Depending on the MOD_WVG_SET_xxx option chosen, we might have to add vertices to vgroup.
*/
- weightvg_update_vg(
- dvert, defgrp_index, dw1, numIdx, indices, org_w, true, -FLT_MAX, false, 0.0f, do_normalize);
+ weightvg_update_vg(dvert,
+ defgrp_index,
+ dw1,
+ index_num,
+ indices,
+ org_w,
+ true,
+ -FLT_MAX,
+ false,
+ 0.0f,
+ do_normalize);
/* If weight preview enabled... */
#if 0 /* XXX Currently done in mod stack :/ */
if (do_prev) {
- DM_update_weight_mcol(ob, dm, 0, org_w, numIdx, indices);
+ DM_update_weight_mcol(ob, dm, 0, org_w, index_num, indices);
}
#endif
diff --git a/source/blender/modifiers/intern/MOD_weightvgproximity.c b/source/blender/modifiers/intern/MOD_weightvgproximity.c
index 647db5c5aa4..43a90b2a4ac 100644
--- a/source/blender/modifiers/intern/MOD_weightvgproximity.c
+++ b/source/blender/modifiers/intern/MOD_weightvgproximity.c
@@ -143,7 +143,7 @@ static void vert2geom_task_cb_ex(void *__restrict userdata,
/**
* Find nearest vertex and/or edge and/or face, for each vertex (adapted from shrinkwrap.c).
*/
-static void get_vert2geom_distance(int numVerts,
+static void get_vert2geom_distance(int verts_num,
float (*v_cos)[3],
float *dist_v,
float *dist_e,
@@ -194,10 +194,10 @@ static void get_vert2geom_distance(int numVerts,
TaskParallelSettings settings;
BLI_parallel_range_settings_defaults(&settings);
- settings.use_threading = (numVerts > 10000);
+ settings.use_threading = (verts_num > 10000);
settings.userdata_chunk = &data_chunk;
settings.userdata_chunk_size = sizeof(data_chunk);
- BLI_task_parallel_range(0, numVerts, &data, vert2geom_task_cb_ex, &settings);
+ BLI_task_parallel_range(0, verts_num, &data, vert2geom_task_cb_ex, &settings);
if (dist_v) {
free_bvhtree_from_mesh(&treeData_v);
@@ -215,11 +215,11 @@ static void get_vert2geom_distance(int numVerts,
* Note that it works in final world space (i.e. with constraints etc. applied).
*/
static void get_vert2ob_distance(
- int numVerts, float (*v_cos)[3], float *dist, Object *ob, Object *obr)
+ int verts_num, float (*v_cos)[3], float *dist, Object *ob, Object *obr)
{
/* Vertex and ref object coordinates. */
float v_wco[3];
- uint i = numVerts;
+ uint i = verts_num;
while (i-- > 0) {
/* Get world-coordinates of the vertex (constraints and anim included). */
@@ -347,9 +347,7 @@ static void requiredDataMask(Object *UNUSED(ob),
/* No need to ask for CD_PREVIEW_MLOOPCOL... */
}
-static bool dependsOnTime(struct Scene *UNUSED(scene),
- ModifierData *md,
- const int UNUSED(dag_eval_mode))
+static bool dependsOnTime(struct Scene *UNUSED(scene), ModifierData *md)
{
WeightVGProximityModifierData *wmd = (WeightVGProximityModifierData *)md;
@@ -435,7 +433,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *
float *org_w = NULL;
float *new_w = NULL;
int *tidx, *indices = NULL;
- int numIdx = 0;
+ int index_num = 0;
int i;
const bool invert_vgroup_mask = (wmd->proximity_flags & MOD_WVG_PROXIMITY_INVERT_VGROUP_MASK) !=
0;
@@ -450,12 +448,12 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *
#endif
/* Get number of verts. */
- const int numVerts = mesh->totvert;
+ const int verts_num = mesh->totvert;
/* Check if we can just return the original mesh.
* Must have verts and therefore verts assigned to vgroups to do anything useful!
*/
- if ((numVerts == 0) || BLI_listbase_is_empty(&mesh->vertex_group_names)) {
+ if ((verts_num == 0) || BLI_listbase_is_empty(&mesh->vertex_group_names)) {
return mesh;
}
@@ -477,7 +475,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *
return mesh;
}
- dvert = CustomData_duplicate_referenced_layer(&mesh->vdata, CD_MDEFORMVERT, numVerts);
+ dvert = CustomData_duplicate_referenced_layer(&mesh->vdata, CD_MDEFORMVERT, verts_num);
/* Ultimate security check. */
if (!dvert) {
return mesh;
@@ -485,31 +483,31 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *
mesh->dvert = dvert;
/* Find out which vertices to work on (all vertices in vgroup), and get their relevant weight. */
- tidx = MEM_malloc_arrayN(numVerts, sizeof(int), "WeightVGProximity Modifier, tidx");
- tw = MEM_malloc_arrayN(numVerts, sizeof(float), "WeightVGProximity Modifier, tw");
- tdw = MEM_malloc_arrayN(numVerts, sizeof(MDeformWeight *), "WeightVGProximity Modifier, tdw");
- for (i = 0; i < numVerts; i++) {
+ tidx = MEM_malloc_arrayN(verts_num, sizeof(int), "WeightVGProximity Modifier, tidx");
+ tw = MEM_malloc_arrayN(verts_num, sizeof(float), "WeightVGProximity Modifier, tw");
+ tdw = MEM_malloc_arrayN(verts_num, sizeof(MDeformWeight *), "WeightVGProximity Modifier, tdw");
+ for (i = 0; i < verts_num; i++) {
MDeformWeight *_dw = BKE_defvert_find_index(&dvert[i], defgrp_index);
if (_dw) {
- tidx[numIdx] = i;
- tw[numIdx] = _dw->weight;
- tdw[numIdx++] = _dw;
+ tidx[index_num] = i;
+ tw[index_num] = _dw->weight;
+ tdw[index_num++] = _dw;
}
}
/* If no vertices found, return org data! */
- if (numIdx == 0) {
+ if (index_num == 0) {
MEM_freeN(tidx);
MEM_freeN(tw);
MEM_freeN(tdw);
return mesh;
}
- if (numIdx != numVerts) {
- indices = MEM_malloc_arrayN(numIdx, sizeof(int), "WeightVGProximity Modifier, indices");
- memcpy(indices, tidx, sizeof(int) * numIdx);
- org_w = MEM_malloc_arrayN(numIdx, sizeof(float), "WeightVGProximity Modifier, org_w");
- memcpy(org_w, tw, sizeof(float) * numIdx);
- dw = MEM_malloc_arrayN(numIdx, sizeof(MDeformWeight *), "WeightVGProximity Modifier, dw");
- memcpy(dw, tdw, sizeof(MDeformWeight *) * numIdx);
+ if (index_num != verts_num) {
+ indices = MEM_malloc_arrayN(index_num, sizeof(int), "WeightVGProximity Modifier, indices");
+ memcpy(indices, tidx, sizeof(int) * index_num);
+ org_w = MEM_malloc_arrayN(index_num, sizeof(float), "WeightVGProximity Modifier, org_w");
+ memcpy(org_w, tw, sizeof(float) * index_num);
+ dw = MEM_malloc_arrayN(index_num, sizeof(MDeformWeight *), "WeightVGProximity Modifier, dw");
+ memcpy(dw, tdw, sizeof(MDeformWeight *) * index_num);
MEM_freeN(tw);
MEM_freeN(tdw);
}
@@ -517,14 +515,14 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *
org_w = tw;
dw = tdw;
}
- new_w = MEM_malloc_arrayN(numIdx, sizeof(float), "WeightVGProximity Modifier, new_w");
+ new_w = MEM_malloc_arrayN(index_num, sizeof(float), "WeightVGProximity Modifier, new_w");
MEM_freeN(tidx);
/* Get our vertex coordinates. */
- if (numIdx != numVerts) {
+ if (index_num != verts_num) {
float(*tv_cos)[3] = BKE_mesh_vert_coords_alloc(mesh, NULL);
- v_cos = MEM_malloc_arrayN(numIdx, sizeof(float[3]), "WeightVGProximity Modifier, v_cos");
- for (i = 0; i < numIdx; i++) {
+ v_cos = MEM_malloc_arrayN(index_num, sizeof(float[3]), "WeightVGProximity Modifier, v_cos");
+ for (i = 0; i < index_num; i++) {
copy_v3_v3(v_cos[i], tv_cos[indices[i]]);
}
MEM_freeN(tv_cos);
@@ -536,7 +534,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *
/* Compute wanted distances. */
if (wmd->proximity_mode == MOD_WVG_PROXIMITY_OBJECT) {
const float dist = get_ob2ob_distance(ob, obr);
- for (i = 0; i < numIdx; i++) {
+ for (i = 0; i < index_num; i++) {
new_w[i] = dist;
}
}
@@ -556,16 +554,17 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *
BKE_mesh_wrapper_ensure_mdata(target_mesh);
SpaceTransform loc2trgt;
- float *dists_v = use_trgt_verts ? MEM_malloc_arrayN(numIdx, sizeof(float), "dists_v") :
+ float *dists_v = use_trgt_verts ? MEM_malloc_arrayN(index_num, sizeof(float), "dists_v") :
NULL;
- float *dists_e = use_trgt_edges ? MEM_malloc_arrayN(numIdx, sizeof(float), "dists_e") :
+ float *dists_e = use_trgt_edges ? MEM_malloc_arrayN(index_num, sizeof(float), "dists_e") :
NULL;
- float *dists_f = use_trgt_faces ? MEM_malloc_arrayN(numIdx, sizeof(float), "dists_f") :
+ float *dists_f = use_trgt_faces ? MEM_malloc_arrayN(index_num, sizeof(float), "dists_f") :
NULL;
BLI_SPACE_TRANSFORM_SETUP(&loc2trgt, ob, obr);
- get_vert2geom_distance(numIdx, v_cos, dists_v, dists_e, dists_f, target_mesh, &loc2trgt);
- for (i = 0; i < numIdx; i++) {
+ get_vert2geom_distance(
+ index_num, v_cos, dists_v, dists_e, dists_f, target_mesh, &loc2trgt);
+ for (i = 0; i < index_num; i++) {
new_w[i] = dists_v ? dists_v[i] : FLT_MAX;
if (dists_e) {
new_w[i] = min_ff(dists_e[i], new_w[i]);
@@ -581,18 +580,18 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *
}
/* Else, fall back to default obj2vert behavior. */
else {
- get_vert2ob_distance(numIdx, v_cos, new_w, ob, obr);
+ get_vert2ob_distance(index_num, v_cos, new_w, ob, obr);
}
}
else {
- get_vert2ob_distance(numIdx, v_cos, new_w, ob, obr);
+ get_vert2ob_distance(index_num, v_cos, new_w, ob, obr);
}
}
/* Map distances to weights. */
do_map(ob,
new_w,
- numIdx,
+ index_num,
wmd->min_dist,
wmd->max_dist,
wmd->falloff_type,
@@ -602,7 +601,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *
/* Do masking. */
struct Scene *scene = DEG_get_evaluated_scene(ctx->depsgraph);
weightvg_do_mask(ctx,
- numIdx,
+ index_num,
indices,
org_w,
new_w,
@@ -621,12 +620,12 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *
/* Update vgroup. Note we never add nor remove vertices from vgroup here. */
weightvg_update_vg(
- dvert, defgrp_index, dw, numIdx, indices, org_w, false, 0.0f, false, 0.0f, do_normalize);
+ dvert, defgrp_index, dw, index_num, indices, org_w, false, 0.0f, false, 0.0f, do_normalize);
/* If weight preview enabled... */
#if 0 /* XXX Currently done in mod stack :/ */
if (do_prev) {
- DM_update_weight_mcol(ob, dm, 0, org_w, numIdx, indices);
+ DM_update_weight_mcol(ob, dm, 0, org_w, index_num, indices);
}
#endif
diff --git a/source/blender/nodes/NOD_geometry_exec.hh b/source/blender/nodes/NOD_geometry_exec.hh
index dc0965f5d71..96a1904abdd 100644
--- a/source/blender/nodes/NOD_geometry_exec.hh
+++ b/source/blender/nodes/NOD_geometry_exec.hh
@@ -6,6 +6,7 @@
#include "FN_multi_function_builder.hh"
#include "BKE_attribute_access.hh"
+#include "BKE_geometry_fields.hh"
#include "BKE_geometry_set.hh"
#include "BKE_geometry_set_instances.hh"
diff --git a/source/blender/nodes/NOD_geometry_nodes_eval_log.hh b/source/blender/nodes/NOD_geometry_nodes_eval_log.hh
index 319fcdeebb7..16332be5179 100644
--- a/source/blender/nodes/NOD_geometry_nodes_eval_log.hh
+++ b/source/blender/nodes/NOD_geometry_nodes_eval_log.hh
@@ -26,6 +26,8 @@
#include "NOD_derived_node_tree.hh"
+#include "FN_field.hh"
+
#include <chrono>
struct SpaceNode;
@@ -353,6 +355,8 @@ class ModifierLog {
static const TreeLog *find_tree_by_node_editor_context(const SpaceNode &snode);
static const NodeLog *find_node_by_node_editor_context(const SpaceNode &snode,
const bNode &node);
+ static const NodeLog *find_node_by_node_editor_context(const SpaceNode &snode,
+ const StringRef node_name);
static const SocketLog *find_socket_by_node_editor_context(const SpaceNode &snode,
const bNode &node,
const bNodeSocket &socket);
diff --git a/source/blender/nodes/composite/nodes/node_composite_cryptomatte.cc b/source/blender/nodes/composite/nodes/node_composite_cryptomatte.cc
index 162ef07a6dd..67d861aad9f 100644
--- a/source/blender/nodes/composite/nodes/node_composite_cryptomatte.cc
+++ b/source/blender/nodes/composite/nodes/node_composite_cryptomatte.cc
@@ -323,8 +323,8 @@ bNodeSocket *ntreeCompositCryptomatteAddSocket(bNodeTree *ntree, bNode *node)
BLI_assert(node->type == CMP_NODE_CRYPTOMATTE_LEGACY);
NodeCryptomatte *n = static_cast<NodeCryptomatte *>(node->storage);
char sockname[32];
- n->num_inputs++;
- BLI_snprintf(sockname, sizeof(sockname), "Crypto %.2d", n->num_inputs - 1);
+ n->inputs_num++;
+ BLI_snprintf(sockname, sizeof(sockname), "Crypto %.2d", n->inputs_num - 1);
bNodeSocket *sock = nodeAddStaticSocket(
ntree, node, SOCK_IN, SOCK_RGBA, PROP_NONE, nullptr, sockname);
return sock;
@@ -334,12 +334,12 @@ int ntreeCompositCryptomatteRemoveSocket(bNodeTree *ntree, bNode *node)
{
BLI_assert(node->type == CMP_NODE_CRYPTOMATTE_LEGACY);
NodeCryptomatte *n = static_cast<NodeCryptomatte *>(node->storage);
- if (n->num_inputs < 2) {
+ if (n->inputs_num < 2) {
return 0;
}
bNodeSocket *sock = static_cast<bNodeSocket *>(node->inputs.last);
nodeRemoveSocket(ntree, node, sock);
- n->num_inputs--;
+ n->inputs_num--;
return 1;
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_normal.cc b/source/blender/nodes/composite/nodes/node_composite_normal.cc
index c04e4bed660..b4dd0bbacd0 100644
--- a/source/blender/nodes/composite/nodes/node_composite_normal.cc
+++ b/source/blender/nodes/composite/nodes/node_composite_normal.cc
@@ -14,11 +14,15 @@ namespace blender::nodes::node_composite_normal_cc {
static void cmp_node_normal_declare(NodeDeclarationBuilder &b)
{
b.add_input<decl::Vector>(N_("Normal"))
- .default_value({1.0f, 1.0f, 1.0f})
+ .default_value({0.0f, 0.0f, 1.0f})
+ .min(-1.0f)
+ .max(1.0f)
+ .subtype(PROP_DIRECTION);
+ b.add_output<decl::Vector>(N_("Normal"))
+ .default_value({0.0f, 0.0f, 1.0f})
.min(-1.0f)
.max(1.0f)
.subtype(PROP_DIRECTION);
- b.add_output<decl::Vector>(N_("Normal"));
b.add_output<decl::Float>(N_("Dot"));
}
diff --git a/source/blender/nodes/geometry/node_geometry_util.hh b/source/blender/nodes/geometry/node_geometry_util.hh
index 5b7211e44b4..7af3159bbf8 100644
--- a/source/blender/nodes/geometry/node_geometry_util.hh
+++ b/source/blender/nodes/geometry/node_geometry_util.hh
@@ -81,4 +81,14 @@ void separate_geometry(GeometrySet &geometry_set,
std::optional<CustomDataType> node_data_type_to_custom_data_type(eNodeSocketDatatype type);
std::optional<CustomDataType> node_socket_to_custom_data_type(const bNodeSocket &socket);
+class SplineLengthFieldInput final : public GeometryFieldInput {
+ public:
+ SplineLengthFieldInput();
+ GVArray get_varray_for_context(const GeometryComponent &component,
+ AttributeDomain domain,
+ IndexMask mask) const final;
+ uint64_t hash() const override;
+ bool is_equal_to(const fn::FieldNode &other) const override;
+};
+
} // namespace blender::nodes
diff --git a/source/blender/nodes/geometry/nodes/node_geo_convex_hull.cc b/source/blender/nodes/geometry/nodes/node_geo_convex_hull.cc
index 6794671f707..4792fada98b 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_convex_hull.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_convex_hull.cc
@@ -30,25 +30,25 @@ static Mesh *hull_from_bullet(const Mesh *mesh, Span<float3> coords)
{
plConvexHull hull = plConvexHullCompute((float(*)[3])coords.data(), coords.size());
- const int num_verts = plConvexHullNumVertices(hull);
- const int num_faces = num_verts <= 2 ? 0 : plConvexHullNumFaces(hull);
- const int num_loops = num_verts <= 2 ? 0 : plConvexHullNumLoops(hull);
+ const int verts_num = plConvexHullNumVertices(hull);
+ const int faces_num = verts_num <= 2 ? 0 : plConvexHullNumFaces(hull);
+ const int loops_num = verts_num <= 2 ? 0 : plConvexHullNumLoops(hull);
/* Half as many edges as loops, because the mesh is manifold. */
- const int num_edges = num_verts == 2 ? 1 : num_verts < 2 ? 0 : num_loops / 2;
+ const int edges_num = verts_num == 2 ? 1 : verts_num < 2 ? 0 : loops_num / 2;
/* Create Mesh *result with proper capacity. */
Mesh *result;
if (mesh) {
result = BKE_mesh_new_nomain_from_template(
- mesh, num_verts, num_edges, 0, num_loops, num_faces);
+ mesh, verts_num, edges_num, 0, loops_num, faces_num);
}
else {
- result = BKE_mesh_new_nomain(num_verts, num_edges, 0, num_loops, num_faces);
+ result = BKE_mesh_new_nomain(verts_num, edges_num, 0, loops_num, faces_num);
BKE_id_material_eval_ensure_default_slot(&result->id);
}
/* Copy vertices. */
- for (const int i : IndexRange(num_verts)) {
+ for (const int i : IndexRange(verts_num)) {
float co[3];
int original_index;
plConvexHullGetVertex(hull, i, co, &original_index);
@@ -73,9 +73,9 @@ static Mesh *hull_from_bullet(const Mesh *mesh, Span<float3> coords)
/* NOTE: ConvexHull from Bullet uses a half-edge data structure
* for its mesh. To convert that, each half-edge needs to be converted
* to a loop and edges need to be created from that. */
- Array<MLoop> mloop_src(num_loops);
+ Array<MLoop> mloop_src(loops_num);
uint edge_index = 0;
- for (const int i : IndexRange(num_loops)) {
+ for (const int i : IndexRange(loops_num)) {
int v_from;
int v_to;
plConvexHullGetLoop(hull, i, &v_from, &v_to);
@@ -95,7 +95,7 @@ static Mesh *hull_from_bullet(const Mesh *mesh, Span<float3> coords)
edge_index++;
}
}
- if (num_edges == 1) {
+ if (edges_num == 1) {
/* In this case there are no loops. */
MEdge &edge = result->medge[0];
edge.v1 = 0;
@@ -103,13 +103,13 @@ static Mesh *hull_from_bullet(const Mesh *mesh, Span<float3> coords)
edge.flag |= ME_EDGEDRAW | ME_EDGERENDER | ME_LOOSEEDGE;
edge_index++;
}
- BLI_assert(edge_index == num_edges);
+ BLI_assert(edge_index == edges_num);
/* Copy faces. */
Array<int> loops;
int j = 0;
MLoop *loop = result->mloop;
- for (const int i : IndexRange(num_faces)) {
+ for (const int i : IndexRange(faces_num)) {
const int len = plConvexHullGetFaceSize(hull, i);
BLI_assert(len > 2);
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 81ca87eec25..95ea978541c 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_curve_fillet.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_curve_fillet.cc
@@ -551,8 +551,8 @@ static std::unique_ptr<CurveEval> fillet_curve(const CurveEval &input_curve,
Span<SplinePtr> input_splines = input_curve.splines();
std::unique_ptr<CurveEval> output_curve = std::make_unique<CurveEval>();
- const int num_splines = input_splines.size();
- output_curve->resize(num_splines);
+ const int splines_num = input_splines.size();
+ output_curve->resize(splines_num);
MutableSpan<SplinePtr> output_splines = output_curve->splines();
Array<int> spline_offsets = input_curve.control_point_offsets();
diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_length.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_length.cc
index d5769c691c8..11eb472a6e2 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_curve_length.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_curve_length.cc
@@ -1,6 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
-#include "BKE_spline.hh"
+#include "BKE_curves.hh"
+
#include "node_geometry_util.hh"
namespace blender::nodes::node_geo_curve_length_cc {
@@ -18,11 +19,18 @@ static void node_geo_exec(GeoNodeExecParams params)
params.set_default_remaining_outputs();
return;
}
- const std::unique_ptr<CurveEval> curve = curves_to_curve_eval(*curve_set.get_curves_for_read());
+
+ const Curves &curves_id = *curve_set.get_curves_for_read();
+ const bke::CurvesGeometry &curves = bke::CurvesGeometry::wrap(curves_id.geometry);
+ const VArray<bool> cyclic = curves.cyclic();
+
+ curves.ensure_evaluated_lengths();
+
float length = 0.0f;
- for (const SplinePtr &spline : curve->splines()) {
- length += spline->length();
+ for (const int i : curves.curves_range()) {
+ length += curves.evaluated_length_total_for_curve(i, cyclic[i]);
}
+
params.set_output("Length", length);
}
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 5a4c2ad1660..139b17138fa 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_curve_resample.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_curve_resample.cc
@@ -1,11 +1,13 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
#include "BLI_array.hh"
+#include "BLI_index_mask_ops.hh"
+#include "BLI_length_parameterize.hh"
#include "BLI_task.hh"
#include "BLI_timeit.hh"
#include "BKE_attribute_math.hh"
-#include "BKE_spline.hh"
+#include "BKE_curves.hh"
#include "UI_interface.h"
#include "UI_resources.h"
@@ -23,7 +25,7 @@ static void node_declare(NodeDeclarationBuilder &b)
b.add_input<decl::Int>(N_("Count")).default_value(10).min(1).max(100000).supports_field();
b.add_input<decl::Float>(N_("Length"))
.default_value(0.1f)
- .min(0.001f)
+ .min(0.01f)
.supports_field()
.subtype(PROP_DISTANCE);
b.add_output<decl::Geometry>(N_("Curve"));
@@ -54,195 +56,549 @@ static void node_update(bNodeTree *ntree, bNode *node)
nodeSetSocketAvailability(ntree, length_socket, mode == GEO_NODE_CURVE_RESAMPLE_LENGTH);
}
-struct SampleModeParam {
- GeometryNodeCurveResampleMode mode;
- std::optional<Field<float>> length;
- std::optional<Field<int>> count;
- Field<bool> selection;
+/** Returns the number of evaluated points in each curve. Used to deselect curves with none. */
+class EvaluatedCountFieldInput final : public GeometryFieldInput {
+ public:
+ EvaluatedCountFieldInput() : GeometryFieldInput(CPPType::get<int>(), "Evaluated Point Count")
+ {
+ category_ = Category::Generated;
+ }
+
+ GVArray get_varray_for_context(const GeometryComponent &component,
+ const AttributeDomain domain,
+ IndexMask UNUSED(mask)) const final
+ {
+ if (component.type() == GEO_COMPONENT_TYPE_CURVE && domain == ATTR_DOMAIN_CURVE &&
+ !component.is_empty()) {
+ const CurveComponent &curve_component = static_cast<const CurveComponent &>(component);
+ const Curves &curves_id = *curve_component.get_for_read();
+ const bke::CurvesGeometry &curves = bke::CurvesGeometry::wrap(curves_id.geometry);
+ curves.ensure_evaluated_offsets();
+ return VArray<int>::ForFunc(curves.curves_num(), [&](const int64_t index) -> int {
+ return curves.evaluated_points_for_curve(index).size();
+ });
+ }
+ return {};
+ }
+
+ uint64_t hash() const override
+ {
+ /* Some random constant hash. */
+ return 234905872379865;
+ }
+
+ bool is_equal_to(const fn::FieldNode &other) const override
+ {
+ return dynamic_cast<const EvaluatedCountFieldInput *>(&other) != nullptr;
+ }
};
-static SplinePtr resample_spline(const Spline &src, const int count)
+/**
+ * Return true if the attribute should be copied/interpolated to the result curves.
+ * Don't output attributes that correspond to curve types that have no curves in the result.
+ */
+static bool interpolate_attribute_to_curves(const AttributeIDRef &attribute_id,
+ const std::array<int, CURVE_TYPES_NUM> &type_counts)
{
- std::unique_ptr<PolySpline> dst = std::make_unique<PolySpline>();
- Spline::copy_base_settings(src, *dst);
-
- if (src.evaluated_edges_size() < 1 || count == 1) {
- dst->resize(1);
- dst->positions().first() = src.positions().first();
- dst->radii().first() = src.radii().first();
- dst->tilts().first() = src.tilts().first();
-
- src.attributes.foreach_attribute(
- [&](const AttributeIDRef &attribute_id, const AttributeMetaData &meta_data) {
- std::optional<GSpan> src_attribute = src.attributes.get_for_read(attribute_id);
- if (dst->attributes.create(attribute_id, meta_data.data_type)) {
- std::optional<GMutableSpan> dst_attribute = dst->attributes.get_for_write(
- attribute_id);
- if (dst_attribute) {
- src_attribute->type().copy_assign(src_attribute->data(), dst_attribute->data());
- return true;
- }
- }
- BLI_assert_unreachable();
- return false;
- },
- ATTR_DOMAIN_POINT);
- return dst;
+ if (!attribute_id.is_named()) {
+ return true;
}
+ if (ELEM(attribute_id.name(),
+ "handle_type_left",
+ "handle_type_right",
+ "handle_left",
+ "handle_right")) {
+ return type_counts[CURVE_TYPE_BEZIER] != 0;
+ }
+ if (ELEM(attribute_id.name(), "nurbs_weight")) {
+ return type_counts[CURVE_TYPE_NURBS] != 0;
+ }
+ return true;
+}
- dst->resize(count);
+/**
+ * Return true if the attribute should be copied to poly curves.
+ */
+static bool interpolate_attribute_to_poly_curve(const AttributeIDRef &attribute_id)
+{
+ static const Set<StringRef> no_interpolation{{
+ "handle_type_left",
+ "handle_type_right",
+ "handle_position_right",
+ "handle_position_left",
+ "nurbs_weight",
+ }};
+ return !(attribute_id.is_named() && no_interpolation.contains(attribute_id.name()));
+}
- Array<float> uniform_samples = src.sample_uniform_index_factors(count);
+/**
+ * Retrieve spans from source and result attributes.
+ */
+static void retrieve_attribute_spans(const Span<AttributeIDRef> ids,
+ const CurveComponent &src_component,
+ CurveComponent &dst_component,
+ Vector<GSpan> &src,
+ Vector<GMutableSpan> &dst,
+ Vector<OutputAttribute> &dst_attributes)
+{
+ for (const int i : ids.index_range()) {
+ GVArray src_attribute = src_component.attribute_try_get_for_read(ids[i], ATTR_DOMAIN_POINT);
+ BLI_assert(src_attribute);
+ src.append(src_attribute.get_internal_span());
+
+ const CustomDataType data_type = bke::cpp_type_to_custom_data_type(src_attribute.type());
+ OutputAttribute dst_attribute = dst_component.attribute_try_get_for_output_only(
+ ids[i], ATTR_DOMAIN_POINT, data_type);
+ dst.append(dst_attribute.as_span());
+ dst_attributes.append(std::move(dst_attribute));
+ }
+}
- src.sample_with_index_factors<float3>(
- src.evaluated_positions(), uniform_samples, dst->positions());
+struct AttributesForInterpolation : NonCopyable, NonMovable {
+ Vector<GSpan> src;
+ Vector<GMutableSpan> dst;
- src.sample_with_index_factors<float>(
- src.interpolate_to_evaluated(src.radii()), uniform_samples, dst->radii());
+ Vector<OutputAttribute> dst_attributes;
- src.sample_with_index_factors<float>(
- src.interpolate_to_evaluated(src.tilts()), uniform_samples, dst->tilts());
+ Vector<GSpan> src_no_interpolation;
+ Vector<GMutableSpan> dst_no_interpolation;
+};
- src.attributes.foreach_attribute(
- [&](const AttributeIDRef &attribute_id, const AttributeMetaData &meta_data) {
- std::optional<GSpan> input_attribute = src.attributes.get_for_read(attribute_id);
- if (dst->attributes.create(attribute_id, meta_data.data_type)) {
- std::optional<GMutableSpan> output_attribute = dst->attributes.get_for_write(
- attribute_id);
- if (output_attribute) {
- src.sample_with_index_factors(src.interpolate_to_evaluated(*input_attribute),
- uniform_samples,
- *output_attribute);
- return true;
- }
+/**
+ * Gather a set of all generic attribute IDs to copy to the result curves.
+ */
+static void gather_point_attributes_to_interpolate(const CurveComponent &src_component,
+ CurveComponent &dst_component,
+ AttributesForInterpolation &result)
+{
+ const Curves &dst_curves_id = *dst_component.get_for_read();
+ const bke::CurvesGeometry &dst_curves = bke::CurvesGeometry::wrap(dst_curves_id.geometry);
+ const std::array<int, CURVE_TYPES_NUM> type_counts = dst_curves.count_curve_types();
+
+ VectorSet<AttributeIDRef> ids;
+ VectorSet<AttributeIDRef> ids_no_interpolation;
+ src_component.attribute_foreach(
+ [&](const AttributeIDRef &id, const AttributeMetaData meta_data) {
+ if (meta_data.domain != ATTR_DOMAIN_POINT) {
+ return true;
+ }
+ if (!interpolate_attribute_to_curves(id, type_counts)) {
+ return true;
+ }
+ if (interpolate_attribute_to_poly_curve(id)) {
+ ids.add_new(id);
+ }
+ else {
+ ids_no_interpolation.add_new(id);
}
+ return true;
+ });
+
+ /* Position is handled differently since it has non-generic interpolation for Bezier
+ * curves and because the evaluated positions are cached for each evaluated point. */
+ ids.remove_contained("position");
+
+ retrieve_attribute_spans(
+ ids, src_component, dst_component, result.src, result.dst, result.dst_attributes);
+
+ /* Attributes that aren't interpolated like Bezier handles still have to be be copied
+ * to the result when there are any unselected curves of the corresponding type. */
+ retrieve_attribute_spans(ids_no_interpolation,
+ src_component,
+ dst_component,
+ result.src_no_interpolation,
+ result.dst_no_interpolation,
+ result.dst_attributes);
+}
- BLI_assert_unreachable();
- return false;
- },
- ATTR_DOMAIN_POINT);
+/**
+ * Copy the provided point attribute values between all curves in the #curve_ranges index
+ * ranges, assuming that all curves are the same size in #src_curves and #dst_curves.
+ */
+template<typename T>
+static void copy_between_curves(const bke::CurvesGeometry &src_curves,
+ const bke::CurvesGeometry &dst_curves,
+ const Span<IndexRange> curve_ranges,
+ const Span<T> src,
+ const MutableSpan<T> dst)
+{
+ threading::parallel_for(curve_ranges.index_range(), 512, [&](IndexRange range) {
+ for (const IndexRange range : curve_ranges.slice(range)) {
+ const IndexRange src_points = src_curves.points_for_curves(range);
+ const IndexRange dst_points = dst_curves.points_for_curves(range);
+ /* The arrays might be large, so a threaded copy might make sense here too. */
+ dst.slice(dst_points).copy_from(src.slice(src_points));
+ }
+ });
+}
+static void copy_between_curves(const bke::CurvesGeometry &src_curves,
+ const bke::CurvesGeometry &dst_curves,
+ const Span<IndexRange> unselected_ranges,
+ const GSpan src,
+ const GMutableSpan dst)
+{
+ attribute_math::convert_to_static_type(src.type(), [&](auto dummy) {
+ using T = decltype(dummy);
+ copy_between_curves(src_curves, dst_curves, unselected_ranges, src.typed<T>(), dst.typed<T>());
+ });
+}
- return dst;
+/**
+ * Copy the size of every curve in #curve_ranges to the corresponding index in #counts.
+ */
+static void fill_curve_counts(const bke::CurvesGeometry &src_curves,
+ const Span<IndexRange> curve_ranges,
+ MutableSpan<int> counts)
+{
+ threading::parallel_for(curve_ranges.index_range(), 512, [&](IndexRange ranges_range) {
+ for (const IndexRange curves_range : curve_ranges.slice(ranges_range)) {
+ for (const int i : curves_range) {
+ counts[i] = src_curves.points_for_curve(i).size();
+ }
+ }
+ });
}
-static SplinePtr resample_spline_evaluated(const Spline &src)
+/**
+ * Turn an array of sizes into the offset at each index including all previous sizes.
+ */
+static void accumulate_counts_to_offsets(MutableSpan<int> counts_to_offsets)
{
- std::unique_ptr<PolySpline> dst = std::make_unique<PolySpline>();
- Spline::copy_base_settings(src, *dst);
- dst->resize(src.evaluated_points_size());
-
- dst->positions().copy_from(src.evaluated_positions());
- dst->positions().copy_from(src.evaluated_positions());
- src.interpolate_to_evaluated(src.radii()).materialize(dst->radii());
- src.interpolate_to_evaluated(src.tilts()).materialize(dst->tilts());
-
- src.attributes.foreach_attribute(
- [&](const AttributeIDRef &attribute_id, const AttributeMetaData &meta_data) {
- std::optional<GSpan> src_attribute = src.attributes.get_for_read(attribute_id);
- if (dst->attributes.create(attribute_id, meta_data.data_type)) {
- std::optional<GMutableSpan> dst_attribute = dst->attributes.get_for_write(attribute_id);
- if (dst_attribute) {
- src.interpolate_to_evaluated(*src_attribute).materialize(dst_attribute->data());
- return true;
+ int total = 0;
+ for (const int i : counts_to_offsets.index_range().drop_back(1)) {
+ const int count = counts_to_offsets[i];
+ BLI_assert(count > 0);
+ counts_to_offsets[i] = total;
+ total += count;
+ }
+ counts_to_offsets.last() = total;
+}
+
+/**
+ * Create new curves where the selected curves have been resampled with a number of uniform-length
+ * samples defined by the count field. Interpolate attributes to the result, with an accuracy that
+ * depends on the curve's resolution parameter.
+ *
+ * \warning The values provided by the #count_field must be 1 or greater.
+ * \warning Curves with no evaluated points must not be selected.
+ */
+static Curves *resample_to_uniform_count(const CurveComponent &src_component,
+ const Field<bool> &selection_field,
+ const Field<int> &count_field)
+{
+ const Curves &src_curves_id = *src_component.get_for_read();
+ const bke::CurvesGeometry &src_curves = bke::CurvesGeometry::wrap(src_curves_id.geometry);
+
+ /* Create the new curves without any points and evaluate the final count directly
+ * into the offsets array, in order to be accumulated into offsets later. */
+ Curves *dst_curves_id = bke::curves_new_nomain(0, src_curves.curves_num());
+ bke::CurvesGeometry &dst_curves = bke::CurvesGeometry::wrap(dst_curves_id->geometry);
+ CurveComponent dst_component;
+ dst_component.replace(dst_curves_id, GeometryOwnershipType::Editable);
+ /* Directly copy curve attributes, since they stay the same (except for curve types). */
+ CustomData_copy(&src_curves.curve_data,
+ &dst_curves.curve_data,
+ CD_MASK_ALL,
+ CD_DUPLICATE,
+ src_curves.curves_num());
+ MutableSpan<int> dst_offsets = dst_curves.offsets();
+
+ GeometryComponentFieldContext field_context{src_component, ATTR_DOMAIN_CURVE};
+ fn::FieldEvaluator evaluator{field_context, src_curves.curves_num()};
+ evaluator.set_selection(selection_field);
+ evaluator.add_with_destination(count_field, dst_offsets);
+ evaluator.evaluate();
+ const IndexMask selection = evaluator.get_evaluated_selection_as_mask();
+ const Vector<IndexRange> unselected_ranges = selection.extract_ranges_invert(
+ src_curves.curves_range(), nullptr);
+
+ /* Fill the counts for the curves that aren't selected and accumulate the counts into offsets. */
+ fill_curve_counts(src_curves, unselected_ranges, dst_offsets);
+ accumulate_counts_to_offsets(dst_offsets);
+ dst_curves.resize(dst_offsets.last(), dst_curves.curves_num());
+
+ /* All resampled curves are poly curves. */
+ dst_curves.curve_types().fill_indices(selection, CURVE_TYPE_POLY);
+
+ VArray<bool> curves_cyclic = src_curves.cyclic();
+ VArray<int8_t> curve_types = src_curves.curve_types();
+ Span<float3> evaluated_positions = src_curves.evaluated_positions();
+ MutableSpan<float3> dst_positions = dst_curves.positions();
+
+ AttributesForInterpolation attributes;
+ gather_point_attributes_to_interpolate(src_component, dst_component, attributes);
+
+ src_curves.ensure_evaluated_lengths();
+
+ /* Sampling arbitrary attributes works by first interpolating them to the curve's standard
+ * "evaluated points" and then interpolating that result with the uniform samples. This is
+ * potentially wasteful when down-sampling a curve to many fewer points. There are two possible
+ * solutions: only sample the necessary points for interpolation, or first sample curve
+ * parameter/segment indices and evaluate the curve directly. */
+ Array<int> sample_indices(dst_curves.points_num());
+ Array<float> sample_factors(dst_curves.points_num());
+
+ /* Use a "for each group of curves: for each attribute: for each curve" pattern to work on
+ * smaller sections of data that ideally fit into CPU cache better than simply one attribute at a
+ * time or one curve at a time. */
+ threading::parallel_for(selection.index_range(), 512, [&](IndexRange selection_range) {
+ const IndexMask sliced_selection = selection.slice(selection_range);
+
+ Vector<std::byte> evaluated_buffer;
+
+ /* Gather uniform samples based on the accumulated lengths of the original curve. */
+ for (const int i_curve : sliced_selection) {
+ const bool cyclic = curves_cyclic[i_curve];
+ const IndexRange dst_points = dst_curves.points_for_curve(i_curve);
+ length_parameterize::create_uniform_samples(
+ src_curves.evaluated_lengths_for_curve(i_curve, cyclic),
+ curves_cyclic[i_curve],
+ sample_indices.as_mutable_span().slice(dst_points),
+ sample_factors.as_mutable_span().slice(dst_points));
+ }
+
+ /* For every attribute, evaluate attributes from every curve in the range in the original
+ * curve's "evaluated points", then use linear interpolation to sample to the result. */
+ for (const int i_attribute : attributes.dst.index_range()) {
+ attribute_math::convert_to_static_type(attributes.src[i_attribute].type(), [&](auto dummy) {
+ using T = decltype(dummy);
+ Span<T> src = attributes.src[i_attribute].typed<T>();
+ MutableSpan<T> dst = attributes.dst[i_attribute].typed<T>();
+
+ for (const int i_curve : sliced_selection) {
+ const IndexRange src_points = src_curves.points_for_curve(i_curve);
+ const IndexRange dst_points = dst_curves.points_for_curve(i_curve);
+
+ if (curve_types[i_curve] == CURVE_TYPE_POLY) {
+ length_parameterize::linear_interpolation(src.slice(src_points),
+ sample_indices.as_span().slice(dst_points),
+ sample_factors.as_span().slice(dst_points),
+ dst.slice(dst_points));
+ }
+ else {
+ const int evaluated_size = src_curves.evaluated_points_for_curve(i_curve).size();
+ evaluated_buffer.clear();
+ evaluated_buffer.resize(sizeof(T) * evaluated_size);
+ MutableSpan<T> evaluated = evaluated_buffer.as_mutable_span().cast<T>();
+ src_curves.interpolate_to_evaluated(i_curve, src.slice(src_points), evaluated);
+
+ length_parameterize::linear_interpolation(evaluated.as_span(),
+ sample_indices.as_span().slice(dst_points),
+ sample_factors.as_span().slice(dst_points),
+ dst.slice(dst_points));
}
}
+ });
+ }
- BLI_assert_unreachable();
- return true;
- },
- ATTR_DOMAIN_POINT);
+ /* Interpolate the evaluated positions to the resampled curves. */
+ for (const int i_curve : sliced_selection) {
+ const IndexRange src_points = src_curves.evaluated_points_for_curve(i_curve);
+ const IndexRange dst_points = dst_curves.points_for_curve(i_curve);
+ length_parameterize::linear_interpolation(evaluated_positions.slice(src_points),
+ sample_indices.as_span().slice(dst_points),
+ sample_factors.as_span().slice(dst_points),
+ dst_positions.slice(dst_points));
+ }
- return dst;
+ /* Fill the default value for non-interpolating attributes that still must be copied. */
+ for (GMutableSpan dst : attributes.dst_no_interpolation) {
+ for (const int i_curve : sliced_selection) {
+ const IndexRange dst_points = dst_curves.points_for_curve(i_curve);
+ dst.type().value_initialize_n(dst.slice(dst_points).data(), dst_points.size());
+ }
+ }
+ });
+
+ /* Any attribute data from unselected curve points can be directly copied. */
+ for (const int i : attributes.src.index_range()) {
+ copy_between_curves(
+ src_curves, dst_curves, unselected_ranges, attributes.src[i], attributes.dst[i]);
+ }
+ for (const int i : attributes.src_no_interpolation.index_range()) {
+ copy_between_curves(src_curves,
+ dst_curves,
+ unselected_ranges,
+ attributes.src_no_interpolation[i],
+ attributes.dst_no_interpolation[i]);
+ }
+
+ /* Copy positions for unselected curves. */
+ Span<float3> src_positions = src_curves.positions();
+ copy_between_curves(src_curves, dst_curves, unselected_ranges, src_positions, dst_positions);
+
+ for (OutputAttribute &attribute : attributes.dst_attributes) {
+ attribute.save();
+ }
+
+ return dst_curves_id;
}
-static std::unique_ptr<CurveEval> resample_curve(const CurveComponent *component,
- const SampleModeParam &mode_param)
+/**
+ * Evaluate each selected curve to its implicit evaluated points.
+ *
+ * \warning Curves with no evaluated points must not be selected.
+ */
+static Curves *resample_to_evaluated(const CurveComponent &src_component,
+ const Field<bool> &selection_field)
{
- const std::unique_ptr<CurveEval> input_curve = curves_to_curve_eval(*component->get_for_read());
- GeometryComponentFieldContext field_context{*component, ATTR_DOMAIN_CURVE};
- const int domain_size = component->attribute_domain_size(ATTR_DOMAIN_CURVE);
-
- Span<SplinePtr> input_splines = input_curve->splines();
-
- std::unique_ptr<CurveEval> output_curve = std::make_unique<CurveEval>();
- output_curve->resize(input_splines.size());
- MutableSpan<SplinePtr> output_splines = output_curve->splines();
-
- if (mode_param.mode == GEO_NODE_CURVE_RESAMPLE_COUNT) {
- fn::FieldEvaluator evaluator{field_context, domain_size};
- evaluator.add(*mode_param.count);
- evaluator.add(mode_param.selection);
- evaluator.evaluate();
- const VArray<int> &cuts = evaluator.get_evaluated<int>(0);
- const VArray<bool> &selections = evaluator.get_evaluated<bool>(1);
-
- threading::parallel_for(input_splines.index_range(), 128, [&](IndexRange range) {
- for (const int i : range) {
- BLI_assert(mode_param.count);
- if (selections[i] && input_splines[i]->evaluated_points_size() > 0) {
- output_splines[i] = resample_spline(*input_splines[i], std::max(cuts[i], 1));
- }
- else {
- output_splines[i] = input_splines[i]->copy();
+ const Curves &src_curves_id = *src_component.get_for_read();
+ const bke::CurvesGeometry &src_curves = bke::CurvesGeometry::wrap(src_curves_id.geometry);
+
+ GeometryComponentFieldContext field_context{src_component, ATTR_DOMAIN_CURVE};
+ fn::FieldEvaluator evaluator{field_context, src_curves.curves_num()};
+ evaluator.set_selection(selection_field);
+ evaluator.evaluate();
+ const IndexMask selection = evaluator.get_evaluated_selection_as_mask();
+ const Vector<IndexRange> unselected_ranges = selection.extract_ranges_invert(
+ src_curves.curves_range(), nullptr);
+
+ Curves *dst_curves_id = bke::curves_new_nomain(0, src_curves.curves_num());
+ bke::CurvesGeometry &dst_curves = bke::CurvesGeometry::wrap(dst_curves_id->geometry);
+ CurveComponent dst_component;
+ dst_component.replace(dst_curves_id, GeometryOwnershipType::Editable);
+ /* Directly copy curve attributes, since they stay the same (except for curve types). */
+ CustomData_copy(&src_curves.curve_data,
+ &dst_curves.curve_data,
+ CD_MASK_ALL,
+ CD_DUPLICATE,
+ src_curves.curves_num());
+ /* All resampled curves are poly curves. */
+ dst_curves.curve_types().fill_indices(selection, CURVE_TYPE_POLY);
+ MutableSpan<int> dst_offsets = dst_curves.offsets();
+
+ src_curves.ensure_evaluated_offsets();
+ threading::parallel_for(selection.index_range(), 4096, [&](IndexRange range) {
+ for (const int i : selection.slice(range)) {
+ dst_offsets[i] = src_curves.evaluated_points_for_curve(i).size();
+ }
+ });
+ fill_curve_counts(src_curves, unselected_ranges, dst_offsets);
+ accumulate_counts_to_offsets(dst_offsets);
+
+ dst_curves.resize(dst_offsets.last(), dst_curves.curves_num());
+
+ /* Create the correct number of uniform-length samples for every selected curve. */
+ Span<float3> evaluated_positions = src_curves.evaluated_positions();
+ MutableSpan<float3> dst_positions = dst_curves.positions();
+
+ AttributesForInterpolation attributes;
+ gather_point_attributes_to_interpolate(src_component, dst_component, attributes);
+
+ threading::parallel_for(selection.index_range(), 512, [&](IndexRange selection_range) {
+ const IndexMask sliced_selection = selection.slice(selection_range);
+
+ /* Evaluate generic point attributes directly to the result attributes. */
+ for (const int i_attribute : attributes.dst.index_range()) {
+ attribute_math::convert_to_static_type(attributes.src[i_attribute].type(), [&](auto dummy) {
+ using T = decltype(dummy);
+ Span<T> src = attributes.src[i_attribute].typed<T>();
+ MutableSpan<T> dst = attributes.dst[i_attribute].typed<T>();
+
+ for (const int i_curve : sliced_selection) {
+ const IndexRange src_points = src_curves.points_for_curve(i_curve);
+ const IndexRange dst_points = dst_curves.points_for_curve(i_curve);
+ src_curves.interpolate_to_evaluated(
+ i_curve, src.slice(src_points), dst.slice(dst_points));
}
+ });
+ }
+
+ /* Copy the evaluated positions to the selected curves. */
+ for (const int i_curve : sliced_selection) {
+ const IndexRange src_points = src_curves.evaluated_points_for_curve(i_curve);
+ const IndexRange dst_points = dst_curves.points_for_curve(i_curve);
+ dst_positions.slice(dst_points).copy_from(evaluated_positions.slice(src_points));
+ }
+
+ /* Fill the default value for non-interpolating attributes that still must be copied. */
+ for (GMutableSpan dst : attributes.dst_no_interpolation) {
+ for (const int i_curve : sliced_selection) {
+ const IndexRange dst_points = dst_curves.points_for_curve(i_curve);
+ dst.type().value_initialize_n(dst.slice(dst_points).data(), dst_points.size());
}
- });
+ }
+ });
+
+ /* Any attribute data from unselected curve points can be directly copied. */
+ for (const int i : attributes.src.index_range()) {
+ copy_between_curves(
+ src_curves, dst_curves, unselected_ranges, attributes.src[i], attributes.dst[i]);
}
- else if (mode_param.mode == GEO_NODE_CURVE_RESAMPLE_LENGTH) {
- fn::FieldEvaluator evaluator{field_context, domain_size};
- evaluator.add(*mode_param.length);
- evaluator.add(mode_param.selection);
- evaluator.evaluate();
- const VArray<float> &lengths = evaluator.get_evaluated<float>(0);
- const VArray<bool> &selections = evaluator.get_evaluated<bool>(1);
-
- threading::parallel_for(input_splines.index_range(), 128, [&](IndexRange range) {
- for (const int i : range) {
- if (selections[i] && input_splines[i]->evaluated_points_size() > 0) {
- /* Don't allow asymptotic count increase for low resolution values. */
- const float divide_length = std::max(lengths[i], 0.0001f);
- const float spline_length = input_splines[i]->length();
- const int count = std::max(int(spline_length / divide_length) + 1, 1);
- output_splines[i] = resample_spline(*input_splines[i], count);
- }
- else {
- output_splines[i] = input_splines[i]->copy();
- }
- }
- });
+ for (const int i : attributes.src_no_interpolation.index_range()) {
+ copy_between_curves(src_curves,
+ dst_curves,
+ unselected_ranges,
+ attributes.src_no_interpolation[i],
+ attributes.dst_no_interpolation[i]);
}
- else if (mode_param.mode == GEO_NODE_CURVE_RESAMPLE_EVALUATED) {
- fn::FieldEvaluator evaluator{field_context, domain_size};
- evaluator.add(mode_param.selection);
- evaluator.evaluate();
- const VArray<bool> &selections = evaluator.get_evaluated<bool>(0);
-
- threading::parallel_for(input_splines.index_range(), 128, [&](IndexRange range) {
- for (const int i : range) {
- if (selections[i] && input_splines[i]->evaluated_points_size() > 0) {
- output_splines[i] = resample_spline_evaluated(*input_splines[i]);
- }
- else {
- output_splines[i] = input_splines[i]->copy();
- }
- }
- });
+
+ /* Copy positions for unselected curves. */
+ Span<float3> src_positions = src_curves.positions();
+ copy_between_curves(src_curves, dst_curves, unselected_ranges, src_positions, dst_positions);
+
+ for (OutputAttribute &attribute : attributes.dst_attributes) {
+ attribute.save();
}
- output_curve->attributes = input_curve->attributes;
- return output_curve;
+
+ return dst_curves_id;
}
-static void geometry_set_curve_resample(GeometrySet &geometry_set,
- const SampleModeParam &mode_param)
+/**
+ * Create a resampled curve point count field for both "uniform" options.
+ * The complexity is handled here in order to make the actual resampling functions simpler.
+ */
+static Field<int> get_curve_count_field(GeoNodeExecParams params,
+ const GeometryNodeCurveResampleMode mode)
{
- if (!geometry_set.has_curves()) {
- return;
+ if (mode == GEO_NODE_CURVE_RESAMPLE_COUNT) {
+ static fn::CustomMF_SI_SO<int, int> max_one_fn("Clamp Above One",
+ [](int value) { return std::max(1, value); });
+ auto clamp_op = std::make_shared<FieldOperation>(
+ FieldOperation(max_one_fn, {Field<int>(params.extract_input<Field<int>>("Count"))}));
+
+ return Field<int>(std::move(clamp_op));
}
- std::unique_ptr<CurveEval> output_curve = resample_curve(
- geometry_set.get_component_for_read<CurveComponent>(), mode_param);
+ if (mode == GEO_NODE_CURVE_RESAMPLE_LENGTH) {
+ static fn::CustomMF_SI_SI_SO<float, float, int> get_count_fn(
+ "Length Input to Count", [](const float curve_length, const float sample_length) {
+ /* Find the number of sampled segments by dividing the total length by
+ * the sample length. Then there is one more sampled point than segment. */
+ const int count = int(curve_length / sample_length) + 1;
+ return std::max(1, count);
+ });
+
+ auto get_count_op = std::make_shared<FieldOperation>(
+ FieldOperation(get_count_fn,
+ {Field<float>(std::make_shared<SplineLengthFieldInput>()),
+ params.extract_input<Field<float>>("Length")}));
+
+ return Field<int>(std::move(get_count_op));
+ }
+
+ BLI_assert_unreachable();
+ return {};
+}
+
+/**
+ * Create a selection field that removes curves without any evaluated points (invalid NURBS curves)
+ * from the original selection provided to the node. This is here to simplify the sampling actual
+ * resampling code.
+ */
+static Field<bool> get_selection_field(GeoNodeExecParams params)
+{
+ static fn::CustomMF_SI_SI_SO<bool, int, bool> get_selection_fn(
+ "Create Curve Selection", [](const bool orig_selection, const int evaluated_points_num) {
+ return orig_selection && evaluated_points_num > 1;
+ });
+
+ auto selection_op = std::make_shared<FieldOperation>(
+ FieldOperation(get_selection_fn,
+ {params.extract_input<Field<bool>>("Selection"),
+ Field<int>(std::make_shared<EvaluatedCountFieldInput>())}));
- geometry_set.replace_curves(curve_eval_to_curves(*output_curve));
+ return Field<bool>(std::move(selection_op));
}
static void node_geo_exec(GeoNodeExecParams params)
@@ -252,25 +608,38 @@ static void node_geo_exec(GeoNodeExecParams params)
const NodeGeometryCurveResample &storage = node_storage(params.node());
const GeometryNodeCurveResampleMode mode = (GeometryNodeCurveResampleMode)storage.mode;
- SampleModeParam mode_param;
- mode_param.mode = mode;
- mode_param.selection = params.extract_input<Field<bool>>("Selection");
+ const Field<bool> selection = get_selection_field(params);
- if (mode == GEO_NODE_CURVE_RESAMPLE_COUNT) {
- Field<int> count = params.extract_input<Field<int>>("Count");
- if (count < 1) {
- params.set_default_remaining_outputs();
- return;
+ switch (mode) {
+ case GEO_NODE_CURVE_RESAMPLE_COUNT:
+ case GEO_NODE_CURVE_RESAMPLE_LENGTH: {
+ Field<int> count = get_curve_count_field(params, mode);
+
+ geometry_set.modify_geometry_sets([&](GeometrySet &geometry_set) {
+ if (!geometry_set.has_curves()) {
+ return;
+ }
+
+ Curves *result = resample_to_uniform_count(
+ *geometry_set.get_component_for_read<CurveComponent>(), selection, count);
+
+ geometry_set.replace_curves(result);
+ });
+ break;
}
- mode_param.count.emplace(count);
- }
- else if (mode == GEO_NODE_CURVE_RESAMPLE_LENGTH) {
- Field<float> resolution = params.extract_input<Field<float>>("Length");
- mode_param.length.emplace(resolution);
- }
+ case GEO_NODE_CURVE_RESAMPLE_EVALUATED:
+ geometry_set.modify_geometry_sets([&](GeometrySet &geometry_set) {
+ if (!geometry_set.has_curves()) {
+ return;
+ }
- geometry_set.modify_geometry_sets(
- [&](GeometrySet &geometry_set) { geometry_set_curve_resample(geometry_set, mode_param); });
+ Curves *result = resample_to_evaluated(
+ *geometry_set.get_component_for_read<CurveComponent>(), selection);
+
+ geometry_set.replace_curves(result);
+ });
+ break;
+ }
params.set_output("Curve", std::move(geometry_set));
}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_set_handle_type.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_set_handle_type.cc
index e8ba78816a5..169f808c473 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_curve_set_handle_type.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_curve_set_handle_type.cc
@@ -1,6 +1,8 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
-#include "BKE_spline.hh"
+#include <atomic>
+
+#include "BKE_curves.hh"
#include "UI_interface.h"
#include "UI_resources.h"
@@ -49,6 +51,33 @@ static HandleType handle_type_from_input_type(GeometryNodeCurveHandleType type)
return BEZIER_HANDLE_AUTO;
}
+static void set_type_in_component(CurveComponent &component,
+ const GeometryNodeCurveHandleMode mode,
+ const HandleType new_handle_type,
+ const Field<bool> &selection_field)
+{
+ Curves &curves_id = *component.get_for_write();
+ bke::CurvesGeometry &curves = bke::CurvesGeometry::wrap(curves_id.geometry);
+
+ GeometryComponentFieldContext field_context{component, ATTR_DOMAIN_POINT};
+ fn::FieldEvaluator evaluator{field_context, curves.points_num()};
+ evaluator.set_selection(selection_field);
+ evaluator.evaluate();
+ const IndexMask selection = evaluator.get_evaluated_selection_as_mask();
+
+ if (mode & GEO_NODE_CURVE_HANDLE_LEFT) {
+ curves.handle_types_left().fill_indices(selection, new_handle_type);
+ }
+ if (mode & GEO_NODE_CURVE_HANDLE_RIGHT) {
+ curves.handle_types_right().fill_indices(selection, new_handle_type);
+ }
+
+ /* Eagerly calculate automatically derived handle positions if necessary. */
+ if (ELEM(new_handle_type, BEZIER_HANDLE_AUTO, BEZIER_HANDLE_VECTOR, BEZIER_HANDLE_ALIGN)) {
+ curves.calculate_bezier_auto_handles();
+ }
+}
+
static void node_geo_exec(GeoNodeExecParams params)
{
const NodeGeometryCurveSetHandles &storage = node_storage(params.node());
@@ -58,62 +87,33 @@ static void node_geo_exec(GeoNodeExecParams params)
GeometrySet geometry_set = params.extract_input<GeometrySet>("Curve");
Field<bool> selection_field = params.extract_input<Field<bool>>("Selection");
- bool has_bezier_spline = false;
+ const HandleType new_handle_type = handle_type_from_input_type(type);
+
+ std::atomic<bool> has_curves = false;
+ std::atomic<bool> has_bezier = false;
+
geometry_set.modify_geometry_sets([&](GeometrySet &geometry_set) {
if (!geometry_set.has_curves()) {
return;
}
-
- /* Retrieve data for write access so we can avoid new allocations for the handles data. */
- CurveComponent &curve_component = geometry_set.get_component_for_write<CurveComponent>();
- std::unique_ptr<CurveEval> curve = curves_to_curve_eval(*curve_component.get_for_read());
- MutableSpan<SplinePtr> splines = curve->splines();
-
- GeometryComponentFieldContext field_context{curve_component, ATTR_DOMAIN_POINT};
- const int domain_size = curve_component.attribute_domain_size(ATTR_DOMAIN_POINT);
-
- fn::FieldEvaluator selection_evaluator{field_context, domain_size};
- selection_evaluator.add(selection_field);
- selection_evaluator.evaluate();
- const VArray<bool> &selection = selection_evaluator.get_evaluated<bool>(0);
-
- const HandleType new_handle_type = handle_type_from_input_type(type);
- int point_index = 0;
-
- for (SplinePtr &spline : splines) {
- if (spline->type() != CURVE_TYPE_BEZIER) {
- point_index += spline->positions().size();
- continue;
- }
-
- has_bezier_spline = true;
- BezierSpline &bezier_spline = static_cast<BezierSpline &>(*spline);
- if (ELEM(new_handle_type, BEZIER_HANDLE_FREE, BEZIER_HANDLE_ALIGN)) {
- /* In this case the automatically calculated handle types need to be "baked", because
- * they're possibly changing from a type that is calculated automatically to a type that
- * is positioned manually. */
- bezier_spline.ensure_auto_handles();
- }
-
- for (int i_point : IndexRange(bezier_spline.size())) {
- if (selection[point_index]) {
- if (mode & GEO_NODE_CURVE_HANDLE_LEFT) {
- bezier_spline.handle_types_left()[i_point] = new_handle_type;
- }
- if (mode & GEO_NODE_CURVE_HANDLE_RIGHT) {
- bezier_spline.handle_types_right()[i_point] = new_handle_type;
- }
- }
- point_index++;
- }
- bezier_spline.mark_cache_invalid();
+ has_curves = true;
+ const CurveComponent &component = *geometry_set.get_component_for_read<CurveComponent>();
+ if (!component.attribute_exists("handle_type_left") ||
+ !component.attribute_exists("handle_type_right")) {
+ return;
}
+ has_bezier = true;
- curve_component.replace(curve_eval_to_curves(*curve));
+ set_type_in_component(geometry_set.get_component_for_write<CurveComponent>(),
+ mode,
+ new_handle_type,
+ selection_field);
});
- if (!has_bezier_spline) {
- params.error_message_add(NodeWarningType::Info, TIP_("No Bezier splines in input curve"));
+
+ if (has_curves && !has_bezier) {
+ params.error_message_add(NodeWarningType::Info, TIP_("Input curves do not have Bezier type"));
}
+
params.set_output("Curve", std::move(geometry_set));
}
} // namespace blender::nodes::node_geo_curve_set_handle_type_cc
diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_spline_parameter.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_spline_parameter.cc
index 3edaccba506..62fae8b8eca 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_curve_spline_parameter.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_curve_spline_parameter.cc
@@ -2,7 +2,7 @@
#include "BLI_task.hh"
-#include "BKE_spline.hh"
+#include "BKE_curves.hh"
#include "node_geometry_util.hh"
@@ -26,168 +26,160 @@ static void node_declare(NodeDeclarationBuilder &b)
}
/**
- * A basic interpolation from the point domain to the spline domain would be useless, since the
- * average parameter for each spline would just be 0.5, or close to it. Instead, the parameter for
- * each spline is the portion of the total length at the start of the spline.
+ * For lengths on the curve domain, a basic interpolation from the point domain would be useless,
+ * since the average parameter for each curve would just be 0.5, or close to it. Instead, the
+ * value for each curve is defined as the portion of the total length of all curves at its start.
*/
-static Array<float> curve_length_spline_domain(const CurveEval &curve,
- const IndexMask UNUSED(mask))
+static Array<float> accumulated_lengths_curve_domain(const bke::CurvesGeometry &curves)
{
- Span<SplinePtr> splines = curve.splines();
+ curves.ensure_evaluated_lengths();
+
+ Array<float> lengths(curves.curves_num());
+ VArray<bool> cyclic = curves.cyclic();
float length = 0.0f;
- Array<float> lengths(splines.size());
- for (const int i : splines.index_range()) {
+ for (const int i : curves.curves_range()) {
lengths[i] = length;
- length += splines[i]->length();
- }
- return lengths;
-}
-
-/**
- * The parameter at each control point is the factor at the corresponding evaluated point.
- */
-static void calculate_bezier_lengths(const BezierSpline &spline, MutableSpan<float> lengths)
-{
- Span<int> offsets = spline.control_point_offsets();
- Span<float> lengths_eval = spline.evaluated_lengths();
- for (const int i : IndexRange(1, spline.size() - 1)) {
- lengths[i] = lengths_eval[offsets[i] - 1];
+ length += curves.evaluated_length_total_for_curve(i, cyclic[i]);
}
-}
-/**
- * The parameter for poly splines is simply the evaluated lengths divided by the total length.
- */
-static void calculate_poly_length(const PolySpline &spline, MutableSpan<float> lengths)
-{
- Span<float> lengths_eval = spline.evaluated_lengths();
- if (spline.is_cyclic()) {
- lengths.drop_front(1).copy_from(lengths_eval.drop_back(1));
- }
- else {
- lengths.drop_front(1).copy_from(lengths_eval);
- }
+ return lengths;
}
/**
- * Since NURBS control points do not necessarily coincide with the evaluated curve's path, and
- * each control point doesn't correspond well to a specific evaluated point, the parameter at
- * each point is not well defined. So instead, treat the control points as if they were a poly
- * spline.
+ * Return the length of each control point along each curve, starting at zero for the first point.
+ * Importantly, this is different than the length at each evaluated point. The implementation is
+ * different for every curve type:
+ * - Catmull Rom Curves: Use the resolution to find the evaluated point for each control point.
+ * - Poly Curves: Copy the evaluated lengths, but we need to add a zero to the front of the array.
+ * - Bezier Curves: Use the evaluated offsets to find the evaluated point for each control point.
+ * - NURBS Curves: Treat the control points as if they were a poly curve, because there
+ * is no obvious mapping from each control point to a specific evaluated point.
*/
-static void calculate_nurbs_lengths(const NURBSpline &spline, MutableSpan<float> lengths)
-{
- Span<float3> positions = spline.positions();
- Array<float> control_point_lengths(spline.size());
- float length = 0.0f;
- for (const int i : IndexRange(positions.size() - 1)) {
- lengths[i] = length;
- length += math::distance(positions[i], positions[i + 1]);
- }
- lengths.last() = length;
-}
-
-static Array<float> curve_length_point_domain(const CurveEval &curve)
+static Array<float> curve_length_point_domain(const bke::CurvesGeometry &curves)
{
- Span<SplinePtr> splines = curve.splines();
- Array<int> offsets = curve.control_point_offsets();
- const int total_size = offsets.last();
- Array<float> lengths(total_size);
-
- threading::parallel_for(splines.index_range(), 128, [&](IndexRange range) {
- for (const int i : range) {
- const Spline &spline = *splines[i];
- MutableSpan spline_factors{lengths.as_mutable_span().slice(offsets[i], spline.size())};
- spline_factors.first() = 0.0f;
- switch (splines[i]->type()) {
- case CURVE_TYPE_BEZIER: {
- calculate_bezier_lengths(static_cast<const BezierSpline &>(spline), spline_factors);
+ curves.ensure_evaluated_lengths();
+ const VArray<int8_t> types = curves.curve_types();
+ const VArray<int> resolution = curves.resolution();
+ const VArray<bool> cyclic = curves.cyclic();
+
+ Array<float> result(curves.points_num());
+ VArray<int> resolutions = curves.resolution();
+
+ threading::parallel_for(curves.curves_range(), 128, [&](IndexRange range) {
+ for (const int i_curve : range) {
+ const IndexRange points = curves.points_for_curve(i_curve);
+ const Span<float> evaluated_lengths = curves.evaluated_lengths_for_curve(i_curve,
+ cyclic[i_curve]);
+ MutableSpan<float> lengths = result.as_mutable_span().slice(points);
+ lengths.first() = 0.0f;
+ switch (types[i_curve]) {
+ case CURVE_TYPE_CATMULL_ROM: {
+ const int resolution = resolutions[i_curve];
+ for (const int i : IndexRange(points.size()).drop_front(1).drop_back(1)) {
+ lengths[i] = evaluated_lengths[resolution * i - 1];
+ }
break;
}
- case CURVE_TYPE_POLY: {
- calculate_poly_length(static_cast<const PolySpline &>(spline), spline_factors);
+ case CURVE_TYPE_POLY:
+ lengths.drop_front(1).copy_from(evaluated_lengths.take_front(lengths.size() - 1));
break;
- }
- case CURVE_TYPE_NURBS: {
- calculate_nurbs_lengths(static_cast<const NURBSpline &>(spline), spline_factors);
+ case CURVE_TYPE_BEZIER: {
+ const Span<int> offsets = curves.bezier_evaluated_offsets_for_curve(i_curve);
+ for (const int i : IndexRange(points.size()).drop_front(1).drop_back(1)) {
+ lengths[i] = evaluated_lengths[offsets[i] - 1];
+ }
break;
}
- case CURVE_TYPE_CATMULL_ROM: {
- BLI_assert_unreachable();
+ case CURVE_TYPE_NURBS: {
+ const Span<float3> positions = curves.positions().slice(points);
+ float length = 0.0f;
+ for (const int i : positions.index_range().drop_back(1)) {
+ lengths[i] = length;
+ length += math::distance(positions[i], positions[i + 1]);
+ }
+ lengths.last() = length;
break;
}
}
}
});
- return lengths;
+ return result;
}
-static VArray<float> construct_curve_parameter_varray(const CurveEval &curve,
- const IndexMask mask,
+static VArray<float> construct_curve_parameter_varray(const bke::CurvesGeometry &curves,
+ const IndexMask UNUSED(mask),
const AttributeDomain domain)
{
+ VArray<bool> cyclic = curves.cyclic();
+
if (domain == ATTR_DOMAIN_POINT) {
- Span<SplinePtr> splines = curve.splines();
- Array<float> values = curve_length_point_domain(curve);
-
- const Array<int> offsets = curve.control_point_offsets();
- for (const int i_spline : curve.splines().index_range()) {
- const Spline &spline = *splines[i_spline];
- const float spline_length = spline.length();
- const float spline_length_inv = spline_length == 0.0f ? 0.0f : 1.0f / spline_length;
- for (const int i : IndexRange(spline.size())) {
- values[offsets[i_spline] + i] *= spline_length_inv;
+ Array<float> result = curve_length_point_domain(curves);
+ MutableSpan<float> lengths = result.as_mutable_span();
+
+ threading::parallel_for(curves.curves_range(), 1024, [&](IndexRange range) {
+ for (const int i_curve : range) {
+ const float total_length = curves.evaluated_length_total_for_curve(i_curve,
+ cyclic[i_curve]);
+ const float factor = total_length == 0.0f ? 0.0f : 1.0f / total_length;
+ MutableSpan<float> curve_lengths = lengths.slice(curves.points_for_curve(i_curve));
+ for (float &value : curve_lengths) {
+ value *= factor;
+ }
}
- }
- return VArray<float>::ForContainer(std::move(values));
+ });
+ return VArray<float>::ForContainer(std::move(result));
}
if (domain == ATTR_DOMAIN_CURVE) {
- Array<float> values = curve.accumulated_spline_lengths();
- const float total_length_inv = values.last() == 0.0f ? 0.0f : 1.0f / values.last();
- for (const int i : mask) {
- values[i] *= total_length_inv;
+ Array<float> lengths = accumulated_lengths_curve_domain(curves);
+
+ const int last_index = curves.curves_num() - 1;
+ const int total_length = lengths.last() + curves.evaluated_length_total_for_curve(
+ last_index, cyclic[last_index]);
+ const float factor = total_length == 0.0f ? 0.0f : 1.0f / total_length;
+ for (float &value : lengths) {
+ value *= factor;
}
- return VArray<float>::ForContainer(std::move(values));
+ return VArray<float>::ForContainer(std::move(lengths));
}
return {};
}
-static VArray<float> construct_curve_length_varray(const CurveEval &curve,
- const IndexMask mask,
+static VArray<float> construct_curve_length_varray(const bke::CurvesGeometry &curves,
+ const IndexMask UNUSED(mask),
const AttributeDomain domain)
{
+ curves.ensure_evaluated_lengths();
+
if (domain == ATTR_DOMAIN_POINT) {
- Array<float> lengths = curve_length_point_domain(curve);
+ Array<float> lengths = curve_length_point_domain(curves);
return VArray<float>::ForContainer(std::move(lengths));
}
if (domain == ATTR_DOMAIN_CURVE) {
- if (curve.splines().size() == 1) {
- Array<float> lengths(1, 0.0f);
- return VArray<float>::ForContainer(std::move(lengths));
- }
-
- Array<float> lengths = curve_length_spline_domain(curve, mask);
+ Array<float> lengths = accumulated_lengths_curve_domain(curves);
return VArray<float>::ForContainer(std::move(lengths));
}
return {};
}
-static VArray<int> construct_index_on_spline_varray(const CurveEval &curve,
+static VArray<int> construct_index_on_spline_varray(const bke::CurvesGeometry &curves,
const IndexMask UNUSED(mask),
const AttributeDomain domain)
{
if (domain == ATTR_DOMAIN_POINT) {
- Array<int> output(curve.total_control_point_size());
- int output_index = 0;
- for (int spline_index : curve.splines().index_range()) {
- for (int point_index : IndexRange(curve.splines()[spline_index]->size())) {
- output[output_index++] = point_index;
+ Array<int> result(curves.points_num());
+ MutableSpan<int> span = result.as_mutable_span();
+ threading::parallel_for(curves.curves_range(), 1024, [&](IndexRange range) {
+ for (const int i_curve : range) {
+ MutableSpan<int> indices = span.slice(curves.points_for_curve(i_curve));
+ for (const int i : indices.index_range()) {
+ indices[i] = i;
+ }
}
- }
- return VArray<int>::ForContainer(std::move(output));
+ });
+ return VArray<int>::ForContainer(std::move(result));
}
return {};
}
@@ -206,9 +198,9 @@ class CurveParameterFieldInput final : public GeometryFieldInput {
if (component.type() == GEO_COMPONENT_TYPE_CURVE) {
const CurveComponent &curve_component = static_cast<const CurveComponent &>(component);
if (curve_component.has_curves()) {
- const std::unique_ptr<CurveEval> curve = curves_to_curve_eval(
- *curve_component.get_for_read());
- return construct_curve_parameter_varray(*curve, mask, domain);
+ const Curves &curves_id = *curve_component.get_for_read();
+ const bke::CurvesGeometry &curves = bke::CurvesGeometry::wrap(curves_id.geometry);
+ return construct_curve_parameter_varray(curves, mask, domain);
}
}
return {};
@@ -240,8 +232,9 @@ class CurveLengthFieldInput final : public GeometryFieldInput {
if (component.type() == GEO_COMPONENT_TYPE_CURVE) {
const CurveComponent &curve_component = static_cast<const CurveComponent &>(component);
if (curve_component.has_curves()) {
- std::unique_ptr<CurveEval> curve = curves_to_curve_eval(*curve_component.get_for_read());
- return construct_curve_length_varray(*curve, mask, domain);
+ const Curves &curves_id = *curve_component.get_for_read();
+ const bke::CurvesGeometry &curves = bke::CurvesGeometry::wrap(curves_id.geometry);
+ return construct_curve_length_varray(curves, mask, domain);
}
}
return {};
@@ -273,9 +266,9 @@ class IndexOnSplineFieldInput final : public GeometryFieldInput {
if (component.type() == GEO_COMPONENT_TYPE_CURVE) {
const CurveComponent &curve_component = static_cast<const CurveComponent &>(component);
if (curve_component.has_curves()) {
- const std::unique_ptr<CurveEval> curve = curves_to_curve_eval(
- *curve_component.get_for_read());
- return construct_index_on_spline_varray(*curve, mask, domain);
+ const Curves &curves_id = *curve_component.get_for_read();
+ const bke::CurvesGeometry &curves = bke::CurvesGeometry::wrap(curves_id.geometry);
+ return construct_index_on_spline_varray(curves, mask, domain);
}
}
return {};
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 cf6837817c2..c3b1a141f4a 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_delete_geometry.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_delete_geometry.cc
@@ -168,12 +168,12 @@ static void copy_attributes_based_on_map(const Map<AttributeIDRef, AttributeKind
static void copy_face_corner_attributes(const Map<AttributeIDRef, AttributeKind> &attributes,
const GeometryComponent &in_component,
GeometryComponent &out_component,
- const int num_selected_loops,
+ const int selected_loops_num,
const Span<int> selected_poly_indices,
const Mesh &mesh_in)
{
Vector<int64_t> indices;
- indices.reserve(num_selected_loops);
+ indices.reserve(selected_loops_num);
for (const int src_poly_index : selected_poly_indices) {
const MPoly &src_poly = mesh_in.mpoly[src_poly_index];
const int src_loop_start = src_poly.loopstart;
@@ -546,47 +546,47 @@ static void separate_instance_selection(GeometrySet &geometry_set,
static void compute_selected_vertices_from_vertex_selection(const Span<bool> vertex_selection,
const bool invert,
MutableSpan<int> r_vertex_map,
- int *r_num_selected_vertices)
+ int *r_selected_vertices_num)
{
BLI_assert(vertex_selection.size() == r_vertex_map.size());
- int num_selected_vertices = 0;
+ int selected_verts_num = 0;
for (const int i : r_vertex_map.index_range()) {
if (vertex_selection[i] != invert) {
- r_vertex_map[i] = num_selected_vertices;
- num_selected_vertices++;
+ r_vertex_map[i] = selected_verts_num;
+ selected_verts_num++;
}
else {
r_vertex_map[i] = -1;
}
}
- *r_num_selected_vertices = num_selected_vertices;
+ *r_selected_vertices_num = selected_verts_num;
}
static void compute_selected_edges_from_vertex_selection(const Mesh &mesh,
const Span<bool> vertex_selection,
const bool invert,
MutableSpan<int> r_edge_map,
- int *r_num_selected_edges)
+ int *r_selected_edges_num)
{
BLI_assert(mesh.totedge == r_edge_map.size());
- int num_selected_edges = 0;
+ int selected_edges_num = 0;
for (const int i : IndexRange(mesh.totedge)) {
const MEdge &edge = mesh.medge[i];
/* Only add the edge if both vertices will be in the new mesh. */
if (vertex_selection[edge.v1] != invert && vertex_selection[edge.v2] != invert) {
- r_edge_map[i] = num_selected_edges;
- num_selected_edges++;
+ r_edge_map[i] = selected_edges_num;
+ selected_edges_num++;
}
else {
r_edge_map[i] = -1;
}
}
- *r_num_selected_edges = num_selected_edges;
+ *r_selected_edges_num = selected_edges_num;
}
static void compute_selected_polygons_from_vertex_selection(const Mesh &mesh,
@@ -594,15 +594,15 @@ static void compute_selected_polygons_from_vertex_selection(const Mesh &mesh,
const bool invert,
Vector<int> &r_selected_poly_indices,
Vector<int> &r_loop_starts,
- int *r_num_selected_polys,
- int *r_num_selected_loops)
+ int *r_selected_polys_num,
+ int *r_selected_loops_num)
{
BLI_assert(mesh.totvert == vertex_selection.size());
r_selected_poly_indices.reserve(mesh.totpoly);
r_loop_starts.reserve(mesh.totloop);
- int num_selected_loops = 0;
+ int selected_loops_num = 0;
for (const int i : IndexRange(mesh.totpoly)) {
const MPoly &poly_src = mesh.mpoly[i];
@@ -617,13 +617,13 @@ static void compute_selected_polygons_from_vertex_selection(const Mesh &mesh,
if (all_verts_in_selection) {
r_selected_poly_indices.append_unchecked(i);
- r_loop_starts.append_unchecked(num_selected_loops);
- num_selected_loops += poly_src.totloop;
+ r_loop_starts.append_unchecked(selected_loops_num);
+ selected_loops_num += poly_src.totloop;
}
}
- *r_num_selected_polys = r_selected_poly_indices.size();
- *r_num_selected_loops = num_selected_loops;
+ *r_selected_polys_num = r_selected_poly_indices.size();
+ *r_selected_loops_num = selected_loops_num;
}
/**
@@ -636,25 +636,25 @@ static void compute_selected_vertices_and_edges_from_edge_selection(
const bool invert,
MutableSpan<int> r_vertex_map,
MutableSpan<int> r_edge_map,
- int *r_num_selected_vertices,
- int *r_num_selected_edges)
+ int *r_selected_vertices_num,
+ int *r_selected_edges_num)
{
BLI_assert(mesh.totedge == edge_selection.size());
- int num_selected_edges = 0;
- int num_selected_vertices = 0;
+ int selected_edges_num = 0;
+ int selected_verts_num = 0;
for (const int i : IndexRange(mesh.totedge)) {
const MEdge &edge = mesh.medge[i];
if (edge_selection[i] != invert) {
- r_edge_map[i] = num_selected_edges;
- num_selected_edges++;
+ r_edge_map[i] = selected_edges_num;
+ selected_edges_num++;
if (r_vertex_map[edge.v1] == -1) {
- r_vertex_map[edge.v1] = num_selected_vertices;
- num_selected_vertices++;
+ r_vertex_map[edge.v1] = selected_verts_num;
+ selected_verts_num++;
}
if (r_vertex_map[edge.v2] == -1) {
- r_vertex_map[edge.v2] = num_selected_vertices;
- num_selected_vertices++;
+ r_vertex_map[edge.v2] = selected_verts_num;
+ selected_verts_num++;
}
}
else {
@@ -662,8 +662,8 @@ static void compute_selected_vertices_and_edges_from_edge_selection(
}
}
- *r_num_selected_vertices = num_selected_vertices;
- *r_num_selected_edges = num_selected_edges;
+ *r_selected_vertices_num = selected_verts_num;
+ *r_selected_edges_num = selected_edges_num;
}
/**
@@ -673,22 +673,22 @@ static void compute_selected_edges_from_edge_selection(const Mesh &mesh,
const Span<bool> edge_selection,
const bool invert,
MutableSpan<int> r_edge_map,
- int *r_num_selected_edges)
+ int *r_selected_edges_num)
{
BLI_assert(mesh.totedge == edge_selection.size());
- int num_selected_edges = 0;
+ int selected_edges_num = 0;
for (const int i : IndexRange(mesh.totedge)) {
if (edge_selection[i] != invert) {
- r_edge_map[i] = num_selected_edges;
- num_selected_edges++;
+ r_edge_map[i] = selected_edges_num;
+ selected_edges_num++;
}
else {
r_edge_map[i] = -1;
}
}
- *r_num_selected_edges = num_selected_edges;
+ *r_selected_edges_num = selected_edges_num;
}
/**
@@ -700,13 +700,13 @@ static void compute_selected_polygons_from_edge_selection(const Mesh &mesh,
const bool invert,
Vector<int> &r_selected_poly_indices,
Vector<int> &r_loop_starts,
- int *r_num_selected_polys,
- int *r_num_selected_loops)
+ int *r_selected_polys_num,
+ int *r_selected_loops_num)
{
r_selected_poly_indices.reserve(mesh.totpoly);
r_loop_starts.reserve(mesh.totloop);
- int num_selected_loops = 0;
+ int selected_loops_num = 0;
for (const int i : IndexRange(mesh.totpoly)) {
const MPoly &poly_src = mesh.mpoly[i];
@@ -721,13 +721,13 @@ static void compute_selected_polygons_from_edge_selection(const Mesh &mesh,
if (all_edges_in_selection) {
r_selected_poly_indices.append_unchecked(i);
- r_loop_starts.append_unchecked(num_selected_loops);
- num_selected_loops += poly_src.totloop;
+ r_loop_starts.append_unchecked(selected_loops_num);
+ selected_loops_num += poly_src.totloop;
}
}
- *r_num_selected_polys = r_selected_poly_indices.size();
- *r_num_selected_loops = num_selected_loops;
+ *r_selected_polys_num = r_selected_poly_indices.size();
+ *r_selected_loops_num = selected_loops_num;
}
/**
@@ -740,21 +740,21 @@ static void compute_selected_mesh_data_from_vertex_selection_edge_face(
MutableSpan<int> r_edge_map,
Vector<int> &r_selected_poly_indices,
Vector<int> &r_loop_starts,
- int *r_num_selected_edges,
- int *r_num_selected_polys,
- int *r_num_selected_loops)
+ int *r_selected_edges_num,
+ int *r_selected_polys_num,
+ int *r_selected_loops_num)
{
compute_selected_edges_from_vertex_selection(
- mesh, vertex_selection, invert, r_edge_map, r_num_selected_edges);
+ mesh, vertex_selection, invert, r_edge_map, r_selected_edges_num);
compute_selected_polygons_from_vertex_selection(mesh,
vertex_selection,
invert,
r_selected_poly_indices,
r_loop_starts,
- r_num_selected_polys,
- r_num_selected_loops);
+ r_selected_polys_num,
+ r_selected_loops_num);
}
/**
@@ -768,24 +768,24 @@ static void compute_selected_mesh_data_from_vertex_selection(const Mesh &mesh,
MutableSpan<int> r_edge_map,
Vector<int> &r_selected_poly_indices,
Vector<int> &r_loop_starts,
- int *r_num_selected_vertices,
- int *r_num_selected_edges,
- int *r_num_selected_polys,
- int *r_num_selected_loops)
+ int *r_selected_vertices_num,
+ int *r_selected_edges_num,
+ int *r_selected_polys_num,
+ int *r_selected_loops_num)
{
compute_selected_vertices_from_vertex_selection(
- vertex_selection, invert, r_vertex_map, r_num_selected_vertices);
+ vertex_selection, invert, r_vertex_map, r_selected_vertices_num);
compute_selected_edges_from_vertex_selection(
- mesh, vertex_selection, invert, r_edge_map, r_num_selected_edges);
+ mesh, vertex_selection, invert, r_edge_map, r_selected_edges_num);
compute_selected_polygons_from_vertex_selection(mesh,
vertex_selection,
invert,
r_selected_poly_indices,
r_loop_starts,
- r_num_selected_polys,
- r_num_selected_loops);
+ r_selected_polys_num,
+ r_selected_loops_num);
}
/**
@@ -799,19 +799,19 @@ static void compute_selected_mesh_data_from_edge_selection_edge_face(
MutableSpan<int> r_edge_map,
Vector<int> &r_selected_poly_indices,
Vector<int> &r_loop_starts,
- int *r_num_selected_edges,
- int *r_num_selected_polys,
- int *r_num_selected_loops)
+ int *r_selected_edges_num,
+ int *r_selected_polys_num,
+ int *r_selected_loops_num)
{
compute_selected_edges_from_edge_selection(
- mesh, edge_selection, invert, r_edge_map, r_num_selected_edges);
+ mesh, edge_selection, invert, r_edge_map, r_selected_edges_num);
compute_selected_polygons_from_edge_selection(mesh,
edge_selection,
invert,
r_selected_poly_indices,
r_loop_starts,
- r_num_selected_polys,
- r_num_selected_loops);
+ r_selected_polys_num,
+ r_selected_loops_num);
}
/**
@@ -825,10 +825,10 @@ static void compute_selected_mesh_data_from_edge_selection(const Mesh &mesh,
MutableSpan<int> r_edge_map,
Vector<int> &r_selected_poly_indices,
Vector<int> &r_loop_starts,
- int *r_num_selected_vertices,
- int *r_num_selected_edges,
- int *r_num_selected_polys,
- int *r_num_selected_loops)
+ int *r_selected_vertices_num,
+ int *r_selected_edges_num,
+ int *r_selected_polys_num,
+ int *r_selected_loops_num)
{
r_vertex_map.fill(-1);
compute_selected_vertices_and_edges_from_edge_selection(mesh,
@@ -836,15 +836,15 @@ static void compute_selected_mesh_data_from_edge_selection(const Mesh &mesh,
invert,
r_vertex_map,
r_edge_map,
- r_num_selected_vertices,
- r_num_selected_edges);
+ r_selected_vertices_num,
+ r_selected_edges_num);
compute_selected_polygons_from_edge_selection(mesh,
edge_selection,
invert,
r_selected_poly_indices,
r_loop_starts,
- r_num_selected_polys,
- r_num_selected_loops);
+ r_selected_polys_num,
+ r_selected_loops_num);
}
/**
@@ -855,26 +855,26 @@ static void compute_selected_polygons_from_poly_selection(const Mesh &mesh,
const bool invert,
Vector<int> &r_selected_poly_indices,
Vector<int> &r_loop_starts,
- int *r_num_selected_polys,
- int *r_num_selected_loops)
+ int *r_selected_polys_num,
+ int *r_selected_loops_num)
{
BLI_assert(mesh.totpoly == poly_selection.size());
r_selected_poly_indices.reserve(mesh.totpoly);
r_loop_starts.reserve(mesh.totloop);
- int num_selected_loops = 0;
+ int selected_loops_num = 0;
for (const int i : IndexRange(mesh.totpoly)) {
const MPoly &poly_src = mesh.mpoly[i];
/* We keep this one. */
if (poly_selection[i] != invert) {
r_selected_poly_indices.append_unchecked(i);
- r_loop_starts.append_unchecked(num_selected_loops);
- num_selected_loops += poly_src.totloop;
+ r_loop_starts.append_unchecked(selected_loops_num);
+ selected_loops_num += poly_src.totloop;
}
}
- *r_num_selected_polys = r_selected_poly_indices.size();
- *r_num_selected_loops = num_selected_loops;
+ *r_selected_polys_num = r_selected_poly_indices.size();
+ *r_selected_loops_num = selected_loops_num;
}
/**
* Checks for every polygon if it is in `poly_selection`. If it is, the edges
@@ -887,9 +887,9 @@ static void compute_selected_mesh_data_from_poly_selection_edge_face(
MutableSpan<int> r_edge_map,
Vector<int> &r_selected_poly_indices,
Vector<int> &r_loop_starts,
- int *r_num_selected_edges,
- int *r_num_selected_polys,
- int *r_num_selected_loops)
+ int *r_selected_edges_num,
+ int *r_selected_polys_num,
+ int *r_selected_loops_num)
{
BLI_assert(mesh.totpoly == poly_selection.size());
BLI_assert(mesh.totedge == r_edge_map.size());
@@ -898,30 +898,30 @@ static void compute_selected_mesh_data_from_poly_selection_edge_face(
r_selected_poly_indices.reserve(mesh.totpoly);
r_loop_starts.reserve(mesh.totloop);
- int num_selected_loops = 0;
- int num_selected_edges = 0;
+ int selected_loops_num = 0;
+ int selected_edges_num = 0;
for (const int i : IndexRange(mesh.totpoly)) {
const MPoly &poly_src = mesh.mpoly[i];
/* We keep this one. */
if (poly_selection[i] != invert) {
r_selected_poly_indices.append_unchecked(i);
- r_loop_starts.append_unchecked(num_selected_loops);
- num_selected_loops += poly_src.totloop;
+ r_loop_starts.append_unchecked(selected_loops_num);
+ selected_loops_num += poly_src.totloop;
/* Add the vertices and the edges. */
Span<MLoop> loops_src(&mesh.mloop[poly_src.loopstart], poly_src.totloop);
for (const MLoop &loop : loops_src) {
/* Check first if it has not yet been added. */
if (r_edge_map[loop.e] == -1) {
- r_edge_map[loop.e] = num_selected_edges;
- num_selected_edges++;
+ r_edge_map[loop.e] = selected_edges_num;
+ selected_edges_num++;
}
}
}
}
- *r_num_selected_edges = num_selected_edges;
- *r_num_selected_polys = r_selected_poly_indices.size();
- *r_num_selected_loops = num_selected_loops;
+ *r_selected_edges_num = selected_edges_num;
+ *r_selected_polys_num = r_selected_poly_indices.size();
+ *r_selected_loops_num = selected_loops_num;
}
/**
@@ -935,10 +935,10 @@ static void compute_selected_mesh_data_from_poly_selection(const Mesh &mesh,
MutableSpan<int> r_edge_map,
Vector<int> &r_selected_poly_indices,
Vector<int> &r_loop_starts,
- int *r_num_selected_vertices,
- int *r_num_selected_edges,
- int *r_num_selected_polys,
- int *r_num_selected_loops)
+ int *r_selected_vertices_num,
+ int *r_selected_edges_num,
+ int *r_selected_polys_num,
+ int *r_selected_loops_num)
{
BLI_assert(mesh.totpoly == poly_selection.size());
BLI_assert(mesh.totedge == r_edge_map.size());
@@ -948,36 +948,36 @@ static void compute_selected_mesh_data_from_poly_selection(const Mesh &mesh,
r_selected_poly_indices.reserve(mesh.totpoly);
r_loop_starts.reserve(mesh.totloop);
- int num_selected_loops = 0;
- int num_selected_vertices = 0;
- int num_selected_edges = 0;
+ int selected_loops_num = 0;
+ int selected_verts_num = 0;
+ int selected_edges_num = 0;
for (const int i : IndexRange(mesh.totpoly)) {
const MPoly &poly_src = mesh.mpoly[i];
/* We keep this one. */
if (poly_selection[i] != invert) {
r_selected_poly_indices.append_unchecked(i);
- r_loop_starts.append_unchecked(num_selected_loops);
- num_selected_loops += poly_src.totloop;
+ r_loop_starts.append_unchecked(selected_loops_num);
+ selected_loops_num += poly_src.totloop;
/* Add the vertices and the edges. */
Span<MLoop> loops_src(&mesh.mloop[poly_src.loopstart], poly_src.totloop);
for (const MLoop &loop : loops_src) {
/* Check first if it has not yet been added. */
if (r_vertex_map[loop.v] == -1) {
- r_vertex_map[loop.v] = num_selected_vertices;
- num_selected_vertices++;
+ r_vertex_map[loop.v] = selected_verts_num;
+ selected_verts_num++;
}
if (r_edge_map[loop.e] == -1) {
- r_edge_map[loop.e] = num_selected_edges;
- num_selected_edges++;
+ r_edge_map[loop.e] = selected_edges_num;
+ selected_edges_num++;
}
}
}
}
- *r_num_selected_vertices = num_selected_vertices;
- *r_num_selected_edges = num_selected_edges;
- *r_num_selected_polys = r_selected_poly_indices.size();
- *r_num_selected_loops = num_selected_loops;
+ *r_selected_vertices_num = selected_verts_num;
+ *r_selected_edges_num = selected_edges_num;
+ *r_selected_polys_num = r_selected_poly_indices.size();
+ *r_selected_loops_num = selected_loops_num;
}
/**
@@ -993,8 +993,8 @@ static void do_mesh_separation(GeometrySet &geometry_set,
/* Needed in all cases. */
Vector<int> selected_poly_indices;
Vector<int> new_loop_starts;
- int num_selected_polys = 0;
- int num_selected_loops = 0;
+ int selected_polys_num = 0;
+ int selected_loops_num = 0;
const Mesh &mesh_in = *in_component.get_for_read();
Mesh *mesh_out;
@@ -1007,10 +1007,10 @@ static void do_mesh_separation(GeometrySet &geometry_set,
switch (mode) {
case GEO_NODE_DELETE_GEOMETRY_MODE_ALL: {
Array<int> vertex_map(mesh_in.totvert);
- int num_selected_vertices = 0;
+ int selected_verts_num = 0;
Array<int> edge_map(mesh_in.totedge);
- int num_selected_edges = 0;
+ int selected_edges_num = 0;
/* Fill all the maps based on the selection. */
switch (domain) {
@@ -1022,10 +1022,10 @@ static void do_mesh_separation(GeometrySet &geometry_set,
edge_map,
selected_poly_indices,
new_loop_starts,
- &num_selected_vertices,
- &num_selected_edges,
- &num_selected_polys,
- &num_selected_loops);
+ &selected_verts_num,
+ &selected_edges_num,
+ &selected_polys_num,
+ &selected_loops_num);
break;
case ATTR_DOMAIN_EDGE:
compute_selected_mesh_data_from_edge_selection(mesh_in,
@@ -1035,10 +1035,10 @@ static void do_mesh_separation(GeometrySet &geometry_set,
edge_map,
selected_poly_indices,
new_loop_starts,
- &num_selected_vertices,
- &num_selected_edges,
- &num_selected_polys,
- &num_selected_loops);
+ &selected_verts_num,
+ &selected_edges_num,
+ &selected_polys_num,
+ &selected_loops_num);
break;
case ATTR_DOMAIN_FACE:
compute_selected_mesh_data_from_poly_selection(mesh_in,
@@ -1048,21 +1048,21 @@ static void do_mesh_separation(GeometrySet &geometry_set,
edge_map,
selected_poly_indices,
new_loop_starts,
- &num_selected_vertices,
- &num_selected_edges,
- &num_selected_polys,
- &num_selected_loops);
+ &selected_verts_num,
+ &selected_edges_num,
+ &selected_polys_num,
+ &selected_loops_num);
break;
default:
BLI_assert_unreachable();
break;
}
mesh_out = BKE_mesh_new_nomain_from_template(&mesh_in,
- num_selected_vertices,
- num_selected_edges,
+ selected_verts_num,
+ selected_edges_num,
0,
- num_selected_loops,
- num_selected_polys);
+ selected_loops_num,
+ selected_polys_num);
out_component.replace(mesh_out, GeometryOwnershipType::Editable);
/* Copy the selected parts of the mesh over to the new mesh. */
@@ -1084,14 +1084,14 @@ static void do_mesh_separation(GeometrySet &geometry_set,
copy_face_corner_attributes(attributes,
in_component,
out_component,
- num_selected_loops,
+ selected_loops_num,
selected_poly_indices,
mesh_in);
break;
}
case GEO_NODE_DELETE_GEOMETRY_MODE_EDGE_FACE: {
Array<int> edge_map(mesh_in.totedge);
- int num_selected_edges = 0;
+ int selected_edges_num = 0;
/* Fill all the maps based on the selection. */
switch (domain) {
@@ -1102,9 +1102,9 @@ static void do_mesh_separation(GeometrySet &geometry_set,
edge_map,
selected_poly_indices,
new_loop_starts,
- &num_selected_edges,
- &num_selected_polys,
- &num_selected_loops);
+ &selected_edges_num,
+ &selected_polys_num,
+ &selected_loops_num);
break;
case ATTR_DOMAIN_EDGE:
compute_selected_mesh_data_from_edge_selection_edge_face(mesh_in,
@@ -1113,9 +1113,9 @@ static void do_mesh_separation(GeometrySet &geometry_set,
edge_map,
selected_poly_indices,
new_loop_starts,
- &num_selected_edges,
- &num_selected_polys,
- &num_selected_loops);
+ &selected_edges_num,
+ &selected_polys_num,
+ &selected_loops_num);
break;
case ATTR_DOMAIN_FACE:
compute_selected_mesh_data_from_poly_selection_edge_face(mesh_in,
@@ -1124,9 +1124,9 @@ static void do_mesh_separation(GeometrySet &geometry_set,
edge_map,
selected_poly_indices,
new_loop_starts,
- &num_selected_edges,
- &num_selected_polys,
- &num_selected_loops);
+ &selected_edges_num,
+ &selected_polys_num,
+ &selected_loops_num);
break;
default:
BLI_assert_unreachable();
@@ -1134,10 +1134,10 @@ static void do_mesh_separation(GeometrySet &geometry_set,
}
mesh_out = BKE_mesh_new_nomain_from_template(&mesh_in,
mesh_in.totvert,
- num_selected_edges,
+ selected_edges_num,
0,
- num_selected_loops,
- num_selected_polys);
+ selected_loops_num,
+ selected_polys_num);
out_component.replace(mesh_out, GeometryOwnershipType::Editable);
/* Copy the selected parts of the mesh over to the new mesh. */
@@ -1158,7 +1158,7 @@ static void do_mesh_separation(GeometrySet &geometry_set,
copy_face_corner_attributes(attributes,
in_component,
out_component,
- num_selected_loops,
+ selected_loops_num,
selected_poly_indices,
mesh_in);
break;
@@ -1172,8 +1172,8 @@ static void do_mesh_separation(GeometrySet &geometry_set,
invert,
selected_poly_indices,
new_loop_starts,
- &num_selected_polys,
- &num_selected_loops);
+ &selected_polys_num,
+ &selected_loops_num);
break;
case ATTR_DOMAIN_EDGE:
compute_selected_polygons_from_edge_selection(mesh_in,
@@ -1181,8 +1181,8 @@ static void do_mesh_separation(GeometrySet &geometry_set,
invert,
selected_poly_indices,
new_loop_starts,
- &num_selected_polys,
- &num_selected_loops);
+ &selected_polys_num,
+ &selected_loops_num);
break;
case ATTR_DOMAIN_FACE:
compute_selected_polygons_from_poly_selection(mesh_in,
@@ -1190,15 +1190,15 @@ static void do_mesh_separation(GeometrySet &geometry_set,
invert,
selected_poly_indices,
new_loop_starts,
- &num_selected_polys,
- &num_selected_loops);
+ &selected_polys_num,
+ &selected_loops_num);
break;
default:
BLI_assert_unreachable();
break;
}
mesh_out = BKE_mesh_new_nomain_from_template(
- &mesh_in, mesh_in.totvert, mesh_in.totedge, 0, num_selected_loops, num_selected_polys);
+ &mesh_in, mesh_in.totvert, mesh_in.totedge, 0, selected_loops_num, selected_polys_num);
out_component.replace(mesh_out, GeometryOwnershipType::Editable);
/* Copy the selected parts of the mesh over to the new mesh. */
@@ -1217,7 +1217,7 @@ static void do_mesh_separation(GeometrySet &geometry_set,
copy_face_corner_attributes(attributes,
in_component,
out_component,
- num_selected_loops,
+ selected_loops_num,
selected_poly_indices,
mesh_in);
break;
diff --git a/source/blender/nodes/geometry/nodes/node_geo_extrude_mesh.cc b/source/blender/nodes/geometry/nodes/node_geo_extrude_mesh.cc
index 82584f6f413..0072fbcde93 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_extrude_mesh.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_extrude_mesh.cc
@@ -25,7 +25,7 @@ static void node_declare(NodeDeclarationBuilder &b)
b.add_input<decl::Geometry>("Mesh").supported_type(GEO_COMPONENT_TYPE_MESH);
b.add_input<decl::Bool>(N_("Selection")).default_value(true).supports_field().hide_value();
b.add_input<decl::Vector>(N_("Offset")).subtype(PROP_TRANSLATION).implicit_field().hide_value();
- b.add_input<decl::Float>(N_("Offset Scale")).default_value(1.0f).min(0.0f).supports_field();
+ b.add_input<decl::Float>(N_("Offset Scale")).default_value(1.0f).supports_field();
b.add_input<decl::Bool>(N_("Individual")).default_value(true);
b.add_output<decl::Geometry>("Mesh");
b.add_output<decl::Bool>(N_("Top")).field_source();
@@ -523,7 +523,7 @@ static void extrude_mesh_edges(MeshComponent &component,
}
case ATTR_DOMAIN_FACE: {
/* Attribute values for new faces are a mix of the values of faces connected to the its
- * original edge. */
+ * original edge. */
copy_with_mixing(data.slice(new_poly_range), data.as_span(), [&](const int i) {
return edge_to_poly_map[edge_selection[i]].as_span();
});
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 ab6f6b40d5e..6c24f86b63b 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
@@ -3,15 +3,8 @@
#include "node_geometry_util.hh"
#include "BKE_curves.hh"
-#include "BKE_spline.hh"
-namespace blender::nodes::node_geo_input_spline_length_cc {
-
-static void node_declare(NodeDeclarationBuilder &b)
-{
- b.add_output<decl::Float>(N_("Length")).field_source();
- b.add_output<decl::Int>(N_("Point Count")).field_source();
-}
+namespace blender::nodes {
/* --------------------------------------------------------------------
* Spline Length
@@ -23,55 +16,66 @@ static VArray<float> construct_spline_length_gvarray(const CurveComponent &compo
if (!component.has_curves()) {
return {};
}
- const std::unique_ptr<CurveEval> curve = curves_to_curve_eval(*component.get_for_read());
+ const Curves &curves_id = *component.get_for_read();
+ const bke::CurvesGeometry &curves = bke::CurvesGeometry::wrap(curves_id.geometry);
- Span<SplinePtr> splines = curve->splines();
- Array<float> spline_lenghts(splines.size());
- for (const int i : splines.index_range()) {
- spline_lenghts[i] = splines[i]->length();
- }
+ curves.ensure_evaluated_lengths();
+
+ VArray<bool> cyclic = curves.cyclic();
+ VArray<float> lengths = VArray<float>::ForFunc(
+ curves.curves_num(), [&curves, cyclic = std::move(cyclic)](int64_t index) {
+ return curves.evaluated_length_total_for_curve(index, cyclic[index]);
+ });
if (domain == ATTR_DOMAIN_CURVE) {
- return VArray<float>::ForContainer(std::move(spline_lenghts));
+ return lengths;
}
+
if (domain == ATTR_DOMAIN_POINT) {
- 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);
+ std::move(lengths), ATTR_DOMAIN_CURVE, ATTR_DOMAIN_POINT);
}
return {};
}
-class SplineLengthFieldInput final : public GeometryFieldInput {
- public:
- SplineLengthFieldInput() : GeometryFieldInput(CPPType::get<float>(), "Spline Length node")
- {
- category_ = Category::Generated;
- }
+SplineLengthFieldInput::SplineLengthFieldInput()
+ : GeometryFieldInput(CPPType::get<float>(), "Spline Length node")
+{
+ category_ = Category::Generated;
+}
- GVArray get_varray_for_context(const GeometryComponent &component,
- const AttributeDomain domain,
- IndexMask UNUSED(mask)) const final
- {
- if (component.type() == GEO_COMPONENT_TYPE_CURVE) {
- const CurveComponent &curve_component = static_cast<const CurveComponent &>(component);
- return construct_spline_length_gvarray(curve_component, domain);
- }
- return {};
+GVArray SplineLengthFieldInput::get_varray_for_context(const GeometryComponent &component,
+ const AttributeDomain domain,
+ IndexMask UNUSED(mask)) const
+{
+ if (component.type() == GEO_COMPONENT_TYPE_CURVE) {
+ const CurveComponent &curve_component = static_cast<const CurveComponent &>(component);
+ return construct_spline_length_gvarray(curve_component, domain);
}
+ return {};
+}
- uint64_t hash() const override
- {
- /* Some random constant hash. */
- return 3549623580;
- }
+uint64_t SplineLengthFieldInput::hash() const
+{
+ /* Some random constant hash. */
+ return 3549623580;
+}
- bool is_equal_to(const fn::FieldNode &other) const override
- {
- return dynamic_cast<const SplineLengthFieldInput *>(&other) != nullptr;
- }
-};
+bool SplineLengthFieldInput::is_equal_to(const fn::FieldNode &other) const
+{
+ return dynamic_cast<const SplineLengthFieldInput *>(&other) != nullptr;
+}
+
+} // namespace blender::nodes
+
+namespace blender::nodes::node_geo_input_spline_length_cc {
+
+static void node_declare(NodeDeclarationBuilder &b)
+{
+ b.add_output<decl::Float>(N_("Length")).field_source();
+ b.add_output<decl::Int>(N_("Point Count")).field_source();
+}
/* --------------------------------------------------------------------
* Spline Count
diff --git a/source/blender/nodes/geometry/nodes/node_geo_raycast.cc b/source/blender/nodes/geometry/nodes/node_geo_raycast.cc
index 231ef547a8b..368954447c9 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_raycast.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_raycast.cc
@@ -298,7 +298,7 @@ class RaycastFunction : public fn::MultiFunction {
GMutableSpan result = params.uninitialized_single_output_if_required(7, "Attribute");
if (!result.is_empty()) {
MeshAttributeInterpolator interp(&mesh, hit_mask, hit_positions, hit_indices);
- result.type().fill_assign_indices(result.type().default_value(), result.data(), mask);
+ result.type().value_initialize_indices(result.data(), mask);
interp.sample_data(*target_data_, domain_, get_map_mode(mapping_), result);
}
}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_set_curve_handles.cc b/source/blender/nodes/geometry/nodes/node_geo_set_curve_handles.cc
index 271dd824d27..31b9f1765a5 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_set_curve_handles.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_set_curve_handles.cc
@@ -1,6 +1,8 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
-#include "BKE_spline.hh"
+#include <atomic>
+
+#include "BKE_curves.hh"
#include "UI_interface.h"
#include "UI_resources.h"
@@ -34,8 +36,40 @@ static void node_init(bNodeTree *UNUSED(tree), bNode *node)
node->storage = data;
}
-static void set_position_in_component(const GeometryNodeCurveHandleMode mode,
- CurveComponent &component,
+static void update_handle_types_for_movement(int8_t &type, int8_t &other)
+{
+ switch (type) {
+ case BEZIER_HANDLE_FREE:
+ break;
+ case BEZIER_HANDLE_AUTO:
+ /* Converting auto handles to aligned handled instead of free handles is
+ * arbitrary, but expected and "standard" based on behavior in edit mode. */
+ if (other == BEZIER_HANDLE_AUTO) {
+ /* Convert pairs of auto handles to aligned handles when moving one side. */
+ type = BEZIER_HANDLE_ALIGN;
+ other = BEZIER_HANDLE_ALIGN;
+ }
+ else {
+ /* If the other handle isn't automatic, just make the handle free. */
+ type = BEZIER_HANDLE_FREE;
+ }
+ break;
+ case BEZIER_HANDLE_VECTOR:
+ type = BEZIER_HANDLE_FREE;
+ break;
+ case BEZIER_HANDLE_ALIGN:
+ /* The handle can stay aligned if the other handle is also aligned (in which case the other
+ * handle should be updated to be consistent). But otherwise the handle must be made free to
+ * avoid conflicting with its "aligned" type. */
+ if (other != BEZIER_HANDLE_ALIGN) {
+ type = BEZIER_HANDLE_FREE;
+ }
+ break;
+ }
+}
+
+static void set_position_in_component(CurveComponent &component,
+ const GeometryNodeCurveHandleMode mode,
const Field<bool> &selection_field,
const Field<float3> &position_field,
const Field<float3> &offset_field)
@@ -52,83 +86,44 @@ static void set_position_in_component(const GeometryNodeCurveHandleMode mode,
evaluator.add(offset_field);
evaluator.evaluate();
const IndexMask selection = evaluator.get_evaluated_selection_as_mask();
-
- std::unique_ptr<CurveEval> curve = curves_to_curve_eval(*component.get_for_read());
-
- int current_point = 0;
- int current_mask = 0;
- for (const SplinePtr &spline : curve->splines()) {
- if (spline->type() == CURVE_TYPE_BEZIER) {
- BezierSpline &bezier = static_cast<BezierSpline &>(*spline);
-
- bezier.ensure_auto_handles();
- for (const int i : bezier.positions().index_range()) {
- if (current_mask < selection.size() && selection[current_mask] == current_point) {
- if (mode & GEO_NODE_CURVE_HANDLE_LEFT) {
- if (bezier.handle_types_left()[i] == BEZIER_HANDLE_VECTOR) {
- bezier.handle_types_left()[i] = BEZIER_HANDLE_FREE;
- }
- else if (bezier.handle_types_left()[i] == BEZIER_HANDLE_AUTO) {
- bezier.handle_types_left()[i] = BEZIER_HANDLE_ALIGN;
- }
- }
- else {
- if (bezier.handle_types_right()[i] == BEZIER_HANDLE_VECTOR) {
- bezier.handle_types_right()[i] = BEZIER_HANDLE_FREE;
- }
- else if (bezier.handle_types_right()[i] == BEZIER_HANDLE_AUTO) {
- bezier.handle_types_right()[i] = BEZIER_HANDLE_ALIGN;
- }
- }
- current_mask++;
- }
- current_point++;
- }
+ const VArray<float3> &new_positions = evaluator.get_evaluated<float3>(0);
+ const VArray<float3> &new_offsets = evaluator.get_evaluated<float3>(1);
+
+ Curves &curves_id = *component.get_for_write();
+ bke::CurvesGeometry &curves = bke::CurvesGeometry::wrap(curves_id.geometry);
+
+ Span<float3> positions = curves.positions();
+
+ const bool use_left = mode == GEO_NODE_CURVE_HANDLE_LEFT;
+ MutableSpan<int8_t> handle_types = use_left ? curves.handle_types_left() :
+ curves.handle_types_right();
+ MutableSpan<int8_t> handle_types_other = use_left ? curves.handle_types_right() :
+ curves.handle_types_left();
+ MutableSpan<float3> handle_positions = use_left ? curves.handle_positions_left() :
+ curves.handle_positions_right();
+ MutableSpan<float3> handle_positions_other = use_left ? curves.handle_positions_right() :
+ curves.handle_positions_left();
+
+ threading::parallel_for(selection.index_range(), 2048, [&](IndexRange range) {
+ for (const int i : selection.slice(range)) {
+ update_handle_types_for_movement(handle_types[i], handle_types_other[i]);
}
- else {
- for ([[maybe_unused]] int i : spline->positions().index_range()) {
- if (current_mask < selection.size() && selection[current_mask] == current_point) {
- current_mask++;
- }
- current_point++;
- }
- }
- }
+ });
- const VArray<float3> &positions_input = evaluator.get_evaluated<float3>(0);
- const VArray<float3> &offsets_input = evaluator.get_evaluated<float3>(1);
-
- current_point = 0;
- current_mask = 0;
- for (const SplinePtr &spline : curve->splines()) {
- if (spline->type() == CURVE_TYPE_BEZIER) {
- BezierSpline &bezier = static_cast<BezierSpline &>(*spline);
- for (const int i : bezier.positions().index_range()) {
- if (current_mask < selection.size() && selection[current_mask] == current_point) {
- if (mode & GEO_NODE_CURVE_HANDLE_LEFT) {
- bezier.set_handle_position_left(
- i, positions_input[current_point] + offsets_input[current_point]);
- }
- else {
- bezier.set_handle_position_right(
- i, positions_input[current_point] + offsets_input[current_point]);
- }
- current_mask++;
- }
- current_point++;
- }
- }
- else {
- for ([[maybe_unused]] int i : spline->positions().index_range()) {
- if (current_mask < selection.size() && selection[current_mask] == current_point) {
- current_mask++;
- }
- current_point++;
- }
+ threading::parallel_for(selection.index_range(), 2048, [&](IndexRange range) {
+ for (const int i : selection.slice(range)) {
+ bke::curves::bezier::set_handle_position(positions[i],
+ HandleType(handle_types[i]),
+ HandleType(handle_types_other[i]),
+ new_positions[i] + new_offsets[i],
+ handle_positions[i],
+ handle_positions_other[i]);
}
- }
+ });
- component.replace(curve_eval_to_curves(*curve), GeometryOwnershipType::Owned);
+ curves.calculate_bezier_auto_handles();
+
+ curves.tag_positions_changed();
}
static void node_geo_exec(GeoNodeExecParams params)
@@ -141,24 +136,32 @@ static void node_geo_exec(GeoNodeExecParams params)
Field<float3> position_field = params.extract_input<Field<float3>>("Position");
Field<float3> offset_field = params.extract_input<Field<float3>>("Offset");
- bool has_bezier = false;
+ std::atomic<bool> has_curves = false;
+ std::atomic<bool> has_bezier = false;
+
geometry_set.modify_geometry_sets([&](GeometrySet &geometry_set) {
- if (geometry_set.has_curves()) {
- const std::unique_ptr<CurveEval> curve = curves_to_curve_eval(
- *geometry_set.get_curves_for_read());
- has_bezier = curve->has_spline_with_type(CURVE_TYPE_BEZIER);
-
- set_position_in_component(mode,
- geometry_set.get_component_for_write<CurveComponent>(),
- selection_field,
- position_field,
- offset_field);
+ if (!geometry_set.has_curves()) {
+ return;
+ }
+ has_curves = true;
+ const CurveComponent &component = *geometry_set.get_component_for_read<CurveComponent>();
+ if (!component.attribute_exists("handle_left") ||
+ !component.attribute_exists("handle_right")) {
+ return;
}
+ has_bezier = true;
+
+ set_position_in_component(geometry_set.get_component_for_write<CurveComponent>(),
+ mode,
+ selection_field,
+ position_field,
+ offset_field);
});
- if (!has_bezier) {
- params.error_message_add(NodeWarningType::Info,
- TIP_("The input geometry does not contain a Bezier spline"));
+
+ if (has_curves && !has_bezier) {
+ params.error_message_add(NodeWarningType::Info, TIP_("Input curves do not have Bezier type"));
}
+
params.set_output("Curve", std::move(geometry_set));
}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_set_position.cc b/source/blender/nodes/geometry/nodes/node_geo_set_position.cc
index eb035aa9b6b..d2ff9753897 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_set_position.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_set_position.cc
@@ -7,6 +7,8 @@
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
+#include "BKE_curves.hh"
+
#include "node_geometry_util.hh"
namespace blender::nodes::node_geo_set_position_cc {
@@ -62,6 +64,9 @@ static void set_computed_position_and_offset(GeometryComponent &component,
break;
}
case GEO_COMPONENT_TYPE_CURVE: {
+ CurveComponent &curve_component = static_cast<CurveComponent &>(component);
+ Curves &curves_id = *curve_component.get_for_write();
+ bke::CurvesGeometry &curves = bke::CurvesGeometry::wrap(curves_id.geometry);
if (component.attribute_exists("handle_right") &&
component.attribute_exists("handle_left")) {
OutputAttribute_Typed<float3> handle_right_attribute =
@@ -90,6 +95,9 @@ static void set_computed_position_and_offset(GeometryComponent &component,
handle_right_attribute.save();
handle_left_attribute.save();
+
+ /* Automatic Bezier handles must be recalculated based on the new positions. */
+ curves.calculate_bezier_auto_handles();
break;
}
else {
diff --git a/source/blender/nodes/geometry/nodes/node_geo_transfer_attribute.cc b/source/blender/nodes/geometry/nodes/node_geo_transfer_attribute.cc
index 7f0ba950490..12e306ba480 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_transfer_attribute.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_transfer_attribute.cc
@@ -493,7 +493,7 @@ class NearestTransferFunction : public fn::MultiFunction {
GMutableSpan dst = params.uninitialized_single_output_if_required(1, "Attribute");
if (!use_mesh_ && !use_points_) {
- dst.type().fill_construct_indices(dst.type().default_value(), dst.data(), mask);
+ dst.type().value_initialize_indices(dst.data(), mask);
return;
}
@@ -673,7 +673,7 @@ class IndexTransferFunction : public fn::MultiFunction {
const CPPType &type = dst.type();
if (src_data_ == nullptr) {
- type.fill_construct_indices(type.default_value(), dst.data(), mask);
+ type.value_initialize_indices(dst.data(), mask);
return;
}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_transform.cc b/source/blender/nodes/geometry/nodes/node_geo_transform.cc
index a04544e2814..cc115ee3b3f 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_transform.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_transform.cc
@@ -103,8 +103,8 @@ static void transform_volume(Volume &volume, const float4x4 &transform, const De
memcpy(vdb_matrix.asPointer(), &scale_limited_transform, sizeof(float[4][4]));
openvdb::Mat4d vdb_matrix_d{vdb_matrix};
- const int num_grids = BKE_volume_num_grids(&volume);
- for (const int i : IndexRange(num_grids)) {
+ const int grids_num = BKE_volume_num_grids(&volume);
+ for (const int i : IndexRange(grids_num)) {
VolumeGrid *volume_grid = BKE_volume_grid_get_for_write(&volume, i);
openvdb::GridBase::Ptr grid = BKE_volume_grid_openvdb_for_write(&volume, volume_grid, false);
diff --git a/source/blender/nodes/intern/geometry_nodes_eval_log.cc b/source/blender/nodes/intern/geometry_nodes_eval_log.cc
index 5c8f4c52f75..13f38c3352e 100644
--- a/source/blender/nodes/intern/geometry_nodes_eval_log.cc
+++ b/source/blender/nodes/intern/geometry_nodes_eval_log.cc
@@ -337,6 +337,16 @@ const NodeLog *ModifierLog::find_node_by_node_editor_context(const SpaceNode &sn
return tree_log->lookup_node_log(node);
}
+const NodeLog *ModifierLog::find_node_by_node_editor_context(const SpaceNode &snode,
+ const StringRef node_name)
+{
+ const TreeLog *tree_log = ModifierLog::find_tree_by_node_editor_context(snode);
+ if (tree_log == nullptr) {
+ return nullptr;
+ }
+ return tree_log->lookup_node_log(node_name);
+}
+
const SocketLog *ModifierLog::find_socket_by_node_editor_context(const SpaceNode &snode,
const bNode &node,
const bNodeSocket &socket)
diff --git a/source/blender/python/bmesh/bmesh_py_ops_call.c b/source/blender/python/bmesh/bmesh_py_ops_call.c
index 6492f528a5e..35d5cb6a994 100644
--- a/source/blender/python/bmesh/bmesh_py_ops_call.c
+++ b/source/blender/python/bmesh/bmesh_py_ops_call.c
@@ -233,8 +233,8 @@ static int bpy_slot_from_py(BMesh *bm,
if (!Matrix_ParseAny(value, &pymat)) {
return -1;
}
- const ushort size = pymat->num_col;
- if ((size != pymat->num_row) || (!ELEM(size, 3, 4))) {
+ const ushort size = pymat->col_num;
+ if ((size != pymat->row_num) || (!ELEM(size, 3, 4))) {
PyErr_Format(PyExc_TypeError,
"%.200s: keyword \"%.200s\" expected a 3x3 or 4x4 matrix",
opname,
diff --git a/source/blender/python/bmesh/bmesh_py_types.c b/source/blender/python/bmesh/bmesh_py_types.c
index 9ceff9b84b6..46f89dd4103 100644
--- a/source/blender/python/bmesh/bmesh_py_types.c
+++ b/source/blender/python/bmesh/bmesh_py_types.c
@@ -1309,7 +1309,7 @@ static PyObject *bpy_bmesh_transform(BPy_BMElem *self, PyObject *args, PyObject
if (BaseMath_ReadCallback(mat) == -1) {
return NULL;
}
- if (mat->num_col != 4 || mat->num_row != 4) {
+ if (mat->col_num != 4 || mat->row_num != 4) {
PyErr_SetString(PyExc_ValueError, "expected a 4x4 matrix");
return NULL;
}
diff --git a/source/blender/python/gpu/gpu_py_shader.c b/source/blender/python/gpu/gpu_py_shader.c
index 1a53ccd6686..43b26e05327 100644
--- a/source/blender/python/gpu/gpu_py_shader.c
+++ b/source/blender/python/gpu/gpu_py_shader.c
@@ -381,11 +381,11 @@ static PyObject *pygpu_shader_uniform_float(BPyGPUShader *self, PyObject *args)
if (BaseMath_ReadCallback(mat) == -1) {
return NULL;
}
- if ((mat->num_row != mat->num_col) || !ELEM(mat->num_row, 3, 4)) {
+ if ((mat->row_num != mat->col_num) || !ELEM(mat->row_num, 3, 4)) {
PyErr_SetString(PyExc_ValueError, "Expected 3x3 or 4x4 matrix");
return NULL;
}
- length = mat->num_row * mat->num_col;
+ length = mat->row_num * mat->col_num;
memcpy(values, mat->matrix, sizeof(float) * length);
}
else {
diff --git a/source/blender/python/intern/bpy_app_handlers.c b/source/blender/python/intern/bpy_app_handlers.c
index ba3e6a3d74b..34ffef03e66 100644
--- a/source/blender/python/intern/bpy_app_handlers.c
+++ b/source/blender/python/intern/bpy_app_handlers.c
@@ -24,7 +24,7 @@
void bpy_app_generic_callback(struct Main *main,
struct PointerRNA **pointers,
- const int num_pointers,
+ const int pointers_num,
void *arg);
static PyTypeObject BlenderAppCbType;
@@ -305,7 +305,7 @@ static PyObject *choose_arguments(PyObject *func, PyObject *args_all, PyObject *
/* the actual callback - not necessarily called from py */
void bpy_app_generic_callback(struct Main *UNUSED(main),
struct PointerRNA **pointers,
- const int num_pointers,
+ const int pointers_num,
void *arg)
{
PyObject *cb_list = py_cb_array[POINTER_AS_INT(arg)];
@@ -320,14 +320,14 @@ void bpy_app_generic_callback(struct Main *UNUSED(main),
Py_ssize_t pos;
/* setup arguments */
- for (int i = 0; i < num_pointers; ++i) {
+ for (int i = 0; i < pointers_num; ++i) {
PyTuple_SET_ITEM(args_all, i, pyrna_struct_CreatePyObject(pointers[i]));
}
- for (int i = num_pointers; i < num_arguments; ++i) {
+ for (int i = pointers_num; i < num_arguments; ++i) {
PyTuple_SET_ITEM(args_all, i, Py_INCREF_RET(Py_None));
}
- if (num_pointers == 0) {
+ if (pointers_num == 0) {
PyTuple_SET_ITEM(args_single, 0, Py_INCREF_RET(Py_None));
}
else {
diff --git a/source/blender/python/intern/bpy_interface_run.c b/source/blender/python/intern/bpy_interface_run.c
index 8db122470b8..9299bd196e2 100644
--- a/source/blender/python/intern/bpy_interface_run.c
+++ b/source/blender/python/intern/bpy_interface_run.c
@@ -35,22 +35,33 @@
/** \name Private Utilities
* \{ */
-static void python_script_error_jump_text(Text *text)
+static void python_script_error_jump_text(Text *text, const char *filepath)
{
- int lineno;
- int offset;
- python_script_error_jump(text->id.name + 2, &lineno, &offset);
- if (lineno != -1) {
- /* select the line with the error */
- txt_move_to(text, lineno - 1, INT_MAX, false);
+ int lineno, lineno_end;
+ int offset, offset_end;
+ if (python_script_error_jump(filepath, &lineno, &offset, &lineno_end, &offset_end)) {
+ /* Start at the end so cursor motion that looses the selection,
+ * leaves the cursor from the most useful place.
+ * Also, the end can't always be set, so don't give it priority. */
+ txt_move_to(text, lineno_end - 1, offset_end, false);
txt_move_to(text, lineno - 1, offset, true);
}
}
-/* returns a dummy filename for a textblock so we can tell what file a text block comes from */
-static void bpy_text_filename_get(char *fn, const Main *bmain, size_t fn_len, const Text *text)
+/**
+ * Generate a `filepath` from a text-block so we can tell what file a text block comes from.
+ */
+static void bpy_text_filepath_get(char *filepath,
+ const size_t filepath_maxlen,
+ const Main *bmain,
+ const Text *text)
{
- BLI_snprintf(fn, fn_len, "%s%c%s", ID_BLEND_PATH(bmain, &text->id), SEP, text->id.name + 2);
+ BLI_snprintf(filepath,
+ filepath_maxlen,
+ "%s%c%s",
+ ID_BLEND_PATH(bmain, &text->id),
+ SEP,
+ text->id.name + 2);
}
/* Very annoying! Undo #_PyModule_Clear(), see T23871. */
@@ -74,17 +85,24 @@ typedef struct {
*
* \note Share a function for this since setup/cleanup logic is the same.
*/
-static bool python_script_exec(
- bContext *C, const char *fn, struct Text *text, struct ReportList *reports, const bool do_jump)
+static bool python_script_exec(bContext *C,
+ const char *filepath,
+ struct Text *text,
+ struct ReportList *reports,
+ const bool do_jump)
{
Main *bmain_old = CTX_data_main(C);
PyObject *main_mod = NULL;
PyObject *py_dict = NULL, *py_result = NULL;
PyGILState_STATE gilstate;
- BLI_assert(fn || text);
+ char filepath_dummy[FILE_MAX];
+ /** The `__file__` added into the name-space. */
+ const char *filepath_namespace = NULL;
+
+ BLI_assert(filepath || text);
- if (fn == NULL && text == NULL) {
+ if (filepath == NULL && text == NULL) {
return 0;
}
@@ -93,40 +111,41 @@ static bool python_script_exec(
PyC_MainModule_Backup(&main_mod);
if (text) {
- char fn_dummy[FILE_MAXDIR];
- bpy_text_filename_get(fn_dummy, bmain_old, sizeof(fn_dummy), text);
+ bpy_text_filepath_get(filepath_dummy, sizeof(filepath_dummy), bmain_old, text);
+ filepath_namespace = filepath_dummy;
if (text->compiled == NULL) { /* if it wasn't already compiled, do it now */
char *buf;
- PyObject *fn_dummy_py;
+ PyObject *filepath_dummy_py;
- fn_dummy_py = PyC_UnicodeFromByte(fn_dummy);
+ filepath_dummy_py = PyC_UnicodeFromByte(filepath_dummy);
size_t buf_len_dummy;
buf = txt_to_buf(text, &buf_len_dummy);
- text->compiled = Py_CompileStringObject(buf, fn_dummy_py, Py_file_input, NULL, -1);
+ text->compiled = Py_CompileStringObject(buf, filepath_dummy_py, Py_file_input, NULL, -1);
MEM_freeN(buf);
- Py_DECREF(fn_dummy_py);
+ Py_DECREF(filepath_dummy_py);
if (PyErr_Occurred()) {
if (do_jump) {
- python_script_error_jump_text(text);
+ python_script_error_jump_text(text, filepath_dummy);
}
BPY_text_free_code(text);
}
}
if (text->compiled) {
- py_dict = PyC_DefaultNameSpace(fn_dummy);
+ py_dict = PyC_DefaultNameSpace(filepath_dummy);
py_result = PyEval_EvalCode(text->compiled, py_dict, py_dict);
}
}
else {
- FILE *fp = BLI_fopen(fn, "r");
+ FILE *fp = BLI_fopen(filepath, "r");
+ filepath_namespace = filepath;
if (fp) {
- py_dict = PyC_DefaultNameSpace(fn);
+ py_dict = PyC_DefaultNameSpace(filepath);
#ifdef _WIN32
/* Previously we used PyRun_File to run directly the code on a FILE
@@ -153,13 +172,13 @@ static bool python_script_exec(
py_result = PyRun_String(pystring, Py_file_input, py_dict, py_dict);
}
#else
- py_result = PyRun_File(fp, fn, Py_file_input, py_dict, py_dict);
+ py_result = PyRun_File(fp, filepath, Py_file_input, py_dict, py_dict);
fclose(fp);
#endif
}
else {
PyErr_Format(
- PyExc_IOError, "Python file \"%s\" could not be opened: %s", fn, strerror(errno));
+ PyExc_IOError, "Python file \"%s\" could not be opened: %s", filepath, strerror(errno));
py_result = NULL;
}
}
@@ -170,7 +189,7 @@ static bool python_script_exec(
/* ensure text is valid before use, the script may have freed itself */
Main *bmain_new = CTX_data_main(C);
if ((bmain_old == bmain_new) && (BLI_findindex(&bmain_new->texts, text) != -1)) {
- python_script_error_jump_text(text);
+ python_script_error_jump_text(text, filepath_namespace);
}
}
}
diff --git a/source/blender/python/intern/bpy_rna_array.c b/source/blender/python/intern/bpy_rna_array.c
index f5bec247250..8506ec97bc3 100644
--- a/source/blender/python/intern/bpy_rna_array.c
+++ b/source/blender/python/intern/bpy_rna_array.c
@@ -377,15 +377,15 @@ static int validate_array(PyObject *rvalue,
totdim);
return -1;
}
- if (pymat->num_col != dimsize[0] || pymat->num_row != dimsize[1]) {
+ if (pymat->col_num != dimsize[0] || pymat->row_num != dimsize[1]) {
PyErr_Format(PyExc_ValueError,
"%s %.200s.%.200s, matrix assign dimension size mismatch, "
"is %dx%d, expected be %dx%d",
error_prefix,
RNA_struct_identifier(ptr->type),
RNA_property_identifier(prop),
- pymat->num_col,
- pymat->num_row,
+ pymat->col_num,
+ pymat->row_num,
dimsize[0],
dimsize[1]);
return -1;
@@ -473,7 +473,7 @@ static char *copy_values(PyObject *seq,
if (dim == 0) {
if (MatrixObject_Check(seq)) {
MatrixObject *pymat = (MatrixObject *)seq;
- const size_t allocsize = pymat->num_col * pymat->num_row * sizeof(float);
+ const size_t allocsize = pymat->col_num * pymat->row_num * sizeof(float);
/* read callback already done by validate */
/* since this is the first iteration we can assume data is allocated */
diff --git a/source/blender/python/intern/bpy_traceback.c b/source/blender/python/intern/bpy_traceback.c
index 13af254c286..40478f3613c 100644
--- a/source/blender/python/intern/bpy_traceback.c
+++ b/source/blender/python/intern/bpy_traceback.c
@@ -24,7 +24,7 @@ static const char *traceback_filepath(PyTracebackObject *tb, PyObject **coerce)
return PyBytes_AS_STRING(*coerce);
}
-/* copied from pythonrun.c, 3.4.0 */
+/* copied from pythonrun.c, 3.10.0 */
_Py_static_string(PyId_string, "<string>");
static int parse_syntax_error(PyObject *err,
@@ -32,14 +32,18 @@ static int parse_syntax_error(PyObject *err,
PyObject **filename,
int *lineno,
int *offset,
+ int *end_lineno,
+ int *end_offset,
PyObject **text)
{
- long hold;
+ Py_ssize_t hold;
PyObject *v;
_Py_IDENTIFIER(msg);
_Py_IDENTIFIER(filename);
_Py_IDENTIFIER(lineno);
_Py_IDENTIFIER(offset);
+ _Py_IDENTIFIER(end_lineno);
+ _Py_IDENTIFIER(end_offset);
_Py_IDENTIFIER(text);
*message = NULL;
@@ -71,7 +75,7 @@ static int parse_syntax_error(PyObject *err,
if (!v) {
goto finally;
}
- hold = PyLong_AsLong(v);
+ hold = PyLong_AsSsize_t(v);
Py_DECREF(v);
if (hold < 0 && PyErr_Occurred()) {
goto finally;
@@ -87,7 +91,7 @@ static int parse_syntax_error(PyObject *err,
Py_DECREF(v);
}
else {
- hold = PyLong_AsLong(v);
+ hold = PyLong_AsSsize_t(v);
Py_DECREF(v);
if (hold < 0 && PyErr_Occurred()) {
goto finally;
@@ -95,6 +99,49 @@ static int parse_syntax_error(PyObject *err,
*offset = (int)hold;
}
+ if (Py_TYPE(err) == (PyTypeObject *)PyExc_SyntaxError) {
+ v = _PyObject_GetAttrId(err, &PyId_end_lineno);
+ if (!v) {
+ PyErr_Clear();
+ *end_lineno = *lineno;
+ }
+ else if (v == Py_None) {
+ *end_lineno = *lineno;
+ Py_DECREF(v);
+ }
+ else {
+ hold = PyLong_AsSsize_t(v);
+ Py_DECREF(v);
+ if (hold < 0 && PyErr_Occurred()) {
+ goto finally;
+ }
+ *end_lineno = hold;
+ }
+
+ v = _PyObject_GetAttrId(err, &PyId_end_offset);
+ if (!v) {
+ PyErr_Clear();
+ *end_offset = -1;
+ }
+ else if (v == Py_None) {
+ *end_offset = -1;
+ Py_DECREF(v);
+ }
+ else {
+ hold = PyLong_AsSsize_t(v);
+ Py_DECREF(v);
+ if (hold < 0 && PyErr_Occurred()) {
+ goto finally;
+ }
+ *end_offset = hold;
+ }
+ }
+ else {
+ /* `SyntaxError` subclasses. */
+ *end_lineno = *lineno;
+ *end_offset = -1;
+ }
+
v = _PyObject_GetAttrId(err, &PyId_text);
if (!v) {
goto finally;
@@ -115,39 +162,48 @@ finally:
}
/* end copied function! */
-void python_script_error_jump(const char *filepath, int *lineno, int *offset)
+bool python_script_error_jump(
+ const char *filepath, int *r_lineno, int *r_offset, int *r_lineno_end, int *r_offset_end)
{
+ bool success = false;
PyObject *exception, *value;
PyTracebackObject *tb;
- *lineno = -1;
- *offset = 0;
+ *r_lineno = -1;
+ *r_offset = 0;
+
+ *r_lineno_end = -1;
+ *r_offset_end = 0;
PyErr_Fetch(&exception, &value, (PyObject **)&tb);
+ if (exception == NULL) {
+ return false;
+ }
- if (exception && PyErr_GivenExceptionMatches(exception, PyExc_SyntaxError)) {
- /* no trace-back available when `SyntaxError`.
- * python has no API's to this. reference #parse_syntax_error() from pythonrun.c */
+ if (PyErr_GivenExceptionMatches(exception, PyExc_SyntaxError)) {
+ /* No trace-back available when `SyntaxError`.
+ * Python has no API's to this. reference #parse_syntax_error() from `pythonrun.c`. */
PyErr_NormalizeException(&exception, &value, (PyObject **)&tb);
- if (value) { /* should always be true */
+ if (value) { /* Should always be true. */
PyObject *message;
- PyObject *filename_py, *text_py;
-
- if (parse_syntax_error(value, &message, &filename_py, lineno, offset, &text_py)) {
- const char *filename = PyUnicode_AsUTF8(filename_py);
+ PyObject *filepath_exc_py, *text_py;
+
+ if (parse_syntax_error(value,
+ &message,
+ &filepath_exc_py,
+ r_lineno,
+ r_offset,
+ r_lineno_end,
+ r_offset_end,
+ &text_py)) {
+ const char *filepath_exc = PyUnicode_AsUTF8(filepath_exc_py);
/* python adds a '/', prefix, so check for both */
- if ((BLI_path_cmp(filename, filepath) == 0) ||
- (ELEM(filename[0], '\\', '/') && BLI_path_cmp(filename + 1, filepath) == 0)) {
- /* good */
- }
- else {
- *lineno = -1;
+ if ((BLI_path_cmp(filepath_exc, filepath) == 0) ||
+ (ELEM(filepath_exc[0], '\\', '/') && BLI_path_cmp(filepath_exc + 1, filepath) == 0)) {
+ success = true;
}
}
- else {
- *lineno = -1;
- }
}
PyErr_Restore(exception, value, (PyObject *)tb); /* takes away reference! */
}
@@ -167,9 +223,12 @@ void python_script_error_jump(const char *filepath, int *lineno, int *offset)
Py_DECREF(coerce);
if (match) {
- *lineno = tb->tb_lineno;
+ success = true;
+ *r_lineno = *r_lineno_end = tb->tb_lineno;
/* used to break here, but better find the inner most line */
}
}
}
+
+ return success;
}
diff --git a/source/blender/python/intern/bpy_traceback.h b/source/blender/python/intern/bpy_traceback.h
index 99e032f3594..f5232eca864 100644
--- a/source/blender/python/intern/bpy_traceback.h
+++ b/source/blender/python/intern/bpy_traceback.h
@@ -10,7 +10,8 @@
extern "C" {
#endif
-void python_script_error_jump(const char *filepath, int *lineno, int *offset);
+bool python_script_error_jump(
+ const char *filepath, int *r_lineno, int *r_offset, int *r_lineno_end, int *r_offset_end);
#ifdef __cplusplus
}
diff --git a/source/blender/python/mathutils/mathutils.c b/source/blender/python/mathutils/mathutils.c
index 8ed156a7e55..1aa2cec861c 100644
--- a/source/blender/python/mathutils/mathutils.c
+++ b/source/blender/python/mathutils/mathutils.c
@@ -92,47 +92,46 @@ Py_hash_t mathutils_array_hash(const float *array, size_t array_len)
}
int mathutils_array_parse(
- float *array, int array_min, int array_max, PyObject *value, const char *error_prefix)
+ float *array, int array_num_min, int array_num_max, PyObject *value, const char *error_prefix)
{
- const uint flag = array_max;
- int size;
+ const uint flag = array_num_max;
+ int num;
- array_max &= ~MU_ARRAY_FLAGS;
+ array_num_max &= ~MU_ARRAY_FLAGS;
#if 1 /* approx 6x speedup for mathutils types */
- if ((size = VectorObject_Check(value) ? ((VectorObject *)value)->size : 0) ||
- (size = EulerObject_Check(value) ? 3 : 0) ||
- (size = QuaternionObject_Check(value) ? 4 : 0) ||
- (size = ColorObject_Check(value) ? 3 : 0)) {
+ if ((num = VectorObject_Check(value) ? ((VectorObject *)value)->vec_num : 0) ||
+ (num = EulerObject_Check(value) ? 3 : 0) || (num = QuaternionObject_Check(value) ? 4 : 0) ||
+ (num = ColorObject_Check(value) ? 3 : 0)) {
if (BaseMath_ReadCallback((BaseMathObject *)value) == -1) {
return -1;
}
if (flag & MU_ARRAY_SPILL) {
- CLAMP_MAX(size, array_max);
+ CLAMP_MAX(num, array_num_max);
}
- if (size > array_max || size < array_min) {
- if (array_max == array_min) {
+ if (num > array_num_max || num < array_num_min) {
+ if (array_num_max == array_num_min) {
PyErr_Format(PyExc_ValueError,
- "%.200s: sequence size is %d, expected %d",
+ "%.200s: sequence length is %d, expected %d",
error_prefix,
- size,
- array_max);
+ num,
+ array_num_max);
}
else {
PyErr_Format(PyExc_ValueError,
- "%.200s: sequence size is %d, expected [%d - %d]",
+ "%.200s: sequence length is %d, expected [%d - %d]",
error_prefix,
- size,
- array_min,
- array_max);
+ num,
+ array_num_min,
+ array_num_max);
}
return -1;
}
- memcpy(array, ((const BaseMathObject *)value)->data, size * sizeof(float));
+ memcpy(array, ((const BaseMathObject *)value)->data, num * sizeof(float));
}
else
#endif
@@ -145,77 +144,76 @@ int mathutils_array_parse(
return -1;
}
- size = PySequence_Fast_GET_SIZE(value_fast);
+ num = PySequence_Fast_GET_SIZE(value_fast);
if (flag & MU_ARRAY_SPILL) {
- CLAMP_MAX(size, array_max);
+ CLAMP_MAX(num, array_num_max);
}
- if (size > array_max || size < array_min) {
- if (array_max == array_min) {
+ if (num > array_num_max || num < array_num_min) {
+ if (array_num_max == array_num_min) {
PyErr_Format(PyExc_ValueError,
- "%.200s: sequence size is %d, expected %d",
+ "%.200s: sequence length is %d, expected %d",
error_prefix,
- size,
- array_max);
+ num,
+ array_num_max);
}
else {
PyErr_Format(PyExc_ValueError,
- "%.200s: sequence size is %d, expected [%d - %d]",
+ "%.200s: sequence length is %d, expected [%d - %d]",
error_prefix,
- size,
- array_min,
- array_max);
+ num,
+ array_num_min,
+ array_num_max);
}
Py_DECREF(value_fast);
return -1;
}
- size = mathutils_array_parse_fast(array, size, value_fast, error_prefix);
+ num = mathutils_array_parse_fast(array, num, value_fast, error_prefix);
Py_DECREF(value_fast);
}
- if (size != -1) {
+ if (num != -1) {
if (flag & MU_ARRAY_ZERO) {
- const int size_left = array_max - size;
- if (size_left) {
- memset(&array[size], 0, sizeof(float) * size_left);
+ const int array_num_left = array_num_max - num;
+ if (array_num_left) {
+ memset(&array[num], 0, sizeof(float) * array_num_left);
}
}
}
- return size;
+ return num;
}
int mathutils_array_parse_alloc(float **array,
- int array_min,
+ int array_num,
PyObject *value,
const char *error_prefix)
{
- int size;
+ int num;
#if 1 /* approx 6x speedup for mathutils types */
- if ((size = VectorObject_Check(value) ? ((VectorObject *)value)->size : 0) ||
- (size = EulerObject_Check(value) ? 3 : 0) ||
- (size = QuaternionObject_Check(value) ? 4 : 0) ||
- (size = ColorObject_Check(value) ? 3 : 0)) {
+ if ((num = VectorObject_Check(value) ? ((VectorObject *)value)->vec_num : 0) ||
+ (num = EulerObject_Check(value) ? 3 : 0) || (num = QuaternionObject_Check(value) ? 4 : 0) ||
+ (num = ColorObject_Check(value) ? 3 : 0)) {
if (BaseMath_ReadCallback((BaseMathObject *)value) == -1) {
return -1;
}
- if (size < array_min) {
+ if (num < array_num) {
PyErr_Format(PyExc_ValueError,
"%.200s: sequence size is %d, expected > %d",
error_prefix,
- size,
- array_min);
+ num,
+ array_num);
return -1;
}
- *array = PyMem_Malloc(size * sizeof(float));
- memcpy(*array, ((const BaseMathObject *)value)->data, size * sizeof(float));
- return size;
+ *array = PyMem_Malloc(num * sizeof(float));
+ memcpy(*array, ((const BaseMathObject *)value)->data, num * sizeof(float));
+ return num;
}
#endif
@@ -230,21 +228,21 @@ int mathutils_array_parse_alloc(float **array,
return -1;
}
- size = PySequence_Fast_GET_SIZE(value_fast);
+ num = PySequence_Fast_GET_SIZE(value_fast);
- if (size < array_min) {
+ if (num < array_num) {
Py_DECREF(value_fast);
PyErr_Format(PyExc_ValueError,
"%.200s: sequence size is %d, expected > %d",
error_prefix,
- size,
- array_min);
+ num,
+ array_num);
return -1;
}
- *array = PyMem_Malloc(size * sizeof(float));
+ *array = PyMem_Malloc(num * sizeof(float));
- ret = mathutils_array_parse_fast(*array, size, value_fast, error_prefix);
+ ret = mathutils_array_parse_fast(*array, num, value_fast, error_prefix);
Py_DECREF(value_fast);
if (ret == -1) {
@@ -261,7 +259,7 @@ int mathutils_array_parse_alloc_v(float **array,
{
PyObject *value_fast;
const int array_dim_flag = array_dim;
- int i, size;
+ int i, num;
/* non list/tuple cases */
if (!(value_fast = PySequence_Fast(value, error_prefix))) {
@@ -269,30 +267,30 @@ int mathutils_array_parse_alloc_v(float **array,
return -1;
}
- size = PySequence_Fast_GET_SIZE(value_fast);
+ num = PySequence_Fast_GET_SIZE(value_fast);
- if (size != 0) {
+ if (num != 0) {
PyObject **value_fast_items = PySequence_Fast_ITEMS(value_fast);
float *fp;
array_dim &= ~MU_ARRAY_FLAGS;
- fp = *array = PyMem_Malloc(size * array_dim * sizeof(float));
+ fp = *array = PyMem_Malloc(num * array_dim * sizeof(float));
- for (i = 0; i < size; i++, fp += array_dim) {
+ for (i = 0; i < num; i++, fp += array_dim) {
PyObject *item = value_fast_items[i];
if (mathutils_array_parse(fp, array_dim, array_dim_flag, item, error_prefix) == -1) {
PyMem_Free(*array);
*array = NULL;
- size = -1;
+ num = -1;
break;
}
}
}
Py_DECREF(value_fast);
- return size;
+ return num;
}
int mathutils_int_array_parse(int *array, int array_dim, PyObject *value, const char *error_prefix)
@@ -458,7 +456,7 @@ int mathutils_any_to_rotmat(float rmat[3][3], PyObject *value, const char *error
if (BaseMath_ReadCallback((BaseMathObject *)value) == -1) {
return -1;
}
- if (((MatrixObject *)value)->num_row < 3 || ((MatrixObject *)value)->num_col < 3) {
+ if (((MatrixObject *)value)->row_num < 3 || ((MatrixObject *)value)->col_num < 3) {
PyErr_Format(
PyExc_ValueError, "%.200s: matrix must have minimum 3x3 dimensions", error_prefix);
return -1;
diff --git a/source/blender/python/mathutils/mathutils.h b/source/blender/python/mathutils/mathutils.h
index 5831489ef5b..84386e99d18 100644
--- a/source/blender/python/mathutils/mathutils.h
+++ b/source/blender/python/mathutils/mathutils.h
@@ -153,12 +153,12 @@ void _BaseMathObject_RaiseNotFrozenExc(const BaseMathObject *self);
* \return length of `value`, -1 on error.
*/
int mathutils_array_parse(
- float *array, int array_min, int array_max, PyObject *value, const char *error_prefix);
+ float *array, int array_num_min, int array_num_max, PyObject *value, const char *error_prefix);
/**
* \return -1 is returned on error and no allocation is made.
*/
int mathutils_array_parse_alloc(float **array,
- int array_min,
+ int array_num_min,
PyObject *value,
const char *error_prefix);
/**
diff --git a/source/blender/python/mathutils/mathutils_Matrix.c b/source/blender/python/mathutils/mathutils_Matrix.c
index b8eaf1486ab..76b5424711f 100644
--- a/source/blender/python/mathutils/mathutils_Matrix.c
+++ b/source/blender/python/mathutils/mathutils_Matrix.c
@@ -34,7 +34,7 @@ static PyObject *MatrixAccess_CreatePyObject(MatrixObject *matrix, const eMatrix
static int matrix_row_vector_check(MatrixObject *mat, VectorObject *vec, int row)
{
- if ((vec->size != mat->num_col) || (row >= mat->num_row)) {
+ if ((vec->vec_num != mat->col_num) || (row >= mat->row_num)) {
PyErr_SetString(PyExc_AttributeError,
"Matrix(): "
"owner matrix has been resized since this row vector was created");
@@ -46,7 +46,7 @@ static int matrix_row_vector_check(MatrixObject *mat, VectorObject *vec, int row
static int matrix_col_vector_check(MatrixObject *mat, VectorObject *vec, int col)
{
- if ((vec->size != mat->num_row) || (col >= mat->num_col)) {
+ if ((vec->vec_num != mat->row_num) || (col >= mat->col_num)) {
PyErr_SetString(PyExc_AttributeError,
"Matrix(): "
"owner matrix has been resized since this column vector was created");
@@ -80,7 +80,7 @@ static int mathutils_matrix_row_get(BaseMathObject *bmo, int row)
return -1;
}
- for (col = 0; col < self->num_col; col++) {
+ for (col = 0; col < self->col_num; col++) {
bmo->data[col] = MATRIX_ITEM(self, row, col);
}
@@ -99,7 +99,7 @@ static int mathutils_matrix_row_set(BaseMathObject *bmo, int row)
return -1;
}
- for (col = 0; col < self->num_col; col++) {
+ for (col = 0; col < self->col_num; col++) {
MATRIX_ITEM(self, row, col) = bmo->data[col];
}
@@ -162,7 +162,7 @@ static int mathutils_matrix_col_check(BaseMathObject *bmo)
static int mathutils_matrix_col_get(BaseMathObject *bmo, int col)
{
MatrixObject *self = (MatrixObject *)bmo->cb_user;
- int num_row;
+ int row_num;
int row;
if (BaseMath_ReadCallback(self) == -1) {
@@ -172,10 +172,10 @@ static int mathutils_matrix_col_get(BaseMathObject *bmo, int col)
return -1;
}
- /* for 'translation' size will always be '3' even on 4x4 vec */
- num_row = min_ii(self->num_row, ((const VectorObject *)bmo)->size);
+ /* for 'translation' `vec_num` will always be '3' even on 4x4 vec */
+ row_num = min_ii(self->row_num, ((const VectorObject *)bmo)->vec_num);
- for (row = 0; row < num_row; row++) {
+ for (row = 0; row < row_num; row++) {
bmo->data[row] = MATRIX_ITEM(self, row, col);
}
@@ -185,7 +185,7 @@ static int mathutils_matrix_col_get(BaseMathObject *bmo, int col)
static int mathutils_matrix_col_set(BaseMathObject *bmo, int col)
{
MatrixObject *self = (MatrixObject *)bmo->cb_user;
- int num_row;
+ int row_num;
int row;
if (BaseMath_ReadCallback_ForWrite(self) == -1) {
@@ -195,10 +195,10 @@ static int mathutils_matrix_col_set(BaseMathObject *bmo, int col)
return -1;
}
- /* for 'translation' size will always be '3' even on 4x4 vec */
- num_row = min_ii(self->num_row, ((const VectorObject *)bmo)->size);
+ /* for 'translation' `vec_num` will always be '3' even on 4x4 vec */
+ row_num = min_ii(self->row_num, ((const VectorObject *)bmo)->vec_num);
- for (row = 0; row < num_row; row++) {
+ for (row = 0; row < row_num; row++) {
MATRIX_ITEM(self, row, col) = bmo->data[row];
}
@@ -349,18 +349,18 @@ static PyObject *Matrix_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
/* Input is now as a sequence of rows so length of sequence
* is the number of rows */
/* -1 is an error, size checks will account for this */
- const ushort num_row = PySequence_Size(arg);
+ const ushort row_num = PySequence_Size(arg);
- if (num_row >= 2 && num_row <= 4) {
+ if (row_num >= 2 && row_num <= 4) {
PyObject *item = PySequence_GetItem(arg, 0);
/* Since each item is a row, number of items is the
* same as the number of columns */
- const ushort num_col = PySequence_Size(item);
+ const ushort col_num = PySequence_Size(item);
Py_XDECREF(item);
- if (num_col >= 2 && num_col <= 4) {
+ if (col_num >= 2 && col_num <= 4) {
/* Sane row & col size, new matrix and assign as slice. */
- PyObject *matrix = Matrix_CreatePyObject(NULL, num_col, num_row, type);
+ PyObject *matrix = Matrix_CreatePyObject(NULL, col_num, row_num, type);
if (Matrix_ass_slice((MatrixObject *)matrix, 0, INT_MAX, arg) == 0) {
return matrix;
}
@@ -613,7 +613,7 @@ PyDoc_STRVAR(C_Matrix_Scale_doc,
static PyObject *C_Matrix_Scale(PyObject *cls, PyObject *args)
{
PyObject *vec = NULL;
- int vec_size;
+ int vec_num;
float tvec[3];
float factor;
int matSize;
@@ -646,12 +646,10 @@ static PyObject *C_Matrix_Scale(PyObject *cls, PyObject *args)
return NULL;
}
if (vec) {
- vec_size = (matSize == 2 ? 2 : 3);
- if (mathutils_array_parse(tvec,
- vec_size,
- vec_size,
- vec,
- "Matrix.Scale(factor, size, axis), invalid 'axis' arg") == -1) {
+ vec_num = (matSize == 2 ? 2 : 3);
+ if (mathutils_array_parse(
+ tvec, vec_num, vec_num, vec, "Matrix.Scale(factor, size, axis), invalid 'axis' arg") ==
+ -1) {
return NULL;
}
}
@@ -671,11 +669,11 @@ static PyObject *C_Matrix_Scale(PyObject *cls, PyObject *args)
* normalize arbitrary axis */
float norm = 0.0f;
int x;
- for (x = 0; x < vec_size; x++) {
+ for (x = 0; x < vec_num; x++) {
norm += tvec[x] * tvec[x];
}
norm = sqrtf(norm);
- for (x = 0; x < vec_size; x++) {
+ for (x = 0; x < vec_num; x++) {
tvec[x] /= norm;
}
if (matSize == 2) {
@@ -795,23 +793,23 @@ static PyObject *C_Matrix_OrthoProjection(PyObject *cls, PyObject *args)
else {
/* arbitrary plane */
- const int vec_size = (matSize == 2 ? 2 : 3);
+ const int vec_num = (matSize == 2 ? 2 : 3);
float tvec[4];
if (mathutils_array_parse(tvec,
- vec_size,
- vec_size,
+ vec_num,
+ vec_num,
axis,
"Matrix.OrthoProjection(axis, size), invalid 'axis' arg") == -1) {
return NULL;
}
/* normalize arbitrary axis */
- for (x = 0; x < vec_size; x++) {
+ for (x = 0; x < vec_num; x++) {
norm += tvec[x] * tvec[x];
}
norm = sqrtf(norm);
- for (x = 0; x < vec_size; x++) {
+ for (x = 0; x < vec_num; x++) {
tvec[x] /= norm;
}
if (matSize == 2) {
@@ -1019,7 +1017,7 @@ static PyObject *C_Matrix_LocRotScale(PyObject *cls, PyObject *args)
return NULL;
}
- if (mat_obj->num_col == 3 && mat_obj->num_row == 3) {
+ if (mat_obj->col_num == 3 && mat_obj->row_num == 3) {
copy_m4_m3(mat, (const float(*)[3])mat_obj->matrix);
}
else {
@@ -1062,20 +1060,20 @@ void matrix_as_3x3(float mat[3][3], MatrixObject *self)
static void matrix_copy(MatrixObject *mat_dst, const MatrixObject *mat_src)
{
- BLI_assert((mat_dst->num_col == mat_src->num_col) && (mat_dst->num_row == mat_src->num_row));
+ BLI_assert((mat_dst->col_num == mat_src->col_num) && (mat_dst->row_num == mat_src->row_num));
BLI_assert(mat_dst != mat_src);
- memcpy(mat_dst->matrix, mat_src->matrix, sizeof(float) * (mat_dst->num_col * mat_dst->num_row));
+ memcpy(mat_dst->matrix, mat_src->matrix, sizeof(float) * (mat_dst->col_num * mat_dst->row_num));
}
static void matrix_unit_internal(MatrixObject *self)
{
- const int mat_size = sizeof(float) * (self->num_col * self->num_row);
+ const int mat_size = sizeof(float) * (self->col_num * self->row_num);
memset(self->matrix, 0x0, mat_size);
- const int col_row_max = min_ii(self->num_col, self->num_row);
- const int num_row = self->num_row;
+ const int col_row_max = min_ii(self->col_num, self->row_num);
+ const int row_num = self->row_num;
for (int col = 0; col < col_row_max; col++) {
- self->matrix[(col * num_row) + col] = 1.0f;
+ self->matrix[(col * row_num) + col] = 1.0f;
}
}
@@ -1085,8 +1083,8 @@ static void matrix_transpose_internal(float mat_dst_fl[], const MatrixObject *ma
ushort col, row;
uint i = 0;
- for (row = 0; row < mat_src->num_row; row++) {
- for (col = 0; col < mat_src->num_col; col++) {
+ for (row = 0; row < mat_src->row_num; row++) {
+ for (col = 0; col < mat_src->col_num; col++) {
mat_dst_fl[i++] = MATRIX_ITEM(mat_src, row, col);
}
}
@@ -1095,13 +1093,13 @@ static void matrix_transpose_internal(float mat_dst_fl[], const MatrixObject *ma
/* assumes rowsize == colsize is checked and the read callback has run */
static float matrix_determinant_internal(const MatrixObject *self)
{
- if (self->num_col == 2) {
+ if (self->col_num == 2) {
return determinant_m2(MATRIX_ITEM(self, 0, 0),
MATRIX_ITEM(self, 0, 1),
MATRIX_ITEM(self, 1, 0),
MATRIX_ITEM(self, 1, 1));
}
- if (self->num_col == 3) {
+ if (self->col_num == 3) {
return determinant_m3(MATRIX_ITEM(self, 0, 0),
MATRIX_ITEM(self, 0, 1),
MATRIX_ITEM(self, 0, 2),
@@ -1152,8 +1150,8 @@ static void matrix_invert_with_det_n_internal(float *mat_dst,
/* divide by determinant & set values */
k = 0;
- for (i = 0; i < dim; i++) { /* num_col */
- for (j = 0; j < dim; j++) { /* num_row */
+ for (i = 0; i < dim; i++) { /* col_num */
+ for (j = 0; j < dim; j++) { /* row_num */
mat_dst[MATRIX_ITEM_INDEX_NUMROW(dim, j, i)] = mat[k++] / det;
}
}
@@ -1165,11 +1163,11 @@ static void matrix_invert_with_det_n_internal(float *mat_dst,
static bool matrix_invert_internal(const MatrixObject *self, float *r_mat)
{
float det;
- BLI_assert(self->num_col == self->num_row);
+ BLI_assert(self->col_num == self->row_num);
det = matrix_determinant_internal(self);
if (det != 0.0f) {
- matrix_invert_with_det_n_internal(r_mat, self->matrix, det, self->num_col);
+ matrix_invert_with_det_n_internal(r_mat, self->matrix, det, self->col_num);
return true;
}
@@ -1184,7 +1182,7 @@ static void matrix_invert_safe_internal(const MatrixObject *self, float *r_mat)
{
float det;
float *in_mat = self->matrix;
- BLI_assert(self->num_col == self->num_row);
+ BLI_assert(self->col_num == self->row_num);
det = matrix_determinant_internal(self);
if (det == 0.0f) {
@@ -1194,7 +1192,7 @@ static void matrix_invert_safe_internal(const MatrixObject *self, float *r_mat)
* and modify it in place to add diagonal epsilon. */
in_mat = r_mat;
- switch (self->num_col) {
+ switch (self->col_num) {
case 2: {
float(*mat)[2] = (float(*)[2])in_mat;
@@ -1248,7 +1246,7 @@ static void matrix_invert_safe_internal(const MatrixObject *self, float *r_mat)
}
}
- matrix_invert_with_det_n_internal(r_mat, in_mat, det, self->num_col);
+ matrix_invert_with_det_n_internal(r_mat, in_mat, det, self->col_num);
}
/*-----------------------------METHODS----------------------------*/
@@ -1268,13 +1266,13 @@ static PyObject *Matrix_to_quaternion(MatrixObject *self)
}
/* must be 3-4 cols, 3-4 rows, square matrix */
- if ((self->num_row < 3) || (self->num_col < 3) || (self->num_row != self->num_col)) {
+ if ((self->row_num < 3) || (self->col_num < 3) || (self->row_num != self->col_num)) {
PyErr_SetString(PyExc_ValueError,
"Matrix.to_quat(): "
"inappropriate matrix size - expects 3x3 or 4x4 matrix");
return NULL;
}
- if (self->num_row == 3) {
+ if (self->row_num == 3) {
mat3_to_quat(quat, (float(*)[3])self->matrix);
}
else {
@@ -1326,10 +1324,10 @@ static PyObject *Matrix_to_euler(MatrixObject *self, PyObject *args)
}
/* Must be 3-4 cols, 3-4 rows, square matrix. */
- if (self->num_row == 3 && self->num_col == 3) {
+ if (self->row_num == 3 && self->col_num == 3) {
copy_m3_m3(mat, (const float(*)[3])self->matrix);
}
- else if (self->num_row == 4 && self->num_col == 4) {
+ else if (self->row_num == 4 && self->col_num == 4) {
copy_m3_m4(mat, (const float(*)[4])self->matrix);
}
else {
@@ -1401,36 +1399,36 @@ static PyObject *Matrix_resize_4x4(MatrixObject *self)
unit_m4(mat);
- for (col = 0; col < self->num_col; col++) {
- memcpy(mat[col], MATRIX_COL_PTR(self, col), self->num_row * sizeof(float));
+ for (col = 0; col < self->col_num; col++) {
+ memcpy(mat[col], MATRIX_COL_PTR(self, col), self->row_num * sizeof(float));
}
copy_m4_m4((float(*)[4])self->matrix, (const float(*)[4])mat);
- self->num_col = 4;
- self->num_row = 4;
+ self->col_num = 4;
+ self->row_num = 4;
Py_RETURN_NONE;
}
-static PyObject *Matrix_to_NxN(MatrixObject *self, const int num_col, const int num_row)
+static PyObject *Matrix_to_NxN(MatrixObject *self, const int col_num, const int row_num)
{
- const int mat_size = sizeof(float) * (num_col * num_row);
+ const int mat_size = sizeof(float) * (col_num * row_num);
MatrixObject *pymat = (MatrixObject *)Matrix_CreatePyObject_alloc(
- PyMem_Malloc(mat_size), num_col, num_row, Py_TYPE(self));
+ PyMem_Malloc(mat_size), col_num, row_num, Py_TYPE(self));
- if ((self->num_row == num_row) && (self->num_col == num_col)) {
+ if ((self->row_num == row_num) && (self->col_num == col_num)) {
memcpy(pymat->matrix, self->matrix, mat_size);
}
else {
- if ((self->num_col < num_col) || (self->num_row < num_row)) {
+ if ((self->col_num < col_num) || (self->row_num < row_num)) {
matrix_unit_internal(pymat);
}
- const int col_len_src = min_ii(num_col, self->num_col);
- const int row_len_src = min_ii(num_row, self->num_row);
+ const int col_len_src = min_ii(col_num, self->col_num);
+ const int row_len_src = min_ii(row_num, self->row_num);
for (int col = 0; col < col_len_src; col++) {
memcpy(
- &pymat->matrix[col * num_row], MATRIX_COL_PTR(self, col), sizeof(float) * row_len_src);
+ &pymat->matrix[col * row_num], MATRIX_COL_PTR(self, col), sizeof(float) * row_len_src);
}
}
return (PyObject *)pymat;
@@ -1495,7 +1493,7 @@ static PyObject *Matrix_to_translation(MatrixObject *self)
return NULL;
}
- if ((self->num_row < 3) || self->num_col < 4) {
+ if ((self->row_num < 3) || self->col_num < 4) {
PyErr_SetString(PyExc_ValueError,
"Matrix.to_translation(): "
"inappropriate matrix size");
@@ -1526,7 +1524,7 @@ static PyObject *Matrix_to_scale(MatrixObject *self)
}
/* Must be 3-4 cols, 3-4 rows, square matrix. */
- if ((self->num_row < 3) || (self->num_col < 3)) {
+ if ((self->row_num < 3) || (self->col_num < 3)) {
PyErr_SetString(PyExc_ValueError,
"Matrix.to_scale(): "
"inappropriate matrix size, 3x3 minimum size");
@@ -1546,7 +1544,7 @@ static PyObject *Matrix_to_scale(MatrixObject *self)
/* re-usable checks for invert */
static bool matrix_invert_is_compat(const MatrixObject *self)
{
- if (self->num_col != self->num_row) {
+ if (self->col_num != self->row_num) {
PyErr_SetString(PyExc_ValueError,
"Matrix.invert(ed): "
"only square matrices are supported");
@@ -1571,7 +1569,7 @@ static bool matrix_invert_args_check(const MatrixObject *self, PyObject *args, b
return false;
}
- if ((self->num_col != fallback->num_col) || (self->num_row != fallback->num_row)) {
+ if ((self->col_num != fallback->col_num) || (self->row_num != fallback->row_num)) {
PyErr_SetString(PyExc_TypeError,
"Matrix.invert: "
"matrix argument has different dimensions");
@@ -1782,7 +1780,7 @@ static PyObject *Matrix_adjugate(MatrixObject *self)
return NULL;
}
- if (self->num_col != self->num_row) {
+ if (self->col_num != self->row_num) {
PyErr_SetString(PyExc_ValueError,
"Matrix.adjugate(d): "
"only square matrices are supported");
@@ -1790,12 +1788,12 @@ static PyObject *Matrix_adjugate(MatrixObject *self)
}
/* calculate the classical adjoint */
- if (self->num_col <= 4) {
- adjoint_matrix_n(self->matrix, self->matrix, self->num_col);
+ if (self->col_num <= 4) {
+ adjoint_matrix_n(self->matrix, self->matrix, self->col_num);
}
else {
PyErr_Format(
- PyExc_ValueError, "Matrix adjugate(d): size (%d) unsupported", (int)self->num_col);
+ PyExc_ValueError, "Matrix adjugate(d): size (%d) unsupported", (int)self->col_num);
return NULL;
}
@@ -1838,7 +1836,7 @@ static PyObject *Matrix_rotate(MatrixObject *self, PyObject *value)
return NULL;
}
- if (self->num_row != 3 || self->num_col != 3) {
+ if (self->row_num != 3 || self->col_num != 3) {
PyErr_SetString(PyExc_ValueError,
"Matrix.rotate(): "
"must have 3x3 dimensions");
@@ -1870,7 +1868,7 @@ static PyObject *Matrix_decompose(MatrixObject *self)
float quat[4];
float size[3];
- if (self->num_row != 4 || self->num_col != 4) {
+ if (self->row_num != 4 || self->col_num != 4) {
PyErr_SetString(PyExc_ValueError,
"Matrix.decompose(): "
"inappropriate matrix size - expects 4x4 matrix");
@@ -1913,7 +1911,7 @@ static PyObject *Matrix_lerp(MatrixObject *self, PyObject *args)
return NULL;
}
- if (self->num_col != mat2->num_col || self->num_row != mat2->num_row) {
+ if (self->col_num != mat2->col_num || self->row_num != mat2->row_num) {
PyErr_SetString(PyExc_ValueError,
"Matrix.lerp(): "
"expects both matrix objects of the same dimensions");
@@ -1925,14 +1923,14 @@ static PyObject *Matrix_lerp(MatrixObject *self, PyObject *args)
}
/* TODO: different sized matrix. */
- if (self->num_col == 4 && self->num_row == 4) {
+ if (self->col_num == 4 && self->row_num == 4) {
#ifdef MATH_STANDALONE
blend_m4_m4m4((float(*)[4])mat, (float(*)[4])self->matrix, (float(*)[4])mat2->matrix, fac);
#else
interp_m4_m4m4((float(*)[4])mat, (float(*)[4])self->matrix, (float(*)[4])mat2->matrix, fac);
#endif
}
- else if (self->num_col == 3 && self->num_row == 3) {
+ else if (self->col_num == 3 && self->row_num == 3) {
#ifdef MATH_STANDALONE
blend_m3_m3m3((float(*)[3])mat, (float(*)[3])self->matrix, (float(*)[3])mat2->matrix, fac);
#else
@@ -1946,7 +1944,7 @@ static PyObject *Matrix_lerp(MatrixObject *self, PyObject *args)
return NULL;
}
- return Matrix_CreatePyObject(mat, self->num_col, self->num_row, Py_TYPE(self));
+ return Matrix_CreatePyObject(mat, self->col_num, self->row_num, Py_TYPE(self));
}
/*---------------------------matrix.determinant() ----------------*/
@@ -1966,7 +1964,7 @@ static PyObject *Matrix_determinant(MatrixObject *self)
return NULL;
}
- if (self->num_col != self->num_row) {
+ if (self->col_num != self->row_num) {
PyErr_SetString(PyExc_ValueError,
"Matrix.determinant(): "
"only square matrices are supported");
@@ -1989,19 +1987,19 @@ static PyObject *Matrix_transpose(MatrixObject *self)
return NULL;
}
- if (self->num_col != self->num_row) {
+ if (self->col_num != self->row_num) {
PyErr_SetString(PyExc_ValueError,
"Matrix.transpose(d): "
"only square matrices are supported");
return NULL;
}
- if (self->num_col == 2) {
+ if (self->col_num == 2) {
const float t = MATRIX_ITEM(self, 1, 0);
MATRIX_ITEM(self, 1, 0) = MATRIX_ITEM(self, 0, 1);
MATRIX_ITEM(self, 0, 1) = t;
}
- else if (self->num_col == 3) {
+ else if (self->col_num == 3) {
transpose_m3((float(*)[3])self->matrix);
}
else {
@@ -2035,17 +2033,17 @@ static PyObject *Matrix_normalize(MatrixObject *self)
return NULL;
}
- if (self->num_col != self->num_row) {
+ if (self->col_num != self->row_num) {
PyErr_SetString(PyExc_ValueError,
"Matrix.normalize(): "
"only square matrices are supported");
return NULL;
}
- if (self->num_col == 3) {
+ if (self->col_num == 3) {
normalize_m3((float(*)[3])self->matrix);
}
- else if (self->num_col == 4) {
+ else if (self->col_num == 4) {
normalize_m4((float(*)[4])self->matrix);
}
else {
@@ -2083,7 +2081,7 @@ static PyObject *Matrix_zero(MatrixObject *self)
return NULL;
}
- copy_vn_fl(self->matrix, self->num_col * self->num_row, 0.0f);
+ copy_vn_fl(self->matrix, self->col_num * self->row_num, 0.0f);
if (BaseMath_WriteCallback(self) == -1) {
return NULL;
@@ -2094,12 +2092,12 @@ static PyObject *Matrix_zero(MatrixObject *self)
/*---------------------------matrix.identity(() ------------------*/
static void matrix_identity_internal(MatrixObject *self)
{
- BLI_assert((self->num_col == self->num_row) && (self->num_row <= 4));
+ BLI_assert((self->col_num == self->row_num) && (self->row_num <= 4));
- if (self->num_col == 2) {
+ if (self->col_num == 2) {
unit_m2((float(*)[2])self->matrix);
}
- else if (self->num_col == 3) {
+ else if (self->col_num == 3) {
unit_m3((float(*)[3])self->matrix);
}
else {
@@ -2123,7 +2121,7 @@ static PyObject *Matrix_identity(MatrixObject *self)
return NULL;
}
- if (self->num_col != self->num_row) {
+ if (self->col_num != self->row_num) {
PyErr_SetString(PyExc_ValueError,
"Matrix.identity(): "
"only square matrices are supported");
@@ -2143,7 +2141,7 @@ static PyObject *Matrix_identity(MatrixObject *self)
static PyObject *Matrix_copy_notest(MatrixObject *self, const float *matrix)
{
- return Matrix_CreatePyObject((const float *)matrix, self->num_col, self->num_row, Py_TYPE(self));
+ return Matrix_CreatePyObject((const float *)matrix, self->col_num, self->row_num, Py_TYPE(self));
}
PyDoc_STRVAR(Matrix_copy_doc,
@@ -2180,13 +2178,13 @@ static PyObject *Matrix_repr(MatrixObject *self)
return NULL;
}
- for (row = 0; row < self->num_row; row++) {
- rows[row] = PyTuple_New(self->num_col);
- for (col = 0; col < self->num_col; col++) {
+ for (row = 0; row < self->row_num; row++) {
+ rows[row] = PyTuple_New(self->col_num);
+ for (col = 0; col < self->col_num; col++) {
PyTuple_SET_ITEM(rows[row], col, PyFloat_FromDouble(MATRIX_ITEM(self, row, col)));
}
}
- switch (self->num_row) {
+ switch (self->row_num) {
case 2:
return PyUnicode_FromFormat(
"Matrix((%R,\n"
@@ -2236,9 +2234,9 @@ static PyObject *Matrix_str(MatrixObject *self)
ds = BLI_dynstr_new();
/* First determine the maximum width for each column */
- for (col = 0; col < self->num_col; col++) {
+ for (col = 0; col < self->col_num; col++) {
maxsize[col] = 0;
- for (row = 0; row < self->num_row; row++) {
+ for (row = 0; row < self->row_num; row++) {
const int size = BLI_snprintf_rlen(
dummy_buf, sizeof(dummy_buf), "%.4f", MATRIX_ITEM(self, row, col));
maxsize[col] = max_ii(maxsize[col], size);
@@ -2246,12 +2244,12 @@ static PyObject *Matrix_str(MatrixObject *self)
}
/* Now write the unicode string to be printed */
- BLI_dynstr_appendf(ds, "<Matrix %dx%d (", self->num_row, self->num_col);
- for (row = 0; row < self->num_row; row++) {
- for (col = 0; col < self->num_col; col++) {
+ BLI_dynstr_appendf(ds, "<Matrix %dx%d (", self->row_num, self->col_num);
+ for (row = 0; row < self->row_num; row++) {
+ for (col = 0; col < self->col_num; col++) {
BLI_dynstr_appendf(ds, col ? ", %*.4f" : "%*.4f", maxsize[col], MATRIX_ITEM(self, row, col));
}
- BLI_dynstr_append(ds, row + 1 != self->num_row ? ")\n (" : ")");
+ BLI_dynstr_append(ds, row + 1 != self->row_num ? ")\n (" : ")");
}
BLI_dynstr_append(ds, ">");
@@ -2272,8 +2270,8 @@ static PyObject *Matrix_richcmpr(PyObject *a, PyObject *b, int op)
return NULL;
}
- ok = ((matA->num_row == matB->num_row) && (matA->num_col == matB->num_col) &&
- EXPP_VectorsAreEqual(matA->matrix, matB->matrix, (matA->num_col * matA->num_row), 1)) ?
+ ok = ((matA->row_num == matB->row_num) && (matA->col_num == matB->col_num) &&
+ EXPP_VectorsAreEqual(matA->matrix, matB->matrix, (matA->col_num * matA->row_num), 1)) ?
0 :
-1;
}
@@ -2314,7 +2312,7 @@ static Py_hash_t Matrix_hash(MatrixObject *self)
matrix_transpose_internal(mat, self);
- return mathutils_array_hash(mat, self->num_row * self->num_col);
+ return mathutils_array_hash(mat, self->row_num * self->col_num);
}
/*---------------------SEQUENCE PROTOCOLS------------------------
@@ -2322,7 +2320,7 @@ static Py_hash_t Matrix_hash(MatrixObject *self)
* sequence length */
static int Matrix_len(MatrixObject *self)
{
- return self->num_row;
+ return self->row_num;
}
/*----------------------------object[]---------------------------
* sequence accessor (get)
@@ -2333,14 +2331,14 @@ static PyObject *Matrix_item_row(MatrixObject *self, int row)
return NULL;
}
- if (row < 0 || row >= self->num_row) {
+ if (row < 0 || row >= self->row_num) {
PyErr_SetString(PyExc_IndexError,
"matrix[attribute]: "
"array index out of range");
return NULL;
}
return Vector_CreatePyObject_cb(
- (PyObject *)self, self->num_col, mathutils_matrix_row_cb_index, row);
+ (PyObject *)self, self->col_num, mathutils_matrix_row_cb_index, row);
}
/* same but column access */
static PyObject *Matrix_item_col(MatrixObject *self, int col)
@@ -2349,14 +2347,14 @@ static PyObject *Matrix_item_col(MatrixObject *self, int col)
return NULL;
}
- if (col < 0 || col >= self->num_col) {
+ if (col < 0 || col >= self->col_num) {
PyErr_SetString(PyExc_IndexError,
"matrix[attribute]: "
"array index out of range");
return NULL;
}
return Vector_CreatePyObject_cb(
- (PyObject *)self, self->num_row, mathutils_matrix_col_cb_index, col);
+ (PyObject *)self, self->row_num, mathutils_matrix_col_cb_index, col);
}
/*----------------------------object[]-------------------------
@@ -2370,18 +2368,18 @@ static int Matrix_ass_item_row(MatrixObject *self, int row, PyObject *value)
return -1;
}
- if (row >= self->num_row || row < 0) {
+ if (row >= self->row_num || row < 0) {
PyErr_SetString(PyExc_IndexError, "matrix[attribute] = x: bad row");
return -1;
}
if (mathutils_array_parse(
- vec, self->num_col, self->num_col, value, "matrix[i] = value assignment") == -1) {
+ vec, self->col_num, self->col_num, value, "matrix[i] = value assignment") == -1) {
return -1;
}
/* Since we are assigning a row we cannot memcpy */
- for (col = 0; col < self->num_col; col++) {
+ for (col = 0; col < self->col_num; col++) {
MATRIX_ITEM(self, row, col) = vec[col];
}
@@ -2396,18 +2394,18 @@ static int Matrix_ass_item_col(MatrixObject *self, int col, PyObject *value)
return -1;
}
- if (col >= self->num_col || col < 0) {
+ if (col >= self->col_num || col < 0) {
PyErr_SetString(PyExc_IndexError, "matrix[attribute] = x: bad col");
return -1;
}
if (mathutils_array_parse(
- vec, self->num_row, self->num_row, value, "matrix[i] = value assignment") == -1) {
+ vec, self->row_num, self->row_num, value, "matrix[i] = value assignment") == -1) {
return -1;
}
/* Since we are assigning a row we cannot memcpy */
- for (row = 0; row < self->num_row; row++) {
+ for (row = 0; row < self->row_num; row++) {
MATRIX_ITEM(self, row, col) = vec[row];
}
@@ -2427,8 +2425,8 @@ static PyObject *Matrix_slice(MatrixObject *self, int begin, int end)
return NULL;
}
- CLAMP(begin, 0, self->num_row);
- CLAMP(end, 0, self->num_row);
+ CLAMP(begin, 0, self->row_num);
+ CLAMP(end, 0, self->row_num);
begin = MIN2(begin, end);
tuple = PyTuple_New(end - begin);
@@ -2436,7 +2434,7 @@ static PyObject *Matrix_slice(MatrixObject *self, int begin, int end)
PyTuple_SET_ITEM(tuple,
count - begin,
Vector_CreatePyObject_cb(
- (PyObject *)self, self->num_col, mathutils_matrix_row_cb_index, count));
+ (PyObject *)self, self->col_num, mathutils_matrix_row_cb_index, count));
}
return tuple;
@@ -2451,8 +2449,8 @@ static int Matrix_ass_slice(MatrixObject *self, int begin, int end, PyObject *va
return -1;
}
- CLAMP(begin, 0, self->num_row);
- CLAMP(end, 0, self->num_row);
+ CLAMP(begin, 0, self->row_num);
+ CLAMP(end, 0, self->row_num);
begin = MIN2(begin, end);
/* non list/tuple cases */
@@ -2475,7 +2473,7 @@ static int Matrix_ass_slice(MatrixObject *self, int begin, int end, PyObject *va
return -1;
}
- memcpy(mat, self->matrix, self->num_col * self->num_row * sizeof(float));
+ memcpy(mat, self->matrix, self->col_num * self->row_num * sizeof(float));
/* parse sub items */
for (row = begin; row < end; row++) {
@@ -2483,21 +2481,21 @@ static int Matrix_ass_slice(MatrixObject *self, int begin, int end, PyObject *va
PyObject *item = value_fast_items[row - begin];
if (mathutils_array_parse(
- vec, self->num_col, self->num_col, item, "matrix[begin:end] = value assignment") ==
+ vec, self->col_num, self->col_num, item, "matrix[begin:end] = value assignment") ==
-1) {
Py_DECREF(value_fast);
return -1;
}
- for (col = 0; col < self->num_col; col++) {
- mat[col * self->num_row + row] = vec[col];
+ for (col = 0; col < self->col_num; col++) {
+ mat[col * self->row_num + row] = vec[col];
}
}
Py_DECREF(value_fast);
/* Parsed well - now set in matrix. */
- memcpy(self->matrix, mat, self->num_col * self->num_row * sizeof(float));
+ memcpy(self->matrix, mat, self->col_num * self->row_num * sizeof(float));
(void)BaseMath_WriteCallback(self);
return 0;
@@ -2525,16 +2523,16 @@ static PyObject *Matrix_add(PyObject *m1, PyObject *m2)
return NULL;
}
- if (mat1->num_col != mat2->num_col || mat1->num_row != mat2->num_row) {
+ if (mat1->col_num != mat2->col_num || mat1->row_num != mat2->row_num) {
PyErr_SetString(PyExc_ValueError,
"Matrix addition: "
"matrices must have the same dimensions for this operation");
return NULL;
}
- add_vn_vnvn(mat, mat1->matrix, mat2->matrix, mat1->num_col * mat1->num_row);
+ add_vn_vnvn(mat, mat1->matrix, mat2->matrix, mat1->col_num * mat1->row_num);
- return Matrix_CreatePyObject(mat, mat1->num_col, mat1->num_row, Py_TYPE(mat1));
+ return Matrix_CreatePyObject(mat, mat1->col_num, mat1->row_num, Py_TYPE(mat1));
}
/*------------------------obj - obj------------------------------
* subtraction */
@@ -2559,24 +2557,24 @@ static PyObject *Matrix_sub(PyObject *m1, PyObject *m2)
return NULL;
}
- if (mat1->num_col != mat2->num_col || mat1->num_row != mat2->num_row) {
+ if (mat1->col_num != mat2->col_num || mat1->row_num != mat2->row_num) {
PyErr_SetString(PyExc_ValueError,
"Matrix addition: "
"matrices must have the same dimensions for this operation");
return NULL;
}
- sub_vn_vnvn(mat, mat1->matrix, mat2->matrix, mat1->num_col * mat1->num_row);
+ sub_vn_vnvn(mat, mat1->matrix, mat2->matrix, mat1->col_num * mat1->row_num);
- return Matrix_CreatePyObject(mat, mat1->num_col, mat1->num_row, Py_TYPE(mat1));
+ return Matrix_CreatePyObject(mat, mat1->col_num, mat1->row_num, Py_TYPE(mat1));
}
/*------------------------obj * obj------------------------------
* element-wise multiplication */
static PyObject *matrix_mul_float(MatrixObject *mat, const float scalar)
{
float tmat[MATRIX_MAX_DIM * MATRIX_MAX_DIM];
- mul_vn_vn_fl(tmat, mat->matrix, mat->num_col * mat->num_row, scalar);
- return Matrix_CreatePyObject(tmat, mat->num_col, mat->num_row, Py_TYPE(mat));
+ mul_vn_vn_fl(tmat, mat->matrix, mat->col_num * mat->row_num, scalar);
+ return Matrix_CreatePyObject(tmat, mat->col_num, mat->row_num, Py_TYPE(mat));
}
static PyObject *Matrix_mul(PyObject *m1, PyObject *m2)
@@ -2602,16 +2600,16 @@ static PyObject *Matrix_mul(PyObject *m1, PyObject *m2)
/* MATRIX * MATRIX */
float mat[MATRIX_MAX_DIM * MATRIX_MAX_DIM];
- if ((mat1->num_row != mat2->num_row) || (mat1->num_col != mat2->num_col)) {
+ if ((mat1->row_num != mat2->row_num) || (mat1->col_num != mat2->col_num)) {
PyErr_SetString(PyExc_ValueError,
"matrix1 * matrix2: matrix1 number of rows/columns "
"and the matrix2 number of rows/columns must be the same");
return NULL;
}
- mul_vn_vnvn(mat, mat1->matrix, mat2->matrix, mat1->num_col * mat1->num_row);
+ mul_vn_vnvn(mat, mat1->matrix, mat2->matrix, mat1->col_num * mat1->row_num);
- return Matrix_CreatePyObject(mat, mat2->num_col, mat1->num_row, Py_TYPE(mat1));
+ return Matrix_CreatePyObject(mat, mat2->col_num, mat1->row_num, Py_TYPE(mat1));
}
if (mat2) {
/* FLOAT/INT * MATRIX */
@@ -2656,18 +2654,18 @@ static PyObject *Matrix_imul(PyObject *m1, PyObject *m2)
if (mat1 && mat2) {
/* MATRIX *= MATRIX */
- if ((mat1->num_row != mat2->num_row) || (mat1->num_col != mat2->num_col)) {
+ if ((mat1->row_num != mat2->row_num) || (mat1->col_num != mat2->col_num)) {
PyErr_SetString(PyExc_ValueError,
"matrix1 *= matrix2: matrix1 number of rows/columns "
"and the matrix2 number of rows/columns must be the same");
return NULL;
}
- mul_vn_vn(mat1->matrix, mat2->matrix, mat1->num_col * mat1->num_row);
+ mul_vn_vn(mat1->matrix, mat2->matrix, mat1->col_num * mat1->row_num);
}
else if (mat1 && (((scalar = PyFloat_AsDouble(m2)) == -1.0f && PyErr_Occurred()) == 0)) {
/* MATRIX *= FLOAT/INT */
- mul_vn_fl(mat1->matrix, mat1->num_row * mat1->num_col, scalar);
+ mul_vn_fl(mat1->matrix, mat1->row_num * mat1->col_num, scalar);
}
else {
PyErr_Format(PyExc_TypeError,
@@ -2686,7 +2684,7 @@ static PyObject *Matrix_imul(PyObject *m1, PyObject *m2)
* matrix multiplication */
static PyObject *Matrix_matmul(PyObject *m1, PyObject *m2)
{
- int vec_size;
+ int vec_num;
MatrixObject *mat1 = NULL, *mat2 = NULL;
@@ -2709,24 +2707,24 @@ static PyObject *Matrix_matmul(PyObject *m1, PyObject *m2)
int col, row, item;
- if (mat1->num_col != mat2->num_row) {
+ if (mat1->col_num != mat2->row_num) {
PyErr_SetString(PyExc_ValueError,
"matrix1 * matrix2: matrix1 number of columns "
"and the matrix2 number of rows must be the same");
return NULL;
}
- for (col = 0; col < mat2->num_col; col++) {
- for (row = 0; row < mat1->num_row; row++) {
+ for (col = 0; col < mat2->col_num; col++) {
+ for (row = 0; row < mat1->row_num; row++) {
double dot = 0.0f;
- for (item = 0; item < mat1->num_col; item++) {
+ for (item = 0; item < mat1->col_num; item++) {
dot += (double)(MATRIX_ITEM(mat1, row, item) * MATRIX_ITEM(mat2, item, col));
}
- mat[(col * mat1->num_row) + row] = (float)dot;
+ mat[(col * mat1->row_num) + row] = (float)dot;
}
}
- return Matrix_CreatePyObject(mat, mat2->num_col, mat1->num_row, Py_TYPE(mat1));
+ return Matrix_CreatePyObject(mat, mat2->col_num, mat1->row_num, Py_TYPE(mat1));
}
if (mat1) {
/* MATRIX @ VECTOR */
@@ -2740,14 +2738,14 @@ static PyObject *Matrix_matmul(PyObject *m1, PyObject *m2)
return NULL;
}
- if (mat1->num_col == 4 && vec2->size == 3) {
- vec_size = 3;
+ if (mat1->col_num == 4 && vec2->vec_num == 3) {
+ vec_num = 3;
}
else {
- vec_size = mat1->num_row;
+ vec_num = mat1->row_num;
}
- return Vector_CreatePyObject(tvec, vec_size, Py_TYPE(m2));
+ return Vector_CreatePyObject(tvec, vec_num, Py_TYPE(m2));
}
}
@@ -2782,27 +2780,27 @@ static PyObject *Matrix_imatmul(PyObject *m1, PyObject *m2)
float mat[MATRIX_MAX_DIM * MATRIX_MAX_DIM];
int col, row, item;
- if (mat1->num_col != mat2->num_row) {
+ if (mat1->col_num != mat2->row_num) {
PyErr_SetString(PyExc_ValueError,
"matrix1 * matrix2: matrix1 number of columns "
"and the matrix2 number of rows must be the same");
return NULL;
}
- for (col = 0; col < mat2->num_col; col++) {
- for (row = 0; row < mat1->num_row; row++) {
+ for (col = 0; col < mat2->col_num; col++) {
+ for (row = 0; row < mat1->row_num; row++) {
double dot = 0.0f;
- for (item = 0; item < mat1->num_col; item++) {
+ for (item = 0; item < mat1->col_num; item++) {
dot += (double)(MATRIX_ITEM(mat1, row, item) * MATRIX_ITEM(mat2, item, col));
}
/* store in new matrix as overwriting original at this point will cause
* subsequent iterations to use incorrect values */
- mat[(col * mat1->num_row) + row] = (float)dot;
+ mat[(col * mat1->row_num) + row] = (float)dot;
}
}
/* copy matrix back */
- memcpy(mat1->matrix, mat, (mat1->num_row * mat1->num_col) * sizeof(float));
+ memcpy(mat1->matrix, mat, (mat1->row_num * mat1->col_num) * sizeof(float));
}
else {
PyErr_Format(PyExc_TypeError,
@@ -2841,14 +2839,14 @@ static PyObject *Matrix_subscript(MatrixObject *self, PyObject *item)
return NULL;
}
if (i < 0) {
- i += self->num_row;
+ i += self->row_num;
}
return Matrix_item_row(self, i);
}
if (PySlice_Check(item)) {
Py_ssize_t start, stop, step, slicelength;
- if (PySlice_GetIndicesEx(item, self->num_row, &start, &stop, &step, &slicelength) < 0) {
+ if (PySlice_GetIndicesEx(item, self->row_num, &start, &stop, &step, &slicelength) < 0) {
return NULL;
}
@@ -2876,14 +2874,14 @@ static int Matrix_ass_subscript(MatrixObject *self, PyObject *item, PyObject *va
return -1;
}
if (i < 0) {
- i += self->num_row;
+ i += self->row_num;
}
return Matrix_ass_item_row(self, i, value);
}
if (PySlice_Check(item)) {
Py_ssize_t start, stop, step, slicelength;
- if (PySlice_GetIndicesEx(item, self->num_row, &start, &stop, &step, &slicelength) < 0) {
+ if (PySlice_GetIndicesEx(item, self->row_num, &start, &stop, &step, &slicelength) < 0) {
return -1;
}
@@ -2955,7 +2953,7 @@ static PyObject *Matrix_translation_get(MatrixObject *self, void *UNUSED(closure
}
/* Must be 4x4 square matrix. */
- if (self->num_row != 4 || self->num_col != 4) {
+ if (self->row_num != 4 || self->col_num != 4) {
PyErr_SetString(PyExc_AttributeError,
"Matrix.translation: "
"inappropriate matrix size, must be 4x4");
@@ -2977,7 +2975,7 @@ static int Matrix_translation_set(MatrixObject *self, PyObject *value, void *UNU
}
/* Must be 4x4 square matrix. */
- if (self->num_row != 4 || self->num_col != 4) {
+ if (self->row_num != 4 || self->col_num != 4) {
PyErr_SetString(PyExc_AttributeError,
"Matrix.translation: "
"inappropriate matrix size, must be 4x4");
@@ -3021,7 +3019,7 @@ static PyObject *Matrix_median_scale_get(MatrixObject *self, void *UNUSED(closur
}
/* Must be 3-4 cols, 3-4 rows, square matrix. */
- if ((self->num_row < 3) || (self->num_col < 3)) {
+ if ((self->row_num < 3) || (self->col_num < 3)) {
PyErr_SetString(PyExc_AttributeError,
"Matrix.median_scale: "
"inappropriate matrix size, 3x3 minimum");
@@ -3043,10 +3041,10 @@ static PyObject *Matrix_is_negative_get(MatrixObject *self, void *UNUSED(closure
}
/* Must be 3-4 cols, 3-4 rows, square matrix. */
- if (self->num_row == 4 && self->num_col == 4) {
+ if (self->row_num == 4 && self->col_num == 4) {
return PyBool_FromLong(is_negative_m4((const float(*)[4])self->matrix));
}
- if (self->num_row == 3 && self->num_col == 3) {
+ if (self->row_num == 3 && self->col_num == 3) {
return PyBool_FromLong(is_negative_m3((const float(*)[3])self->matrix));
}
@@ -3065,10 +3063,10 @@ static PyObject *Matrix_is_orthogonal_get(MatrixObject *self, void *UNUSED(closu
}
/* Must be 3-4 cols, 3-4 rows, square matrix. */
- if (self->num_row == 4 && self->num_col == 4) {
+ if (self->row_num == 4 && self->col_num == 4) {
return PyBool_FromLong(is_orthonormal_m4((const float(*)[4])self->matrix));
}
- if (self->num_row == 3 && self->num_col == 3) {
+ if (self->row_num == 3 && self->col_num == 3) {
return PyBool_FromLong(is_orthonormal_m3((const float(*)[3])self->matrix));
}
@@ -3088,10 +3086,10 @@ static PyObject *Matrix_is_orthogonal_axis_vectors_get(MatrixObject *self, void
}
/* Must be 3-4 cols, 3-4 rows, square matrix. */
- if (self->num_row == 4 && self->num_col == 4) {
+ if (self->row_num == 4 && self->col_num == 4) {
return PyBool_FromLong(is_orthogonal_m4((const float(*)[4])self->matrix));
}
- if (self->num_row == 3 && self->num_col == 3) {
+ if (self->row_num == 3 && self->col_num == 3) {
return PyBool_FromLong(is_orthogonal_m3((const float(*)[3])self->matrix));
}
@@ -3271,22 +3269,22 @@ PyTypeObject matrix_Type = {
};
PyObject *Matrix_CreatePyObject(const float *mat,
- const ushort num_col,
- const ushort num_row,
+ const ushort col_num,
+ const ushort row_num,
PyTypeObject *base_type)
{
MatrixObject *self;
float *mat_alloc;
/* matrix objects can be any 2-4row x 2-4col matrix */
- if (num_col < 2 || num_col > 4 || num_row < 2 || num_row > 4) {
+ if (col_num < 2 || col_num > 4 || row_num < 2 || row_num > 4) {
PyErr_SetString(PyExc_RuntimeError,
"Matrix(): "
"row and column sizes must be between 2 and 4");
return NULL;
}
- mat_alloc = PyMem_Malloc(num_col * num_row * sizeof(float));
+ mat_alloc = PyMem_Malloc(col_num * row_num * sizeof(float));
if (UNLIKELY(mat_alloc == NULL)) {
PyErr_SetString(PyExc_MemoryError,
"Matrix(): "
@@ -3297,23 +3295,23 @@ PyObject *Matrix_CreatePyObject(const float *mat,
self = BASE_MATH_NEW(MatrixObject, matrix_Type, base_type);
if (self) {
self->matrix = mat_alloc;
- self->num_col = num_col;
- self->num_row = num_row;
+ self->col_num = col_num;
+ self->row_num = row_num;
/* init callbacks as NULL */
self->cb_user = NULL;
self->cb_type = self->cb_subtype = 0;
if (mat) { /* If a float array passed. */
- memcpy(self->matrix, mat, num_col * num_row * sizeof(float));
+ memcpy(self->matrix, mat, col_num * row_num * sizeof(float));
}
- else if (num_col == num_row) {
+ else if (col_num == row_num) {
/* or if no arguments are passed return identity matrix for square matrices */
matrix_identity_internal(self);
}
else {
/* otherwise zero everything */
- memset(self->matrix, 0, num_col * num_row * sizeof(float));
+ memset(self->matrix, 0, col_num * row_num * sizeof(float));
}
self->flag = BASE_MATH_FLAG_DEFAULT;
}
@@ -3325,14 +3323,14 @@ PyObject *Matrix_CreatePyObject(const float *mat,
}
PyObject *Matrix_CreatePyObject_wrap(float *mat,
- const ushort num_col,
- const ushort num_row,
+ const ushort col_num,
+ const ushort row_num,
PyTypeObject *base_type)
{
MatrixObject *self;
/* matrix objects can be any 2-4row x 2-4col matrix */
- if (num_col < 2 || num_col > 4 || num_row < 2 || num_row > 4) {
+ if (col_num < 2 || col_num > 4 || row_num < 2 || row_num > 4) {
PyErr_SetString(PyExc_RuntimeError,
"Matrix(): "
"row and column sizes must be between 2 and 4");
@@ -3341,8 +3339,8 @@ PyObject *Matrix_CreatePyObject_wrap(float *mat,
self = BASE_MATH_NEW(MatrixObject, matrix_Type, base_type);
if (self) {
- self->num_col = num_col;
- self->num_row = num_row;
+ self->col_num = col_num;
+ self->row_num = row_num;
/* init callbacks as NULL */
self->cb_user = NULL;
@@ -3355,9 +3353,9 @@ PyObject *Matrix_CreatePyObject_wrap(float *mat,
}
PyObject *Matrix_CreatePyObject_cb(
- PyObject *cb_user, const ushort num_col, const ushort num_row, uchar cb_type, uchar cb_subtype)
+ PyObject *cb_user, const ushort col_num, const ushort row_num, uchar cb_type, uchar cb_subtype)
{
- MatrixObject *self = (MatrixObject *)Matrix_CreatePyObject(NULL, num_col, num_row, NULL);
+ MatrixObject *self = (MatrixObject *)Matrix_CreatePyObject(NULL, col_num, row_num, NULL);
if (self) {
Py_INCREF(cb_user);
self->cb_user = cb_user;
@@ -3369,12 +3367,12 @@ PyObject *Matrix_CreatePyObject_cb(
}
PyObject *Matrix_CreatePyObject_alloc(float *mat,
- const ushort num_col,
- const ushort num_row,
+ const ushort col_num,
+ const ushort row_num,
PyTypeObject *base_type)
{
MatrixObject *self;
- self = (MatrixObject *)Matrix_CreatePyObject_wrap(mat, num_col, num_row, base_type);
+ self = (MatrixObject *)Matrix_CreatePyObject_wrap(mat, col_num, row_num, base_type);
if (self) {
self->flag &= ~BASE_MATH_FLAG_IS_WRAP;
}
@@ -3419,7 +3417,7 @@ int Matrix_Parse2x2(PyObject *o, void *p)
if (!Matrix_ParseCheck(pymat)) {
return 0;
}
- if ((pymat->num_col != 2) || (pymat->num_row != 2)) {
+ if ((pymat->col_num != 2) || (pymat->row_num != 2)) {
PyErr_SetString(PyExc_ValueError, "matrix must be 2x2");
return 0;
}
@@ -3436,7 +3434,7 @@ int Matrix_Parse3x3(PyObject *o, void *p)
if (!Matrix_ParseCheck(pymat)) {
return 0;
}
- if ((pymat->num_col != 3) || (pymat->num_row != 3)) {
+ if ((pymat->col_num != 3) || (pymat->row_num != 3)) {
PyErr_SetString(PyExc_ValueError, "matrix must be 3x3");
return 0;
}
@@ -3453,7 +3451,7 @@ int Matrix_Parse4x4(PyObject *o, void *p)
if (!Matrix_ParseCheck(pymat)) {
return 0;
}
- if ((pymat->num_col != 4) || (pymat->num_row != 4)) {
+ if ((pymat->col_num != 4) || (pymat->row_num != 4)) {
PyErr_SetString(PyExc_ValueError, "matrix must be 4x4");
return 0;
}
@@ -3497,7 +3495,7 @@ static void MatrixAccess_dealloc(MatrixAccessObject *self)
static int MatrixAccess_len(MatrixAccessObject *self)
{
- return (self->type == MAT_ACCESS_ROW) ? self->matrix_user->num_row : self->matrix_user->num_col;
+ return (self->type == MAT_ACCESS_ROW) ? self->matrix_user->row_num : self->matrix_user->col_num;
}
static PyObject *MatrixAccess_slice(MatrixAccessObject *self, int begin, int end)
@@ -3511,11 +3509,11 @@ static PyObject *MatrixAccess_slice(MatrixAccessObject *self, int begin, int end
PyObject *(*Matrix_item_new)(MatrixObject *, int);
if (self->type == MAT_ACCESS_ROW) {
- matrix_access_len = matrix_user->num_row;
+ matrix_access_len = matrix_user->row_num;
Matrix_item_new = Matrix_item_row;
}
else { /* MAT_ACCESS_ROW */
- matrix_access_len = matrix_user->num_col;
+ matrix_access_len = matrix_user->col_num;
Matrix_item_new = Matrix_item_col;
}
@@ -3546,13 +3544,13 @@ static PyObject *MatrixAccess_subscript(MatrixAccessObject *self, PyObject *item
}
if (self->type == MAT_ACCESS_ROW) {
if (i < 0) {
- i += matrix_user->num_row;
+ i += matrix_user->row_num;
}
return Matrix_item_row(matrix_user, i);
}
/* MAT_ACCESS_ROW */
if (i < 0) {
- i += matrix_user->num_col;
+ i += matrix_user->col_num;
}
return Matrix_item_col(matrix_user, i);
}
@@ -3592,13 +3590,13 @@ static int MatrixAccess_ass_subscript(MatrixAccessObject *self, PyObject *item,
if (self->type == MAT_ACCESS_ROW) {
if (i < 0) {
- i += matrix_user->num_row;
+ i += matrix_user->row_num;
}
return Matrix_ass_item_row(matrix_user, i, value);
}
/* MAT_ACCESS_ROW */
if (i < 0) {
- i += matrix_user->num_col;
+ i += matrix_user->col_num;
}
return Matrix_ass_item_col(matrix_user, i, value);
}
diff --git a/source/blender/python/mathutils/mathutils_Matrix.h b/source/blender/python/mathutils/mathutils_Matrix.h
index 6dd1640b3bf..bc596ce6ac8 100644
--- a/source/blender/python/mathutils/mathutils_Matrix.h
+++ b/source/blender/python/mathutils/mathutils_Matrix.h
@@ -20,14 +20,14 @@ typedef unsigned short ushort;
#ifdef DEBUG
# define MATRIX_ITEM_ASSERT(_mat, _row, _col) \
- (BLI_assert(_row < (_mat)->num_row && _col < (_mat)->num_col))
+ (BLI_assert(_row < (_mat)->row_num && _col < (_mat)->col_num))
#else
# define MATRIX_ITEM_ASSERT(_mat, _row, _col) (void)0
#endif
#define MATRIX_ITEM_INDEX_NUMROW(_totrow, _row, _col) (((_totrow) * (_col)) + (_row))
#define MATRIX_ITEM_INDEX(_mat, _row, _col) \
- (MATRIX_ITEM_ASSERT(_mat, _row, _col), (((_mat)->num_row * (_col)) + (_row)))
+ (MATRIX_ITEM_ASSERT(_mat, _row, _col), (((_mat)->row_num * (_col)) + (_row)))
#define MATRIX_ITEM_PTR(_mat, _row, _col) ((_mat)->matrix + MATRIX_ITEM_INDEX(_mat, _row, _col))
#define MATRIX_ITEM(_mat, _row, _col) ((_mat)->matrix[MATRIX_ITEM_INDEX(_mat, _row, _col)])
@@ -36,8 +36,8 @@ typedef unsigned short ushort;
typedef struct {
BASE_MATH_MEMBERS(matrix);
- ushort num_col;
- ushort num_row;
+ ushort col_num;
+ ushort row_num;
} MatrixObject;
/* struct data contains a pointer to the actual data that the
@@ -47,17 +47,17 @@ typedef struct {
/* prototypes */
PyObject *Matrix_CreatePyObject(const float *mat,
- ushort num_col,
- ushort num_row,
+ ushort col_num,
+ ushort row_num,
PyTypeObject *base_type) ATTR_WARN_UNUSED_RESULT;
PyObject *Matrix_CreatePyObject_wrap(float *mat,
- ushort num_col,
- ushort num_row,
+ ushort col_num,
+ ushort row_num,
PyTypeObject *base_type) ATTR_WARN_UNUSED_RESULT
ATTR_NONNULL(1);
PyObject *Matrix_CreatePyObject_cb(PyObject *user,
- unsigned short num_col,
- unsigned short num_row,
+ unsigned short col_num,
+ unsigned short row_num,
unsigned char cb_type,
unsigned char cb_subtype) ATTR_WARN_UNUSED_RESULT;
@@ -65,8 +65,8 @@ PyObject *Matrix_CreatePyObject_cb(PyObject *user,
* \param mat: Initialized matrix value to use in-place, allocated with #PyMem_Malloc
*/
PyObject *Matrix_CreatePyObject_alloc(float *mat,
- ushort num_col,
- ushort num_row,
+ ushort col_num,
+ ushort row_num,
PyTypeObject *base_type) ATTR_WARN_UNUSED_RESULT;
/* PyArg_ParseTuple's "O&" formatting helpers. */
diff --git a/source/blender/python/mathutils/mathutils_Quaternion.c b/source/blender/python/mathutils/mathutils_Quaternion.c
index f0ba125e768..7b51154f0d0 100644
--- a/source/blender/python/mathutils/mathutils_Quaternion.c
+++ b/source/blender/python/mathutils/mathutils_Quaternion.c
@@ -1035,7 +1035,7 @@ static PyObject *Quaternion_matmul(PyObject *q1, PyObject *q2)
VectorObject *vec2 = (VectorObject *)q2;
float tvec[3];
- if (vec2->size != 3) {
+ if (vec2->vec_num != 3) {
PyErr_SetString(PyExc_ValueError,
"Vector multiplication: "
"only 3D vector rotations (with quats) "
diff --git a/source/blender/python/mathutils/mathutils_Vector.c b/source/blender/python/mathutils/mathutils_Vector.c
index 080a1e7fbdd..ffeb121b3d1 100644
--- a/source/blender/python/mathutils/mathutils_Vector.c
+++ b/source/blender/python/mathutils/mathutils_Vector.c
@@ -45,7 +45,7 @@ static int row_vector_multiplication(float r_vec[MAX_DIMENSIONS],
static PyObject *Vector_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
float *vec = NULL;
- int size = 3; /* default to a 3D vector */
+ int vec_num = 3; /* default to a 3D vector */
if (kwds && PyDict_Size(kwds)) {
PyErr_SetString(PyExc_TypeError,
@@ -56,7 +56,7 @@ static PyObject *Vector_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
switch (PyTuple_GET_SIZE(args)) {
case 0:
- vec = PyMem_Malloc(size * sizeof(float));
+ vec = PyMem_Malloc(vec_num * sizeof(float));
if (vec == NULL) {
PyErr_SetString(PyExc_MemoryError,
@@ -65,10 +65,10 @@ static PyObject *Vector_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
return NULL;
}
- copy_vn_fl(vec, size, 0.0f);
+ copy_vn_fl(vec, vec_num, 0.0f);
break;
case 1:
- if ((size = mathutils_array_parse_alloc(
+ if ((vec_num = mathutils_array_parse_alloc(
&vec, 2, PyTuple_GET_ITEM(args, 0), "mathutils.Vector()")) == -1) {
return NULL;
}
@@ -79,7 +79,7 @@ static PyObject *Vector_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
"more than a single arg given");
return NULL;
}
- return Vector_CreatePyObject_alloc(vec, size, type);
+ return Vector_CreatePyObject_alloc(vec, vec_num, type);
}
static PyObject *vec__apply_to_copy(PyObject *(*vec_func)(VectorObject *), VectorObject *self)
@@ -108,19 +108,19 @@ PyDoc_STRVAR(C_Vector_Fill_doc,
static PyObject *C_Vector_Fill(PyObject *cls, PyObject *args)
{
float *vec;
- int size;
+ int vec_num;
float fill = 0.0f;
- if (!PyArg_ParseTuple(args, "i|f:Vector.Fill", &size, &fill)) {
+ if (!PyArg_ParseTuple(args, "i|f:Vector.Fill", &vec_num, &fill)) {
return NULL;
}
- if (size < 2) {
+ if (vec_num < 2) {
PyErr_SetString(PyExc_RuntimeError, "Vector(): invalid size");
return NULL;
}
- vec = PyMem_Malloc(size * sizeof(float));
+ vec = PyMem_Malloc(vec_num * sizeof(float));
if (vec == NULL) {
PyErr_SetString(PyExc_MemoryError,
@@ -129,9 +129,9 @@ static PyObject *C_Vector_Fill(PyObject *cls, PyObject *args)
return NULL;
}
- copy_vn_fl(vec, size, fill);
+ copy_vn_fl(vec, vec_num, fill);
- return Vector_CreatePyObject_alloc(vec, size, (PyTypeObject *)cls);
+ return Vector_CreatePyObject_alloc(vec, vec_num, (PyTypeObject *)cls);
}
PyDoc_STRVAR(C_Vector_Range_doc,
@@ -148,7 +148,7 @@ PyDoc_STRVAR(C_Vector_Range_doc,
static PyObject *C_Vector_Range(PyObject *cls, PyObject *args)
{
float *vec;
- int stop, size;
+ int stop, vec_num;
int start = 0;
int step = 1;
@@ -158,7 +158,7 @@ static PyObject *C_Vector_Range(PyObject *cls, PyObject *args)
switch (PyTuple_GET_SIZE(args)) {
case 1:
- size = start;
+ vec_num = start;
start = 0;
break;
case 2:
@@ -169,7 +169,7 @@ static PyObject *C_Vector_Range(PyObject *cls, PyObject *args)
return NULL;
}
- size = stop - start;
+ vec_num = stop - start;
break;
default:
if (start >= stop) {
@@ -179,23 +179,23 @@ static PyObject *C_Vector_Range(PyObject *cls, PyObject *args)
return NULL;
}
- size = (stop - start);
+ vec_num = (stop - start);
- if ((size % step) != 0) {
- size += step;
+ if ((vec_num % step) != 0) {
+ vec_num += step;
}
- size /= step;
+ vec_num /= step;
break;
}
- if (size < 2) {
+ if (vec_num < 2) {
PyErr_SetString(PyExc_RuntimeError, "Vector(): invalid size");
return NULL;
}
- vec = PyMem_Malloc(size * sizeof(float));
+ vec = PyMem_Malloc(vec_num * sizeof(float));
if (vec == NULL) {
PyErr_SetString(PyExc_MemoryError,
@@ -204,9 +204,9 @@ static PyObject *C_Vector_Range(PyObject *cls, PyObject *args)
return NULL;
}
- range_vn_fl(vec, size, (float)start, (float)step);
+ range_vn_fl(vec, vec_num, (float)start, (float)step);
- return Vector_CreatePyObject_alloc(vec, size, (PyTypeObject *)cls);
+ return Vector_CreatePyObject_alloc(vec, vec_num, (PyTypeObject *)cls);
}
PyDoc_STRVAR(C_Vector_Linspace_doc,
@@ -224,21 +224,21 @@ PyDoc_STRVAR(C_Vector_Linspace_doc,
static PyObject *C_Vector_Linspace(PyObject *cls, PyObject *args)
{
float *vec;
- int size;
+ int vec_num;
float start, end, step;
- if (!PyArg_ParseTuple(args, "ffi:Vector.Linspace", &start, &end, &size)) {
+ if (!PyArg_ParseTuple(args, "ffi:Vector.Linspace", &start, &end, &vec_num)) {
return NULL;
}
- if (size < 2) {
+ if (vec_num < 2) {
PyErr_SetString(PyExc_RuntimeError, "Vector.Linspace(): invalid size");
return NULL;
}
- step = (end - start) / (float)(size - 1);
+ step = (end - start) / (float)(vec_num - 1);
- vec = PyMem_Malloc(size * sizeof(float));
+ vec = PyMem_Malloc(vec_num * sizeof(float));
if (vec == NULL) {
PyErr_SetString(PyExc_MemoryError,
@@ -247,9 +247,9 @@ static PyObject *C_Vector_Linspace(PyObject *cls, PyObject *args)
return NULL;
}
- range_vn_fl(vec, size, start, step);
+ range_vn_fl(vec, vec_num, start, step);
- return Vector_CreatePyObject_alloc(vec, size, (PyTypeObject *)cls);
+ return Vector_CreatePyObject_alloc(vec, vec_num, (PyTypeObject *)cls);
}
PyDoc_STRVAR(
@@ -266,20 +266,20 @@ static PyObject *C_Vector_Repeat(PyObject *cls, PyObject *args)
{
float *vec;
float *iter_vec = NULL;
- int i, size, value_size;
+ int i, vec_num, value_num;
PyObject *value;
- if (!PyArg_ParseTuple(args, "Oi:Vector.Repeat", &value, &size)) {
+ if (!PyArg_ParseTuple(args, "Oi:Vector.Repeat", &value, &vec_num)) {
return NULL;
}
- if (size < 2) {
- PyErr_SetString(PyExc_RuntimeError, "Vector.Repeat(): invalid size");
+ if (vec_num < 2) {
+ PyErr_SetString(PyExc_RuntimeError, "Vector.Repeat(): invalid vec_num");
return NULL;
}
- if ((value_size = mathutils_array_parse_alloc(
- &iter_vec, 2, value, "Vector.Repeat(vector, size), invalid 'vector' arg")) == -1) {
+ if ((value_num = mathutils_array_parse_alloc(
+ &iter_vec, 2, value, "Vector.Repeat(vector, vec_num), invalid 'vector' arg")) == -1) {
return NULL;
}
@@ -290,7 +290,7 @@ static PyObject *C_Vector_Repeat(PyObject *cls, PyObject *args)
return NULL;
}
- vec = PyMem_Malloc(size * sizeof(float));
+ vec = PyMem_Malloc(vec_num * sizeof(float));
if (vec == NULL) {
PyMem_Free(iter_vec);
@@ -301,14 +301,14 @@ static PyObject *C_Vector_Repeat(PyObject *cls, PyObject *args)
}
i = 0;
- while (i < size) {
- vec[i] = iter_vec[i % value_size];
+ while (i < vec_num) {
+ vec[i] = iter_vec[i % value_num];
i++;
}
PyMem_Free(iter_vec);
- return Vector_CreatePyObject_alloc(vec, size, (PyTypeObject *)cls);
+ return Vector_CreatePyObject_alloc(vec, vec_num, (PyTypeObject *)cls);
}
/*-----------------------------METHODS---------------------------- */
@@ -322,7 +322,7 @@ static PyObject *Vector_zero(VectorObject *self)
return NULL;
}
- copy_vn_fl(self->vec, self->size, 0.0f);
+ copy_vn_fl(self->vec, self->vec_num, 0.0f);
if (BaseMath_WriteCallback(self) == -1) {
return NULL;
@@ -342,12 +342,12 @@ PyDoc_STRVAR(Vector_normalize_doc,
" however 4D Vectors w axis is left untouched.\n");
static PyObject *Vector_normalize(VectorObject *self)
{
- const int size = (self->size == 4 ? 3 : self->size);
+ const int vec_num = (self->vec_num == 4 ? 3 : self->vec_num);
if (BaseMath_ReadCallback_ForWrite(self) == -1) {
return NULL;
}
- normalize_vn(self->vec, size);
+ normalize_vn(self->vec, vec_num);
(void)BaseMath_WriteCallback(self);
Py_RETURN_NONE;
@@ -370,7 +370,7 @@ PyDoc_STRVAR(Vector_resize_doc,
" Resize the vector to have size number of elements.\n");
static PyObject *Vector_resize(VectorObject *self, PyObject *value)
{
- int size;
+ int vec_num;
if (self->flag & BASE_MATH_FLAG_IS_WRAP) {
PyErr_SetString(PyExc_TypeError,
@@ -385,19 +385,19 @@ static PyObject *Vector_resize(VectorObject *self, PyObject *value)
return NULL;
}
- if ((size = PyC_Long_AsI32(value)) == -1) {
+ if ((vec_num = PyC_Long_AsI32(value)) == -1) {
PyErr_SetString(PyExc_TypeError,
"Vector.resize(size): "
"expected size argument to be an integer");
return NULL;
}
- if (size < 2) {
+ if (vec_num < 2) {
PyErr_SetString(PyExc_RuntimeError, "Vector.resize(): invalid size");
return NULL;
}
- self->vec = PyMem_Realloc(self->vec, (size * sizeof(float)));
+ self->vec = PyMem_Realloc(self->vec, (vec_num * sizeof(float)));
if (self->vec == NULL) {
PyErr_SetString(PyExc_MemoryError,
"Vector.resize(): "
@@ -406,11 +406,11 @@ static PyObject *Vector_resize(VectorObject *self, PyObject *value)
}
/* If the vector has increased in length, set all new elements to 0.0f */
- if (size > self->size) {
- copy_vn_fl(self->vec + self->size, size - self->size, 0.0f);
+ if (vec_num > self->vec_num) {
+ copy_vn_fl(self->vec + self->vec_num, vec_num - self->vec_num, 0.0f);
}
- self->size = size;
+ self->vec_num = vec_num;
Py_RETURN_NONE;
}
@@ -423,19 +423,19 @@ PyDoc_STRVAR(Vector_resized_doc,
" :rtype: :class:`Vector`\n");
static PyObject *Vector_resized(VectorObject *self, PyObject *value)
{
- int size;
+ int vec_num;
float *vec;
- if ((size = PyLong_AsLong(value)) == -1) {
+ if ((vec_num = PyLong_AsLong(value)) == -1) {
return NULL;
}
- if (size < 2) {
+ if (vec_num < 2) {
PyErr_SetString(PyExc_RuntimeError, "Vector.resized(): invalid size");
return NULL;
}
- vec = PyMem_Malloc(size * sizeof(float));
+ vec = PyMem_Malloc(vec_num * sizeof(float));
if (vec == NULL) {
PyErr_SetString(PyExc_MemoryError,
@@ -444,10 +444,10 @@ static PyObject *Vector_resized(VectorObject *self, PyObject *value)
return NULL;
}
- copy_vn_fl(vec, size, 0.0f);
- memcpy(vec, self->vec, self->size * sizeof(float));
+ copy_vn_fl(vec, vec_num, 0.0f);
+ memcpy(vec, self->vec, self->vec_num * sizeof(float));
- return Vector_CreatePyObject_alloc(vec, size, NULL);
+ return Vector_CreatePyObject_alloc(vec, vec_num, NULL);
}
PyDoc_STRVAR(Vector_resize_2d_doc,
@@ -477,7 +477,7 @@ static PyObject *Vector_resize_2d(VectorObject *self)
return NULL;
}
- self->size = 2;
+ self->vec_num = 2;
Py_RETURN_NONE;
}
@@ -508,11 +508,11 @@ static PyObject *Vector_resize_3d(VectorObject *self)
return NULL;
}
- if (self->size == 2) {
+ if (self->vec_num == 2) {
self->vec[2] = 0.0f;
}
- self->size = 3;
+ self->vec_num = 3;
Py_RETURN_NONE;
}
@@ -543,14 +543,14 @@ static PyObject *Vector_resize_4d(VectorObject *self)
return NULL;
}
- if (self->size == 2) {
+ if (self->vec_num == 2) {
self->vec[2] = 0.0f;
self->vec[3] = 1.0f;
}
- else if (self->size == 3) {
+ else if (self->vec_num == 3) {
self->vec[3] = 1.0f;
}
- self->size = 4;
+ self->vec_num = 4;
Py_RETURN_NONE;
}
PyDoc_STRVAR(Vector_to_2d_doc,
@@ -583,7 +583,7 @@ static PyObject *Vector_to_3d(VectorObject *self)
return NULL;
}
- memcpy(tvec, self->vec, sizeof(float) * MIN2(self->size, 3));
+ memcpy(tvec, self->vec, sizeof(float) * MIN2(self->vec_num, 3));
return Vector_CreatePyObject(tvec, 3, Py_TYPE(self));
}
PyDoc_STRVAR(Vector_to_4d_doc,
@@ -601,7 +601,7 @@ static PyObject *Vector_to_4d(VectorObject *self)
return NULL;
}
- memcpy(tvec, self->vec, sizeof(float) * MIN2(self->size, 4));
+ memcpy(tvec, self->vec, sizeof(float) * MIN2(self->vec_num, 4));
return Vector_CreatePyObject(tvec, 4, Py_TYPE(self));
}
@@ -620,15 +620,15 @@ static PyObject *Vector_to_tuple_ex(VectorObject *self, int ndigits)
PyObject *ret;
int i;
- ret = PyTuple_New(self->size);
+ ret = PyTuple_New(self->vec_num);
if (ndigits >= 0) {
- for (i = 0; i < self->size; i++) {
+ for (i = 0; i < self->vec_num; i++) {
PyTuple_SET_ITEM(ret, i, PyFloat_FromDouble(double_round((double)self->vec[i], ndigits)));
}
}
else {
- for (i = 0; i < self->size; i++) {
+ for (i = 0; i < self->vec_num; i++) {
PyTuple_SET_ITEM(ret, i, PyFloat_FromDouble(self->vec[i]));
}
}
@@ -684,7 +684,7 @@ static PyObject *Vector_to_track_quat(VectorObject *self, PyObject *args)
return NULL;
}
- if (self->size != 3) {
+ if (self->vec_num != 3) {
PyErr_SetString(PyExc_TypeError,
"Vector.to_track_quat(): "
"only for 3D vectors");
@@ -795,7 +795,7 @@ static PyObject *Vector_orthogonal(VectorObject *self)
{
float vec[3];
- if (self->size > 3) {
+ if (self->vec_num > 3) {
PyErr_SetString(PyExc_TypeError,
"Vector.orthogonal(): "
"Vector must be 3D or 2D");
@@ -806,14 +806,14 @@ static PyObject *Vector_orthogonal(VectorObject *self)
return NULL;
}
- if (self->size == 3) {
+ if (self->vec_num == 3) {
ortho_v3_v3(vec, self->vec);
}
else {
ortho_v2_v2(vec, self->vec);
}
- return Vector_CreatePyObject(vec, self->size, Py_TYPE(self));
+ return Vector_CreatePyObject(vec, self->vec_num, Py_TYPE(self));
}
/**
@@ -833,7 +833,7 @@ PyDoc_STRVAR(Vector_reflect_doc,
" :rtype: :class:`Vector`\n");
static PyObject *Vector_reflect(VectorObject *self, PyObject *value)
{
- int value_size;
+ int value_num;
float mirror[3], vec[3];
float reflect[3] = {0.0f};
float tvec[MAX_DIMENSIONS];
@@ -842,28 +842,28 @@ static PyObject *Vector_reflect(VectorObject *self, PyObject *value)
return NULL;
}
- if ((value_size = mathutils_array_parse(
+ if ((value_num = mathutils_array_parse(
tvec, 2, 4, value, "Vector.reflect(other), invalid 'other' arg")) == -1) {
return NULL;
}
- if (self->size < 2 || self->size > 4) {
+ if (self->vec_num < 2 || self->vec_num > 4) {
PyErr_SetString(PyExc_ValueError, "Vector must be 2D, 3D or 4D");
return NULL;
}
mirror[0] = tvec[0];
mirror[1] = tvec[1];
- mirror[2] = (value_size > 2) ? tvec[2] : 0.0f;
+ mirror[2] = (value_num > 2) ? tvec[2] : 0.0f;
vec[0] = self->vec[0];
vec[1] = self->vec[1];
- vec[2] = (value_size > 2) ? self->vec[2] : 0.0f;
+ vec[2] = (value_num > 2) ? self->vec[2] : 0.0f;
normalize_v3(mirror);
reflect_v3_v3v3(reflect, vec, mirror);
- return Vector_CreatePyObject(reflect, self->size, Py_TYPE(self));
+ return Vector_CreatePyObject(reflect, self->vec_num, Py_TYPE(self));
}
PyDoc_STRVAR(Vector_cross_doc,
@@ -886,17 +886,18 @@ static PyObject *Vector_cross(VectorObject *self, PyObject *value)
return NULL;
}
- if (self->size > 3) {
+ if (self->vec_num > 3) {
PyErr_SetString(PyExc_ValueError, "Vector must be 2D or 3D");
return NULL;
}
if (mathutils_array_parse(
- tvec, self->size, self->size, value, "Vector.cross(other), invalid 'other' arg") == -1) {
+ tvec, self->vec_num, self->vec_num, value, "Vector.cross(other), invalid 'other' arg") ==
+ -1) {
return NULL;
}
- if (self->size == 3) {
+ if (self->vec_num == 3) {
ret = Vector_CreatePyObject(NULL, 3, Py_TYPE(self));
cross_v3_v3v3(((VectorObject *)ret)->vec, self->vec, tvec);
}
@@ -926,11 +927,11 @@ static PyObject *Vector_dot(VectorObject *self, PyObject *value)
}
if (mathutils_array_parse_alloc(
- &tvec, self->size, value, "Vector.dot(other), invalid 'other' arg") == -1) {
+ &tvec, self->vec_num, value, "Vector.dot(other), invalid 'other' arg") == -1) {
return NULL;
}
- ret = PyFloat_FromDouble(dot_vn_vn(self->vec, tvec, self->size));
+ ret = PyFloat_FromDouble(dot_vn_vn(self->vec, tvec, self->vec_num));
PyMem_Free(tvec);
return ret;
}
@@ -950,7 +951,7 @@ PyDoc_STRVAR(
" :rtype: float\n");
static PyObject *Vector_angle(VectorObject *self, PyObject *args)
{
- const int size = MIN2(self->size, 3); /* 4D angle makes no sense */
+ const int vec_num = MIN2(self->vec_num, 3); /* 4D angle makes no sense */
float tvec[MAX_DIMENSIONS];
PyObject *value;
double dot = 0.0f, dot_self = 0.0f, dot_other = 0.0f;
@@ -968,16 +969,17 @@ static PyObject *Vector_angle(VectorObject *self, PyObject *args)
/* don't use clamped size, rule of thumb is vector sizes must match,
* even though n this case 'w' is ignored */
if (mathutils_array_parse(
- tvec, self->size, self->size, value, "Vector.angle(other), invalid 'other' arg") == -1) {
+ tvec, self->vec_num, self->vec_num, value, "Vector.angle(other), invalid 'other' arg") ==
+ -1) {
return NULL;
}
- if (self->size > 4) {
+ if (self->vec_num > 4) {
PyErr_SetString(PyExc_ValueError, "Vector must be 2D, 3D or 4D");
return NULL;
}
- for (x = 0; x < size; x++) {
+ for (x = 0; x < vec_num; x++) {
dot_self += (double)self->vec[x] * (double)self->vec[x];
dot_other += (double)tvec[x] * (double)tvec[x];
dot += (double)self->vec[x] * (double)tvec[x];
@@ -1032,7 +1034,7 @@ static PyObject *Vector_angle_signed(VectorObject *self, PyObject *args)
return NULL;
}
- if (self->size != 2) {
+ if (self->vec_num != 2) {
PyErr_SetString(PyExc_ValueError, "Vector must be 2D");
return NULL;
}
@@ -1069,7 +1071,7 @@ static PyObject *Vector_rotation_difference(VectorObject *self, PyObject *value)
{
float quat[4], vec_a[3], vec_b[3];
- if (self->size < 3 || self->size > 4) {
+ if (self->vec_num < 3 || self->vec_num > 4) {
PyErr_SetString(PyExc_ValueError,
"vec.difference(value): "
"expects both vectors to be size 3 or 4");
@@ -1105,7 +1107,7 @@ PyDoc_STRVAR(Vector_project_doc,
" :rtype: :class:`Vector`\n");
static PyObject *Vector_project(VectorObject *self, PyObject *value)
{
- const int size = self->size;
+ const int vec_num = self->vec_num;
float *tvec;
double dot = 0.0f, dot2 = 0.0f;
int x;
@@ -1115,21 +1117,21 @@ static PyObject *Vector_project(VectorObject *self, PyObject *value)
}
if (mathutils_array_parse_alloc(
- &tvec, size, value, "Vector.project(other), invalid 'other' arg") == -1) {
+ &tvec, vec_num, value, "Vector.project(other), invalid 'other' arg") == -1) {
return NULL;
}
/* get dot products */
- for (x = 0; x < size; x++) {
+ for (x = 0; x < vec_num; x++) {
dot += (double)(self->vec[x] * tvec[x]);
dot2 += (double)(tvec[x] * tvec[x]);
}
/* projection */
dot /= dot2;
- for (x = 0; x < size; x++) {
+ for (x = 0; x < vec_num; x++) {
tvec[x] *= (float)dot;
}
- return Vector_CreatePyObject_alloc(tvec, size, Py_TYPE(self));
+ return Vector_CreatePyObject_alloc(tvec, vec_num, Py_TYPE(self));
}
PyDoc_STRVAR(Vector_lerp_doc,
@@ -1145,7 +1147,7 @@ PyDoc_STRVAR(Vector_lerp_doc,
" :rtype: :class:`Vector`\n");
static PyObject *Vector_lerp(VectorObject *self, PyObject *args)
{
- const int size = self->size;
+ const int vec_num = self->vec_num;
PyObject *value = NULL;
float fac;
float *tvec;
@@ -1158,14 +1160,14 @@ static PyObject *Vector_lerp(VectorObject *self, PyObject *args)
return NULL;
}
- if (mathutils_array_parse_alloc(&tvec, size, value, "Vector.lerp(other), invalid 'other' arg") ==
- -1) {
+ if (mathutils_array_parse_alloc(
+ &tvec, vec_num, value, "Vector.lerp(other), invalid 'other' arg") == -1) {
return NULL;
}
- interp_vn_vn(tvec, self->vec, 1.0f - fac, size);
+ interp_vn_vn(tvec, self->vec, 1.0f - fac, vec_num);
- return Vector_CreatePyObject_alloc(tvec, size, Py_TYPE(self));
+ return Vector_CreatePyObject_alloc(tvec, vec_num, Py_TYPE(self));
}
PyDoc_STRVAR(Vector_slerp_doc,
@@ -1185,7 +1187,7 @@ PyDoc_STRVAR(Vector_slerp_doc,
" :rtype: :class:`Vector`\n");
static PyObject *Vector_slerp(VectorObject *self, PyObject *args)
{
- const int size = self->size;
+ const int vec_num = self->vec_num;
PyObject *value = NULL;
float fac, cosom, w[2];
float self_vec[3], other_vec[3], ret_vec[3];
@@ -1201,18 +1203,18 @@ static PyObject *Vector_slerp(VectorObject *self, PyObject *args)
return NULL;
}
- if (self->size > 3) {
+ if (self->vec_num > 3) {
PyErr_SetString(PyExc_ValueError, "Vector must be 2D or 3D");
return NULL;
}
if (mathutils_array_parse(
- other_vec, size, size, value, "Vector.slerp(other), invalid 'other' arg") == -1) {
+ other_vec, vec_num, vec_num, value, "Vector.slerp(other), invalid 'other' arg") == -1) {
return NULL;
}
- self_len_sq = normalize_vn_vn(self_vec, self->vec, size);
- other_len_sq = normalize_vn(other_vec, size);
+ self_len_sq = normalize_vn_vn(self_vec, self->vec, vec_num);
+ other_len_sq = normalize_vn(other_vec, vec_num);
/* use fallbacks for zero length vectors */
if (UNLIKELY((self_len_sq < FLT_EPSILON) || (other_len_sq < FLT_EPSILON))) {
@@ -1229,7 +1231,7 @@ static PyObject *Vector_slerp(VectorObject *self, PyObject *args)
}
/* We have sane state, execute slerp */
- cosom = (float)dot_vn_vn(self_vec, other_vec, size);
+ cosom = (float)dot_vn_vn(self_vec, other_vec, vec_num);
/* direct opposite, can't slerp */
if (UNLIKELY(cosom < (-1.0f + FLT_EPSILON))) {
@@ -1247,11 +1249,11 @@ static PyObject *Vector_slerp(VectorObject *self, PyObject *args)
interp_dot_slerp(fac, cosom, w);
- for (x = 0; x < size; x++) {
+ for (x = 0; x < vec_num; x++) {
ret_vec[x] = (w[0] * self_vec[x]) + (w[1] * other_vec[x]);
}
- return Vector_CreatePyObject(ret_vec, size, Py_TYPE(self));
+ return Vector_CreatePyObject(ret_vec, vec_num, Py_TYPE(self));
}
PyDoc_STRVAR(
@@ -1270,7 +1272,7 @@ static PyObject *Vector_rotate(VectorObject *self, PyObject *value)
return NULL;
}
- if (self->size == 2) {
+ if (self->vec_num == 2) {
/* Special case for 2D Vector with 2x2 matrix, so we avoid resizing it to a 3x3. */
float other_rmat[2][2];
MatrixObject *pymat;
@@ -1311,7 +1313,7 @@ static PyObject *Vector_copy(VectorObject *self)
return NULL;
}
- return Vector_CreatePyObject(self->vec, self->size, Py_TYPE(self));
+ return Vector_CreatePyObject(self->vec, self->vec_num, Py_TYPE(self));
}
static PyObject *Vector_deepcopy(VectorObject *self, PyObject *args)
{
@@ -1350,7 +1352,7 @@ static PyObject *Vector_str(VectorObject *self)
BLI_dynstr_append(ds, "<Vector (");
- for (i = 0; i < self->size; i++) {
+ for (i = 0; i < self->vec_num; i++) {
BLI_dynstr_appendf(ds, i ? ", %.4f" : "%.4f", self->vec[i]);
}
@@ -1364,21 +1366,21 @@ static PyObject *Vector_str(VectorObject *self)
/* sequence length len(vector) */
static int Vector_len(VectorObject *self)
{
- return self->size;
+ return self->vec_num;
}
/* sequence accessor (get): vector[index] */
static PyObject *vector_item_internal(VectorObject *self, int i, const bool is_attr)
{
if (i < 0) {
- i = self->size - i;
+ i = self->vec_num - i;
}
- if (i < 0 || i >= self->size) {
+ if (i < 0 || i >= self->vec_num) {
if (is_attr) {
PyErr_Format(PyExc_AttributeError,
"Vector.%c: unavailable on %dd vector",
*(((const char *)"xyzw") + i),
- self->size);
+ self->vec_num);
}
else {
PyErr_SetString(PyExc_IndexError, "vector[index]: out of range");
@@ -1415,15 +1417,15 @@ static int vector_ass_item_internal(VectorObject *self, int i, PyObject *value,
}
if (i < 0) {
- i = self->size - i;
+ i = self->vec_num - i;
}
- if (i < 0 || i >= self->size) {
+ if (i < 0 || i >= self->vec_num) {
if (is_attr) {
PyErr_Format(PyExc_AttributeError,
"Vector.%c = x: unavailable on %dd vector",
*(((const char *)"xyzw") + i),
- self->size);
+ self->vec_num);
}
else {
PyErr_SetString(PyExc_IndexError,
@@ -1455,11 +1457,11 @@ static PyObject *Vector_slice(VectorObject *self, int begin, int end)
return NULL;
}
- CLAMP(begin, 0, self->size);
+ CLAMP(begin, 0, self->vec_num);
if (end < 0) {
- end = self->size + end + 1;
+ end = self->vec_num + end + 1;
}
- CLAMP(end, 0, self->size);
+ CLAMP(end, 0, self->vec_num);
begin = MIN2(begin, end);
tuple = PyTuple_New(end - begin);
@@ -1472,19 +1474,19 @@ static PyObject *Vector_slice(VectorObject *self, int begin, int end)
/* sequence slice (set): vector[a:b] = value */
static int Vector_ass_slice(VectorObject *self, int begin, int end, PyObject *seq)
{
- int size = 0;
+ int vec_num = 0;
float *vec = NULL;
if (BaseMath_ReadCallback_ForWrite(self) == -1) {
return -1;
}
- CLAMP(begin, 0, self->size);
- CLAMP(end, 0, self->size);
+ CLAMP(begin, 0, self->vec_num);
+ CLAMP(end, 0, self->vec_num);
begin = MIN2(begin, end);
- size = (end - begin);
- if (mathutils_array_parse_alloc(&vec, size, seq, "vector[begin:end] = [...]") == -1) {
+ vec_num = (end - begin);
+ if (mathutils_array_parse_alloc(&vec, vec_num, seq, "vector[begin:end] = [...]") == -1) {
return -1;
}
@@ -1496,7 +1498,7 @@ static int Vector_ass_slice(VectorObject *self, int begin, int end, PyObject *se
}
/* Parsed well - now set in vector. */
- memcpy(self->vec + begin, vec, size * sizeof(float));
+ memcpy(self->vec + begin, vec, vec_num * sizeof(float));
PyMem_Free(vec);
@@ -1530,14 +1532,14 @@ static PyObject *Vector_add(PyObject *v1, PyObject *v2)
}
/* VECTOR + VECTOR. */
- if (vec1->size != vec2->size) {
+ if (vec1->vec_num != vec2->vec_num) {
PyErr_SetString(PyExc_AttributeError,
"Vector addition: "
"vectors must have the same dimensions for this operation");
return NULL;
}
- vec = PyMem_Malloc(vec1->size * sizeof(float));
+ vec = PyMem_Malloc(vec1->vec_num * sizeof(float));
if (vec == NULL) {
PyErr_SetString(PyExc_MemoryError,
"Vector(): "
@@ -1545,9 +1547,9 @@ static PyObject *Vector_add(PyObject *v1, PyObject *v2)
return NULL;
}
- add_vn_vnvn(vec, vec1->vec, vec2->vec, vec1->size);
+ add_vn_vnvn(vec, vec1->vec, vec2->vec, vec1->vec_num);
- return Vector_CreatePyObject_alloc(vec, vec1->size, Py_TYPE(v1));
+ return Vector_CreatePyObject_alloc(vec, vec1->vec_num, Py_TYPE(v1));
}
/* addition in-place: obj += obj */
@@ -1566,7 +1568,7 @@ static PyObject *Vector_iadd(PyObject *v1, PyObject *v2)
vec1 = (VectorObject *)v1;
vec2 = (VectorObject *)v2;
- if (vec1->size != vec2->size) {
+ if (vec1->vec_num != vec2->vec_num) {
PyErr_SetString(PyExc_AttributeError,
"Vector addition: "
"vectors must have the same dimensions for this operation");
@@ -1577,7 +1579,7 @@ static PyObject *Vector_iadd(PyObject *v1, PyObject *v2)
return NULL;
}
- add_vn_vn(vec1->vec, vec2->vec, vec1->size);
+ add_vn_vn(vec1->vec, vec2->vec, vec1->vec_num);
(void)BaseMath_WriteCallback(vec1);
Py_INCREF(v1);
@@ -1605,14 +1607,14 @@ static PyObject *Vector_sub(PyObject *v1, PyObject *v2)
return NULL;
}
- if (vec1->size != vec2->size) {
+ if (vec1->vec_num != vec2->vec_num) {
PyErr_SetString(PyExc_AttributeError,
"Vector subtraction: "
"vectors must have the same dimensions for this operation");
return NULL;
}
- vec = PyMem_Malloc(vec1->size * sizeof(float));
+ vec = PyMem_Malloc(vec1->vec_num * sizeof(float));
if (vec == NULL) {
PyErr_SetString(PyExc_MemoryError,
"Vector(): "
@@ -1620,9 +1622,9 @@ static PyObject *Vector_sub(PyObject *v1, PyObject *v2)
return NULL;
}
- sub_vn_vnvn(vec, vec1->vec, vec2->vec, vec1->size);
+ sub_vn_vnvn(vec, vec1->vec, vec2->vec, vec1->vec_num);
- return Vector_CreatePyObject_alloc(vec, vec1->size, Py_TYPE(v1));
+ return Vector_CreatePyObject_alloc(vec, vec1->vec_num, Py_TYPE(v1));
}
/* subtraction in-place: obj -= obj */
@@ -1641,7 +1643,7 @@ static PyObject *Vector_isub(PyObject *v1, PyObject *v2)
vec1 = (VectorObject *)v1;
vec2 = (VectorObject *)v2;
- if (vec1->size != vec2->size) {
+ if (vec1->vec_num != vec2->vec_num) {
PyErr_SetString(PyExc_AttributeError,
"Vector subtraction: "
"vectors must have the same dimensions for this operation");
@@ -1652,7 +1654,7 @@ static PyObject *Vector_isub(PyObject *v1, PyObject *v2)
return NULL;
}
- sub_vn_vn(vec1->vec, vec2->vec, vec1->size);
+ sub_vn_vn(vec1->vec, vec2->vec, vec1->vec_num);
(void)BaseMath_WriteCallback(vec1);
Py_INCREF(v1);
@@ -1667,8 +1669,8 @@ int column_vector_multiplication(float r_vec[MAX_DIMENSIONS], VectorObject *vec,
float vec_cpy[MAX_DIMENSIONS];
int row, col, z = 0;
- if (mat->num_col != vec->size) {
- if (mat->num_col == 4 && vec->size == 3) {
+ if (mat->col_num != vec->vec_num) {
+ if (mat->col_num == 4 && vec->vec_num == 3) {
vec_cpy[3] = 1.0f;
}
else {
@@ -1680,13 +1682,13 @@ int column_vector_multiplication(float r_vec[MAX_DIMENSIONS], VectorObject *vec,
}
}
- memcpy(vec_cpy, vec->vec, vec->size * sizeof(float));
+ memcpy(vec_cpy, vec->vec, vec->vec_num * sizeof(float));
r_vec[3] = 1.0f;
- for (row = 0; row < mat->num_row; row++) {
+ for (row = 0; row < mat->row_num; row++) {
double dot = 0.0f;
- for (col = 0; col < mat->num_col; col++) {
+ for (col = 0; col < mat->col_num; col++) {
dot += (double)(MATRIX_ITEM(mat, row, col) * vec_cpy[col]);
}
r_vec[z++] = (float)dot;
@@ -1697,7 +1699,7 @@ int column_vector_multiplication(float r_vec[MAX_DIMENSIONS], VectorObject *vec,
static PyObject *vector_mul_float(VectorObject *vec, const float scalar)
{
- float *tvec = PyMem_Malloc(vec->size * sizeof(float));
+ float *tvec = PyMem_Malloc(vec->vec_num * sizeof(float));
if (tvec == NULL) {
PyErr_SetString(PyExc_MemoryError,
"vec * float: "
@@ -1705,13 +1707,13 @@ static PyObject *vector_mul_float(VectorObject *vec, const float scalar)
return NULL;
}
- mul_vn_vn_fl(tvec, vec->vec, vec->size, scalar);
- return Vector_CreatePyObject_alloc(tvec, vec->size, Py_TYPE(vec));
+ mul_vn_vn_fl(tvec, vec->vec, vec->vec_num, scalar);
+ return Vector_CreatePyObject_alloc(tvec, vec->vec_num, Py_TYPE(vec));
}
static PyObject *vector_mul_vec(VectorObject *vec1, VectorObject *vec2)
{
- float *tvec = PyMem_Malloc(vec1->size * sizeof(float));
+ float *tvec = PyMem_Malloc(vec1->vec_num * sizeof(float));
if (tvec == NULL) {
PyErr_SetString(PyExc_MemoryError,
"vec * vec: "
@@ -1719,8 +1721,8 @@ static PyObject *vector_mul_vec(VectorObject *vec1, VectorObject *vec2)
return NULL;
}
- mul_vn_vnvn(tvec, vec1->vec, vec2->vec, vec1->size);
- return Vector_CreatePyObject_alloc(tvec, vec1->size, Py_TYPE(vec1));
+ mul_vn_vnvn(tvec, vec1->vec, vec2->vec, vec1->vec_num);
+ return Vector_CreatePyObject_alloc(tvec, vec1->vec_num, Py_TYPE(vec1));
}
static PyObject *Vector_mul(PyObject *v1, PyObject *v2)
@@ -1745,7 +1747,7 @@ static PyObject *Vector_mul(PyObject *v1, PyObject *v2)
/* make sure v1 is always the vector */
if (vec1 && vec2) {
- if (vec1->size != vec2->size) {
+ if (vec1->vec_num != vec2->vec_num) {
PyErr_SetString(PyExc_ValueError,
"Vector multiplication: "
"vectors must have the same dimensions for this operation");
@@ -1800,7 +1802,7 @@ static PyObject *Vector_imul(PyObject *v1, PyObject *v2)
/* Intentionally don't support (Quaternion, Matrix) here, uses reverse order instead. */
if (vec1 && vec2) {
- if (vec1->size != vec2->size) {
+ if (vec1->vec_num != vec2->vec_num) {
PyErr_SetString(PyExc_ValueError,
"Vector multiplication: "
"vectors must have the same dimensions for this operation");
@@ -1808,11 +1810,11 @@ static PyObject *Vector_imul(PyObject *v1, PyObject *v2)
}
/* Element-wise product in-place. */
- mul_vn_vn(vec1->vec, vec2->vec, vec1->size);
+ mul_vn_vn(vec1->vec, vec2->vec, vec1->vec_num);
}
else if (vec1 && (((scalar = PyFloat_AsDouble(v2)) == -1.0f && PyErr_Occurred()) ==
0)) { /* VEC *= FLOAT */
- mul_vn_fl(vec1->vec, vec1->size, scalar);
+ mul_vn_fl(vec1->vec, vec1->vec_num, scalar);
}
else {
PyErr_Format(PyExc_TypeError,
@@ -1831,7 +1833,7 @@ static PyObject *Vector_imul(PyObject *v1, PyObject *v2)
static PyObject *Vector_matmul(PyObject *v1, PyObject *v2)
{
VectorObject *vec1 = NULL, *vec2 = NULL;
- int vec_size;
+ int vec_num;
if (VectorObject_Check(v1)) {
vec1 = (VectorObject *)v1;
@@ -1850,7 +1852,7 @@ static PyObject *Vector_matmul(PyObject *v1, PyObject *v2)
/* make sure v1 is always the vector */
if (vec1 && vec2) {
- if (vec1->size != vec2->size) {
+ if (vec1->vec_num != vec2->vec_num) {
PyErr_SetString(PyExc_ValueError,
"Vector multiplication: "
"vectors must have the same dimensions for this operation");
@@ -1858,7 +1860,7 @@ static PyObject *Vector_matmul(PyObject *v1, PyObject *v2)
}
/* Dot product. */
- return PyFloat_FromDouble(dot_vn_vn(vec1->vec, vec2->vec, vec1->size));
+ return PyFloat_FromDouble(dot_vn_vn(vec1->vec, vec2->vec, vec1->vec_num));
}
if (vec1) {
if (MatrixObject_Check(v2)) {
@@ -1872,14 +1874,14 @@ static PyObject *Vector_matmul(PyObject *v1, PyObject *v2)
return NULL;
}
- if (((MatrixObject *)v2)->num_row == 4 && vec1->size == 3) {
- vec_size = 3;
+ if (((MatrixObject *)v2)->row_num == 4 && vec1->vec_num == 3) {
+ vec_num = 3;
}
else {
- vec_size = ((MatrixObject *)v2)->num_col;
+ vec_num = ((MatrixObject *)v2)->col_num;
}
- return Vector_CreatePyObject(tvec, vec_size, Py_TYPE(vec1));
+ return Vector_CreatePyObject(tvec, vec_num, Py_TYPE(vec1));
}
}
@@ -1934,7 +1936,7 @@ static PyObject *Vector_div(PyObject *v1, PyObject *v2)
return NULL;
}
- vec = PyMem_Malloc(vec1->size * sizeof(float));
+ vec = PyMem_Malloc(vec1->vec_num * sizeof(float));
if (vec == NULL) {
PyErr_SetString(PyExc_MemoryError,
@@ -1943,9 +1945,9 @@ static PyObject *Vector_div(PyObject *v1, PyObject *v2)
return NULL;
}
- mul_vn_vn_fl(vec, vec1->vec, vec1->size, 1.0f / scalar);
+ mul_vn_vn_fl(vec, vec1->vec, vec1->vec_num, 1.0f / scalar);
- return Vector_CreatePyObject_alloc(vec, vec1->size, Py_TYPE(v1));
+ return Vector_CreatePyObject_alloc(vec, vec1->vec_num, Py_TYPE(v1));
}
/* divide in-place: obj /= obj */
@@ -1973,7 +1975,7 @@ static PyObject *Vector_idiv(PyObject *v1, PyObject *v2)
return NULL;
}
- mul_vn_fl(vec1->vec, vec1->size, 1.0f / scalar);
+ mul_vn_fl(vec1->vec, vec1->vec_num, 1.0f / scalar);
(void)BaseMath_WriteCallback(vec1);
@@ -1991,9 +1993,9 @@ static PyObject *Vector_neg(VectorObject *self)
return NULL;
}
- tvec = PyMem_Malloc(self->size * sizeof(float));
- negate_vn_vn(tvec, self->vec, self->size);
- return Vector_CreatePyObject_alloc(tvec, self->size, Py_TYPE(self));
+ tvec = PyMem_Malloc(self->vec_num * sizeof(float));
+ negate_vn_vn(tvec, self->vec, self->vec_num);
+ return Vector_CreatePyObject_alloc(tvec, self->vec_num, Py_TYPE(self));
}
/*------------------------tp_richcmpr
@@ -2019,7 +2021,7 @@ static PyObject *Vector_richcmpr(PyObject *objectA, PyObject *objectB, int compa
return NULL;
}
- if (vecA->size != vecB->size) {
+ if (vecA->vec_num != vecB->vec_num) {
if (comparison_type == Py_NE) {
Py_RETURN_TRUE;
}
@@ -2029,15 +2031,15 @@ static PyObject *Vector_richcmpr(PyObject *objectA, PyObject *objectB, int compa
switch (comparison_type) {
case Py_LT:
- lenA = len_squared_vn(vecA->vec, vecA->size);
- lenB = len_squared_vn(vecB->vec, vecB->size);
+ lenA = len_squared_vn(vecA->vec, vecA->vec_num);
+ lenB = len_squared_vn(vecB->vec, vecB->vec_num);
if (lenA < lenB) {
result = 1;
}
break;
case Py_LE:
- lenA = len_squared_vn(vecA->vec, vecA->size);
- lenB = len_squared_vn(vecB->vec, vecB->size);
+ lenA = len_squared_vn(vecA->vec, vecA->vec_num);
+ lenB = len_squared_vn(vecB->vec, vecB->vec_num);
if (lenA < lenB) {
result = 1;
}
@@ -2046,21 +2048,21 @@ static PyObject *Vector_richcmpr(PyObject *objectA, PyObject *objectB, int compa
}
break;
case Py_EQ:
- result = EXPP_VectorsAreEqual(vecA->vec, vecB->vec, vecA->size, 1);
+ result = EXPP_VectorsAreEqual(vecA->vec, vecB->vec, vecA->vec_num, 1);
break;
case Py_NE:
- result = !EXPP_VectorsAreEqual(vecA->vec, vecB->vec, vecA->size, 1);
+ result = !EXPP_VectorsAreEqual(vecA->vec, vecB->vec, vecA->vec_num, 1);
break;
case Py_GT:
- lenA = len_squared_vn(vecA->vec, vecA->size);
- lenB = len_squared_vn(vecB->vec, vecB->size);
+ lenA = len_squared_vn(vecA->vec, vecA->vec_num);
+ lenB = len_squared_vn(vecB->vec, vecB->vec_num);
if (lenA > lenB) {
result = 1;
}
break;
case Py_GE:
- lenA = len_squared_vn(vecA->vec, vecA->size);
- lenB = len_squared_vn(vecB->vec, vecB->size);
+ lenA = len_squared_vn(vecA->vec, vecA->vec_num);
+ lenB = len_squared_vn(vecB->vec, vecB->vec_num);
if (lenA > lenB) {
result = 1;
}
@@ -2089,7 +2091,7 @@ static Py_hash_t Vector_hash(VectorObject *self)
return -1;
}
- return mathutils_array_hash(self->vec, self->size);
+ return mathutils_array_hash(self->vec, self->vec_num);
}
/*-----------------PROTCOL DECLARATIONS--------------------------*/
@@ -2115,14 +2117,14 @@ static PyObject *Vector_subscript(VectorObject *self, PyObject *item)
return NULL;
}
if (i < 0) {
- i += self->size;
+ i += self->vec_num;
}
return Vector_item(self, i);
}
if (PySlice_Check(item)) {
Py_ssize_t start, stop, step, slicelength;
- if (PySlice_GetIndicesEx(item, self->size, &start, &stop, &step, &slicelength) < 0) {
+ if (PySlice_GetIndicesEx(item, self->vec_num, &start, &stop, &step, &slicelength) < 0) {
return NULL;
}
@@ -2150,14 +2152,14 @@ static int Vector_ass_subscript(VectorObject *self, PyObject *item, PyObject *va
return -1;
}
if (i < 0) {
- i += self->size;
+ i += self->vec_num;
}
return Vector_ass_item(self, i, value);
}
if (PySlice_Check(item)) {
Py_ssize_t start, stop, step, slicelength;
- if (PySlice_GetIndicesEx(item, self->size, &start, &stop, &step, &slicelength) < 0) {
+ if (PySlice_GetIndicesEx(item, self->vec_num, &start, &stop, &step, &slicelength) < 0) {
return -1;
}
@@ -2247,7 +2249,7 @@ static PyObject *Vector_length_get(VectorObject *self, void *UNUSED(closure))
return NULL;
}
- return PyFloat_FromDouble(sqrt(dot_vn_vn(self->vec, self->vec, self->size)));
+ return PyFloat_FromDouble(sqrt(dot_vn_vn(self->vec, self->vec, self->vec_num)));
}
static int Vector_length_set(VectorObject *self, PyObject *value)
@@ -2268,11 +2270,11 @@ static int Vector_length_set(VectorObject *self, PyObject *value)
return -1;
}
if (param == 0.0) {
- copy_vn_fl(self->vec, self->size, 0.0f);
+ copy_vn_fl(self->vec, self->vec_num, 0.0f);
return 0;
}
- dot = dot_vn_vn(self->vec, self->vec, self->size);
+ dot = dot_vn_vn(self->vec, self->vec, self->vec_num);
if (!dot) {
/* can't sqrt zero */
@@ -2287,7 +2289,7 @@ static int Vector_length_set(VectorObject *self, PyObject *value)
dot = dot / param;
- mul_vn_fl(self->vec, self->size, 1.0 / dot);
+ mul_vn_fl(self->vec, self->vec_num, 1.0 / dot);
(void)BaseMath_WriteCallback(self); /* checked already */
@@ -2302,7 +2304,7 @@ static PyObject *Vector_length_squared_get(VectorObject *self, void *UNUSED(clos
return NULL;
}
- return PyFloat_FromDouble(dot_vn_vn(self->vec, self->vec, self->size));
+ return PyFloat_FromDouble(dot_vn_vn(self->vec, self->vec, self->vec_num));
}
/**
@@ -2382,7 +2384,7 @@ static PyObject *Vector_swizzle_get(VectorObject *self, void *closure)
swizzleClosure = POINTER_AS_INT(closure);
while (swizzleClosure & SWIZZLE_VALID_AXIS) {
axis_from = swizzleClosure & SWIZZLE_AXIS;
- if (axis_from >= self->size) {
+ if (axis_from >= self->vec_num) {
PyErr_SetString(PyExc_AttributeError,
"Vector swizzle: "
"specified axis not present");
@@ -2432,7 +2434,7 @@ static int Vector_swizzle_set(VectorObject *self, PyObject *value, void *closure
while (swizzleClosure & SWIZZLE_VALID_AXIS) {
axis_to = swizzleClosure & SWIZZLE_AXIS;
- if (axis_to >= self->size) {
+ if (axis_to >= self->vec_num) {
PyErr_SetString(PyExc_AttributeError,
"Vector swizzle: "
"specified axis not present");
@@ -2468,8 +2470,8 @@ static int Vector_swizzle_set(VectorObject *self, PyObject *value, void *closure
/* We must first copy current vec into tvec, else some org values may be lost.
* See T31760.
- * Assuming self->size can't be higher than MAX_DIMENSIONS! */
- memcpy(tvec, self->vec, self->size * sizeof(float));
+ * Assuming self->vec_num can't be higher than MAX_DIMENSIONS! */
+ memcpy(tvec, self->vec, self->vec_num * sizeof(float));
while (swizzleClosure & SWIZZLE_VALID_AXIS) {
axis_to = swizzleClosure & SWIZZLE_AXIS;
@@ -2480,7 +2482,7 @@ static int Vector_swizzle_set(VectorObject *self, PyObject *value, void *closure
/* We must copy back the whole tvec into vec, else some changes may be lost (e.g. xz...).
* See T31760. */
- memcpy(self->vec, tvec, self->size * sizeof(float));
+ memcpy(self->vec, tvec, self->vec_num * sizeof(float));
/* continue with BaseMathObject_WriteCallback at the end */
if (BaseMath_WriteCallback(self) == -1) {
@@ -2898,10 +2900,10 @@ static int row_vector_multiplication(float r_vec[MAX_DIMENSIONS],
MatrixObject *mat)
{
float vec_cpy[MAX_DIMENSIONS];
- int row, col, z = 0, vec_size = vec->size;
+ int row, col, z = 0, vec_num = vec->vec_num;
- if (mat->num_row != vec_size) {
- if (mat->num_row == 4 && vec_size == 3) {
+ if (mat->row_num != vec_num) {
+ if (mat->row_num == 4 && vec_num == 3) {
vec_cpy[3] = 1.0f;
}
else {
@@ -2916,13 +2918,13 @@ static int row_vector_multiplication(float r_vec[MAX_DIMENSIONS],
return -1;
}
- memcpy(vec_cpy, vec->vec, vec_size * sizeof(float));
+ memcpy(vec_cpy, vec->vec, vec_num * sizeof(float));
r_vec[3] = 1.0f;
/* Multiplication. */
- for (col = 0; col < mat->num_col; col++) {
+ for (col = 0; col < mat->col_num; col++) {
double dot = 0.0;
- for (row = 0; row < mat->num_row; row++) {
+ for (row = 0; row < mat->row_num; row++) {
dot += (double)(MATRIX_ITEM(mat, row, col) * vec_cpy[row]);
}
r_vec[z++] = (float)dot;
@@ -2941,7 +2943,7 @@ static PyObject *Vector_negate(VectorObject *self)
return NULL;
}
- negate_vn(self->vec, self->size);
+ negate_vn(self->vec, self->vec_num);
(void)BaseMath_WriteCallback(self); /* already checked for error */
Py_RETURN_NONE;
@@ -3096,17 +3098,17 @@ PyTypeObject vector_Type = {
NULL,
};
-PyObject *Vector_CreatePyObject(const float *vec, const int size, PyTypeObject *base_type)
+PyObject *Vector_CreatePyObject(const float *vec, const int vec_num, PyTypeObject *base_type)
{
VectorObject *self;
float *vec_alloc;
- if (size < 2) {
+ if (vec_num < 2) {
PyErr_SetString(PyExc_RuntimeError, "Vector(): invalid size");
return NULL;
}
- vec_alloc = PyMem_Malloc(size * sizeof(float));
+ vec_alloc = PyMem_Malloc(vec_num * sizeof(float));
if (UNLIKELY(vec_alloc == NULL)) {
PyErr_SetString(PyExc_MemoryError,
"Vector(): "
@@ -3117,18 +3119,18 @@ PyObject *Vector_CreatePyObject(const float *vec, const int size, PyTypeObject *
self = BASE_MATH_NEW(VectorObject, vector_Type, base_type);
if (self) {
self->vec = vec_alloc;
- self->size = size;
+ self->vec_num = vec_num;
/* init callbacks as NULL */
self->cb_user = NULL;
self->cb_type = self->cb_subtype = 0;
if (vec) {
- memcpy(self->vec, vec, size * sizeof(float));
+ memcpy(self->vec, vec, vec_num * sizeof(float));
}
else { /* new empty */
- copy_vn_fl(self->vec, size, 0.0f);
- if (size == 4) { /* do the homogeneous thing */
+ copy_vn_fl(self->vec, vec_num, 0.0f);
+ if (vec_num == 4) { /* do the homogeneous thing */
self->vec[3] = 1.0f;
}
}
@@ -3141,18 +3143,18 @@ PyObject *Vector_CreatePyObject(const float *vec, const int size, PyTypeObject *
return (PyObject *)self;
}
-PyObject *Vector_CreatePyObject_wrap(float *vec, const int size, PyTypeObject *base_type)
+PyObject *Vector_CreatePyObject_wrap(float *vec, const int vec_num, PyTypeObject *base_type)
{
VectorObject *self;
- if (size < 2) {
+ if (vec_num < 2) {
PyErr_SetString(PyExc_RuntimeError, "Vector(): invalid size");
return NULL;
}
self = BASE_MATH_NEW(VectorObject, vector_Type, base_type);
if (self) {
- self->size = size;
+ self->vec_num = vec_num;
/* init callbacks as NULL */
self->cb_user = NULL;
@@ -3164,9 +3166,9 @@ PyObject *Vector_CreatePyObject_wrap(float *vec, const int size, PyTypeObject *b
return (PyObject *)self;
}
-PyObject *Vector_CreatePyObject_cb(PyObject *cb_user, int size, uchar cb_type, uchar cb_subtype)
+PyObject *Vector_CreatePyObject_cb(PyObject *cb_user, int vec_num, uchar cb_type, uchar cb_subtype)
{
- VectorObject *self = (VectorObject *)Vector_CreatePyObject(NULL, size, NULL);
+ VectorObject *self = (VectorObject *)Vector_CreatePyObject(NULL, vec_num, NULL);
if (self) {
Py_INCREF(cb_user);
self->cb_user = cb_user;
@@ -3178,10 +3180,10 @@ PyObject *Vector_CreatePyObject_cb(PyObject *cb_user, int size, uchar cb_type, u
return (PyObject *)self;
}
-PyObject *Vector_CreatePyObject_alloc(float *vec, const int size, PyTypeObject *base_type)
+PyObject *Vector_CreatePyObject_alloc(float *vec, const int vec_num, PyTypeObject *base_type)
{
VectorObject *self;
- self = (VectorObject *)Vector_CreatePyObject_wrap(vec, size, base_type);
+ self = (VectorObject *)Vector_CreatePyObject_wrap(vec, vec_num, base_type);
if (self) {
self->flag &= ~BASE_MATH_FLAG_IS_WRAP;
}
diff --git a/source/blender/python/mathutils/mathutils_Vector.h b/source/blender/python/mathutils/mathutils_Vector.h
index 422050c8742..3bc4e9d6b6f 100644
--- a/source/blender/python/mathutils/mathutils_Vector.h
+++ b/source/blender/python/mathutils/mathutils_Vector.h
@@ -14,12 +14,13 @@ extern PyTypeObject vector_Type;
typedef struct {
BASE_MATH_MEMBERS(vec);
- int size; /* vec size 2 or more */
+ /** Number of items in this vector (2 or more). */
+ int vec_num;
} VectorObject;
/*prototypes*/
PyObject *Vector_CreatePyObject(const float *vec,
- int size,
+ int vec_num,
PyTypeObject *base_type) ATTR_WARN_UNUSED_RESULT;
/**
* Create a vector that wraps existing memory.
@@ -27,7 +28,7 @@ PyObject *Vector_CreatePyObject(const float *vec,
* \param vec: Use this vector in-place.
*/
PyObject *Vector_CreatePyObject_wrap(float *vec,
- int size,
+ int vec_num,
PyTypeObject *base_type) ATTR_WARN_UNUSED_RESULT
ATTR_NONNULL(1);
/**
@@ -35,13 +36,13 @@ PyObject *Vector_CreatePyObject_wrap(float *vec,
* see: #Mathutils_RegisterCallback
*/
PyObject *Vector_CreatePyObject_cb(PyObject *user,
- int size,
+ int vec_num,
unsigned char cb_type,
unsigned char subtype) ATTR_WARN_UNUSED_RESULT;
/**
* \param vec: Initialized vector value to use in-place, allocated with #PyMem_Malloc
*/
PyObject *Vector_CreatePyObject_alloc(float *vec,
- int size,
+ int vec_num,
PyTypeObject *base_type) ATTR_WARN_UNUSED_RESULT
ATTR_NONNULL(1);
diff --git a/source/blender/python/mathutils/mathutils_geometry.c b/source/blender/python/mathutils/mathutils_geometry.c
index 84ba2ce4031..1e492574903 100644
--- a/source/blender/python/mathutils/mathutils_geometry.c
+++ b/source/blender/python/mathutils/mathutils_geometry.c
@@ -158,24 +158,30 @@ static PyObject *M_Geometry_intersect_line_line(PyObject *UNUSED(self), PyObject
PyObject *tuple;
PyObject *py_lines[4];
float lines[4][3], i1[3], i2[3];
- int len;
+ int ix_vec_num;
int result;
if (!PyArg_ParseTuple(args, "OOOO:intersect_line_line", UNPACK4_EX(&, py_lines, ))) {
return NULL;
}
- if ((((len = mathutils_array_parse(
+ if ((((ix_vec_num = mathutils_array_parse(
lines[0], 2, 3 | MU_ARRAY_SPILL | MU_ARRAY_ZERO, py_lines[0], error_prefix)) != -1) &&
- (mathutils_array_parse(
- lines[1], len, len | MU_ARRAY_SPILL | MU_ARRAY_ZERO, py_lines[1], error_prefix) !=
- -1) &&
- (mathutils_array_parse(
- lines[2], len, len | MU_ARRAY_SPILL | MU_ARRAY_ZERO, py_lines[2], error_prefix) !=
- -1) &&
- (mathutils_array_parse(
- lines[3], len, len | MU_ARRAY_SPILL | MU_ARRAY_ZERO, py_lines[3], error_prefix) !=
- -1)) == 0) {
+ (mathutils_array_parse(lines[1],
+ ix_vec_num,
+ ix_vec_num | MU_ARRAY_SPILL | MU_ARRAY_ZERO,
+ py_lines[1],
+ error_prefix) != -1) &&
+ (mathutils_array_parse(lines[2],
+ ix_vec_num,
+ ix_vec_num | MU_ARRAY_SPILL | MU_ARRAY_ZERO,
+ py_lines[2],
+ error_prefix) != -1) &&
+ (mathutils_array_parse(lines[3],
+ ix_vec_num,
+ ix_vec_num | MU_ARRAY_SPILL | MU_ARRAY_ZERO,
+ py_lines[3],
+ error_prefix) != -1)) == 0) {
return NULL;
}
@@ -192,8 +198,9 @@ static PyObject *M_Geometry_intersect_line_line(PyObject *UNUSED(self), PyObject
}
tuple = PyTuple_New(2);
- PyTuple_SET_ITEMS(
- tuple, Vector_CreatePyObject(i1, len, NULL), Vector_CreatePyObject(i2, len, NULL));
+ PyTuple_SET_ITEMS(tuple,
+ Vector_CreatePyObject(i1, ix_vec_num, NULL),
+ Vector_CreatePyObject(i2, ix_vec_num, NULL));
return tuple;
}
@@ -764,14 +771,14 @@ static PyObject *M_Geometry_intersect_point_line(PyObject *UNUSED(self), PyObjec
float pt[3], pt_out[3], line_a[3], line_b[3];
float lambda;
PyObject *ret;
- int size = 2;
+ int pt_num = 2;
if (!PyArg_ParseTuple(args, "OOO:intersect_point_line", &py_pt, &py_line_a, &py_line_b)) {
return NULL;
}
/* accept 2d verts */
- if ((((size = mathutils_array_parse(
+ if ((((pt_num = mathutils_array_parse(
pt, 2, 3 | MU_ARRAY_SPILL | MU_ARRAY_ZERO, py_pt, error_prefix)) != -1) &&
(mathutils_array_parse(
line_a, 2, 3 | MU_ARRAY_SPILL | MU_ARRAY_ZERO, py_line_a, error_prefix) != -1) &&
@@ -784,7 +791,7 @@ static PyObject *M_Geometry_intersect_point_line(PyObject *UNUSED(self), PyObjec
lambda = closest_to_line_v3(pt_out, pt, line_a, line_b);
ret = PyTuple_New(2);
- PyTuple_SET_ITEMS(ret, Vector_CreatePyObject(pt_out, size, NULL), PyFloat_FromDouble(lambda));
+ PyTuple_SET_ITEMS(ret, Vector_CreatePyObject(pt_out, pt_num, NULL), PyFloat_FromDouble(lambda));
return ret;
}
diff --git a/source/blender/python/mathutils/mathutils_noise.c b/source/blender/python/mathutils/mathutils_noise.c
index 0853c5dd3ea..e1282e90c48 100644
--- a/source/blender/python/mathutils/mathutils_noise.c
+++ b/source/blender/python/mathutils/mathutils_noise.c
@@ -305,23 +305,24 @@ static PyObject *M_Noise_random_unit_vector(PyObject *UNUSED(self), PyObject *ar
static const char *kwlist[] = {"size", NULL};
float vec[4] = {0.0f, 0.0f, 0.0f, 0.0f};
float norm = 2.0f;
- int size = 3;
+ int vec_num = 3;
- if (!PyArg_ParseTupleAndKeywords(args, kw, "|$i:random_unit_vector", (char **)kwlist, &size)) {
+ if (!PyArg_ParseTupleAndKeywords(
+ args, kw, "|$i:random_unit_vector", (char **)kwlist, &vec_num)) {
return NULL;
}
- if (size > 4 || size < 2) {
+ if (vec_num > 4 || vec_num < 2) {
PyErr_SetString(PyExc_ValueError, "Vector(): invalid size");
return NULL;
}
while (norm == 0.0f || norm > 1.0f) {
- rand_vn(vec, size);
- norm = normalize_vn(vec, size);
+ rand_vn(vec, vec_num);
+ norm = normalize_vn(vec, vec_num);
}
- return Vector_CreatePyObject(vec, size, NULL);
+ return Vector_CreatePyObject(vec, vec_num, NULL);
}
PyDoc_STRVAR(M_Noise_random_vector_doc,
@@ -337,22 +338,22 @@ static PyObject *M_Noise_random_vector(PyObject *UNUSED(self), PyObject *args, P
{
static const char *kwlist[] = {"size", NULL};
float *vec = NULL;
- int size = 3;
+ int vec_num = 3;
- if (!PyArg_ParseTupleAndKeywords(args, kw, "|$i:random_vector", (char **)kwlist, &size)) {
+ if (!PyArg_ParseTupleAndKeywords(args, kw, "|$i:random_vector", (char **)kwlist, &vec_num)) {
return NULL;
}
- if (size < 2) {
+ if (vec_num < 2) {
PyErr_SetString(PyExc_ValueError, "Vector(): invalid size");
return NULL;
}
- vec = PyMem_New(float, size);
+ vec = PyMem_New(float, vec_num);
- rand_vn(vec, size);
+ rand_vn(vec, vec_num);
- return Vector_CreatePyObject_alloc(vec, size, NULL);
+ return Vector_CreatePyObject_alloc(vec, vec_num, NULL);
}
PyDoc_STRVAR(M_Noise_seed_set_doc,
diff --git a/source/blender/render/RE_bake.h b/source/blender/render/RE_bake.h
index 6d849757166..3a4a3e6dcb9 100644
--- a/source/blender/render/RE_bake.h
+++ b/source/blender/render/RE_bake.h
@@ -27,16 +27,16 @@ typedef struct BakeImage {
typedef struct BakeTargets {
/* All images of the object. */
BakeImage *images;
- int num_images;
+ int images_num;
/* Lookup table from Material number to BakeImage. */
int *material_to_image;
- int num_materials;
+ int materials_num;
/* Pixel buffer to bake to. */
float *result;
- int num_pixels;
- int num_channels;
+ int pixels_num;
+ int channels_num;
/* Baking to non-color data image. */
bool is_noncolor;
@@ -81,7 +81,7 @@ bool RE_bake_pixels_populate_from_objects(struct Mesh *me_low,
BakePixel pixel_array_to[],
BakeHighPolyData highpoly[],
int tot_highpoly,
- size_t num_pixels,
+ size_t pixels_num,
bool is_custom_cage,
float cage_extrusion,
float max_ray_distance,
@@ -91,11 +91,11 @@ bool RE_bake_pixels_populate_from_objects(struct Mesh *me_low,
void RE_bake_pixels_populate(struct Mesh *me,
struct BakePixel *pixel_array,
- size_t num_pixels,
+ size_t pixels_num,
const struct BakeTargets *targets,
const char *uv_layer);
-void RE_bake_mask_fill(const BakePixel pixel_array[], size_t num_pixels, char *mask);
+void RE_bake_mask_fill(const BakePixel pixel_array[], size_t pixels_num, char *mask);
void RE_bake_margin(struct ImBuf *ibuf,
char *mask,
@@ -105,7 +105,7 @@ void RE_bake_margin(struct ImBuf *ibuf,
char const *uv_layer);
void RE_bake_normal_world_to_object(const BakePixel pixel_array[],
- size_t num_pixels,
+ size_t pixels_num,
int depth,
float result[],
struct Object *ob,
@@ -115,14 +115,14 @@ void RE_bake_normal_world_to_object(const BakePixel pixel_array[],
* to a tangent space normal map for a given low poly mesh.
*/
void RE_bake_normal_world_to_tangent(const BakePixel pixel_array[],
- size_t num_pixels,
+ size_t pixels_num,
int depth,
float result[],
struct Mesh *me,
const eBakeNormalSwizzle normal_swizzle[3],
float mat[4][4]);
void RE_bake_normal_world_to_world(const BakePixel pixel_array[],
- size_t num_pixels,
+ size_t pixels_num,
int depth,
float result[],
const eBakeNormalSwizzle normal_swizzle[3]);
diff --git a/source/blender/render/intern/bake.c b/source/blender/render/intern/bake.c
index 596adafb2c9..69235fb6cb1 100644
--- a/source/blender/render/intern/bake.c
+++ b/source/blender/render/intern/bake.c
@@ -12,14 +12,14 @@
* The Bake API is fully implemented with Python rna functions.
* The operator expects/call a function:
*
- * `def bake(scene, object, pass_type, object_id, pixel_array, num_pixels, depth, result)`
+ * `def bake(scene, object, pass_type, object_id, pixel_array, pixels_num, depth, result)`
* - scene: current scene (Python object)
* - object: object to render (Python object)
* - pass_type: pass to render (string, e.g., "COMBINED", "AO", "NORMAL", ...)
* - object_id: index of object to bake (to use with the pixel_array)
* - pixel_array: list of primitive ids and barycentric coordinates to
* `bake(Python object, see bake_pixel)`.
- * - num_pixels: size of pixel_array, number of pixels to bake (int)
+ * - pixels_num: size of pixel_array, number of pixels to bake (int)
* - depth: depth of pixels to return (int, assuming always 4 now)
* - result: array to be populated by the engine (float array, PyLong_AsVoidPtr)
*
@@ -126,7 +126,7 @@ static void store_bake_pixel(void *handle, int x, int y, float u, float v)
pixel->seed = i;
}
-void RE_bake_mask_fill(const BakePixel pixel_array[], const size_t num_pixels, char *mask)
+void RE_bake_mask_fill(const BakePixel pixel_array[], const size_t pixels_num, char *mask)
{
size_t i;
if (!mask) {
@@ -134,7 +134,7 @@ void RE_bake_mask_fill(const BakePixel pixel_array[], const size_t num_pixels, c
}
/* only extend to pixels outside the mask area */
- for (i = 0; i < num_pixels; i++) {
+ for (i = 0; i < pixels_num; i++) {
if (pixel_array[i].primitive_id != -1) {
mask[i] = FILTER_MASK_USED;
}
@@ -539,7 +539,7 @@ bool RE_bake_pixels_populate_from_objects(struct Mesh *me_low,
BakePixel pixel_array_to[],
BakeHighPolyData highpoly[],
const int tot_highpoly,
- const size_t num_pixels,
+ const size_t pixels_num,
const bool is_custom_cage,
const float cage_extrusion,
const float max_ray_distance,
@@ -603,7 +603,7 @@ bool RE_bake_pixels_populate_from_objects(struct Mesh *me_low,
}
}
- for (i = 0; i < num_pixels; i++) {
+ for (i = 0; i < pixels_num; i++) {
float co[3];
float dir[3];
TriTessFace *tri_low;
@@ -707,7 +707,7 @@ static void bake_differentials(BakeDataZSpan *bd,
void RE_bake_pixels_populate(Mesh *me,
BakePixel pixel_array[],
- const size_t num_pixels,
+ const size_t pixels_num,
const BakeTargets *targets,
const char *uv_layer)
{
@@ -726,15 +726,15 @@ void RE_bake_pixels_populate(Mesh *me,
BakeDataZSpan bd;
bd.pixel_array = pixel_array;
- bd.zspan = MEM_callocN(sizeof(ZSpan) * targets->num_images, "bake zspan");
+ bd.zspan = MEM_callocN(sizeof(ZSpan) * targets->images_num, "bake zspan");
/* initialize all pixel arrays so we know which ones are 'blank' */
- for (int i = 0; i < num_pixels; i++) {
+ for (int i = 0; i < pixels_num; i++) {
pixel_array[i].primitive_id = -1;
pixel_array[i].object_id = 0;
}
- for (int i = 0; i < targets->num_images; i++) {
+ for (int i = 0; i < targets->images_num; i++) {
zbuf_alloc_span(&bd.zspan[i], targets->images[i].width, targets->images[i].height);
}
@@ -772,7 +772,7 @@ void RE_bake_pixels_populate(Mesh *me,
zspan_scanconvert(&bd.zspan[image_id], (void *)&bd, vec[0], vec[1], vec[2], store_bake_pixel);
}
- for (int i = 0; i < targets->num_images; i++) {
+ for (int i = 0; i < targets->images_num; i++) {
zbuf_free_span(&bd.zspan[i]);
}
@@ -823,7 +823,7 @@ static void normal_compress(float out[3],
}
void RE_bake_normal_world_to_tangent(const BakePixel pixel_array[],
- const size_t num_pixels,
+ const size_t pixels_num,
const int depth,
float result[],
Mesh *me,
@@ -838,9 +838,9 @@ void RE_bake_normal_world_to_tangent(const BakePixel pixel_array[],
triangles = mesh_calc_tri_tessface(me, true, me_eval);
- BLI_assert(num_pixels >= 3);
+ BLI_assert(pixels_num >= 3);
- for (i = 0; i < num_pixels; i++) {
+ for (i = 0; i < pixels_num; i++) {
TriTessFace *triangle;
float tangents[3][3];
float normals[3][3];
@@ -948,7 +948,7 @@ void RE_bake_normal_world_to_tangent(const BakePixel pixel_array[],
}
void RE_bake_normal_world_to_object(const BakePixel pixel_array[],
- const size_t num_pixels,
+ const size_t pixels_num,
const int depth,
float result[],
struct Object *ob,
@@ -959,7 +959,7 @@ void RE_bake_normal_world_to_object(const BakePixel pixel_array[],
invert_m4_m4(iobmat, ob->obmat);
- for (i = 0; i < num_pixels; i++) {
+ for (i = 0; i < pixels_num; i++) {
size_t offset;
float nor[3];
@@ -980,14 +980,14 @@ void RE_bake_normal_world_to_object(const BakePixel pixel_array[],
}
void RE_bake_normal_world_to_world(const BakePixel pixel_array[],
- const size_t num_pixels,
+ const size_t pixels_num,
const int depth,
float result[],
const eBakeNormalSwizzle normal_swizzle[3])
{
size_t i;
- for (i = 0; i < num_pixels; i++) {
+ for (i = 0; i < pixels_num; i++) {
size_t offset;
float nor[3];
diff --git a/source/blender/render/intern/engine.c b/source/blender/render/intern/engine.c
index 3a7ac22dc1f..8a4b4c2a70d 100644
--- a/source/blender/render/intern/engine.c
+++ b/source/blender/render/intern/engine.c
@@ -827,14 +827,14 @@ bool RE_bake_engine(Render *re,
type->update(engine, re->main, engine->depsgraph);
}
- for (int i = 0; i < targets->num_images; i++) {
+ for (int i = 0; i < targets->images_num; i++) {
const BakeImage *image = targets->images + i;
engine->bake.pixels = pixel_array + image->offset;
- engine->bake.result = result + image->offset * targets->num_channels;
+ engine->bake.result = result + image->offset * targets->channels_num;
engine->bake.width = image->width;
engine->bake.height = image->height;
- engine->bake.depth = targets->num_channels;
+ engine->bake.depth = targets->channels_num;
engine->bake.object_id = object_id;
type->bake(
diff --git a/source/blender/render/intern/multires_bake.c b/source/blender/render/intern/multires_bake.c
index c573d4feed1..33d961c027d 100644
--- a/source/blender/render/intern/multires_bake.c
+++ b/source/blender/render/intern/multires_bake.c
@@ -1061,23 +1061,23 @@ static void create_ao_raytree(MultiresBakeRender *bkr, MAOBakeData *ao_data)
RayFace *face;
CCGElem **grid_data;
CCGKey key;
- int num_grids, grid_size /*, face_side */, num_faces;
+ int grids_num, grid_size /*, face_side */, faces_num;
int i;
- num_grids = hidm->getNumGrids(hidm);
+ grids_num = hidm->getNumGrids(hidm);
grid_size = hidm->getGridSize(hidm);
grid_data = hidm->getGridData(hidm);
hidm->getGridKey(hidm, &key);
/* face_side = (grid_size << 1) - 1; */ /* UNUSED */
- num_faces = num_grids * (grid_size - 1) * (grid_size - 1);
+ faces_num = grids_num * (grid_size - 1) * (grid_size - 1);
raytree = ao_data->raytree = RE_rayobject_create(
- bkr->raytrace_structure, num_faces, bkr->octree_resolution);
- face = ao_data->rayfaces = (RayFace *)MEM_callocN(num_faces * sizeof(RayFace),
+ bkr->raytrace_structure, faces_num, bkr->octree_resolution);
+ face = ao_data->rayfaces = (RayFace *)MEM_callocN(faces_num * sizeof(RayFace),
"ObjectRen faces");
- for (i = 0; i < num_grids; i++) {
+ for (i = 0; i < grids_num; i++) {
int x, y;
for (x = 0; x < grid_size - 1; x++) {
for (y = 0; y < grid_size - 1; y++) {
diff --git a/source/blender/render/intern/render_result.c b/source/blender/render/intern/render_result.c
index ea7fa961f0d..9f4aa642773 100644
--- a/source/blender/render/intern/render_result.c
+++ b/source/blender/render/intern/render_result.c
@@ -402,7 +402,7 @@ RenderResult *render_result_new(Render *re,
render_layer_add_pass(rr, rl, 4, RE_PASSNAME_COMBINED, view, "RGBA", false);
}
- /* NOTE: this has to be in sync with `scene.c`. */
+ /* NOTE: this has to be in sync with `scene.cc`. */
rl->layflag = SCE_LAY_FLAG_DEFAULT;
rl->passflag = SCE_PASS_COMBINED;
diff --git a/source/blender/render/intern/texture_pointdensity.c b/source/blender/render/intern/texture_pointdensity.c
index f81b43f4bb0..bb313d4962c 100644
--- a/source/blender/render/intern/texture_pointdensity.c
+++ b/source/blender/render/intern/texture_pointdensity.c
@@ -843,7 +843,7 @@ void RE_point_density_minmax(struct Depsgraph *depsgraph,
}
else {
const float radius[3] = {pd->radius, pd->radius, pd->radius};
- BoundBox *bb = BKE_object_boundbox_get(object);
+ const BoundBox *bb = BKE_object_boundbox_get(object);
if (bb != NULL) {
BLI_assert((bb->flag & BOUNDBOX_DIRTY) == 0);
diff --git a/source/blender/sequencer/SEQ_animation.h b/source/blender/sequencer/SEQ_animation.h
index 455e77fb4a3..f2c66393b65 100644
--- a/source/blender/sequencer/SEQ_animation.h
+++ b/source/blender/sequencer/SEQ_animation.h
@@ -19,6 +19,18 @@ struct Sequence;
void SEQ_free_animdata(struct Scene *scene, struct Sequence *seq);
void SEQ_offset_animdata(struct Scene *scene, struct Sequence *seq, int ofs);
struct GSet *SEQ_fcurves_by_strip_get(const struct Sequence *seq, struct ListBase *fcurve_base);
+/**
+ * Move all `F-curves` from `scene` to `list`.
+ */
+void SEQ_animation_backup_original(struct Scene *scene, struct ListBase *list);
+/**
+ * Move all `F-curves` from `list` to `scene`.
+ */
+void SEQ_animation_restore_original(struct Scene *scene, struct ListBase *list);
+/**
+ * Duplicate `F-curves` used by `seq` from `list` to `scene`.
+ */
+void SEQ_animation_duplicate(struct Scene *scene, struct Sequence *seq, struct ListBase *list);
#ifdef __cplusplus
}
diff --git a/source/blender/sequencer/intern/animation.c b/source/blender/sequencer/intern/animation.c
index 47453ceda2b..27f7316e042 100644
--- a/source/blender/sequencer/intern/animation.c
+++ b/source/blender/sequencer/intern/animation.c
@@ -104,3 +104,32 @@ void SEQ_free_animdata(Scene *scene, Sequence *seq)
GSET_FOREACH_END();
BLI_gset_free(fcurves, NULL);
}
+
+void SEQ_animation_backup_original(Scene *scene, ListBase *list)
+{
+ if (scene->adt == NULL || scene->adt->action == NULL ||
+ BLI_listbase_is_empty(&scene->adt->action->curves)) {
+ return;
+ }
+
+ BLI_movelisttolist(list, &scene->adt->action->curves);
+}
+
+void SEQ_animation_restore_original(Scene *scene, ListBase *list)
+{
+ if (scene->adt == NULL || scene->adt->action == NULL || BLI_listbase_is_empty(list)) {
+ return;
+ }
+
+ BLI_movelisttolist(&scene->adt->action->curves, list);
+}
+
+void SEQ_animation_duplicate(Scene *scene, Sequence *seq, ListBase *list)
+{
+ GSet *fcurves = SEQ_fcurves_by_strip_get(seq, list);
+ GSET_FOREACH_BEGIN (FCurve *, fcu, fcurves) {
+ FCurve *fcu_cpy = BKE_fcurve_copy(fcu);
+ BLI_addtail(&scene->adt->action->curves, fcu_cpy);
+ }
+ GSET_FOREACH_END();
+}
diff --git a/source/blender/sequencer/intern/effects.c b/source/blender/sequencer/intern/effects.c
index 8f7088b0c4b..a4ab7671eb0 100644
--- a/source/blender/sequencer/intern/effects.c
+++ b/source/blender/sequencer/intern/effects.c
@@ -1681,7 +1681,7 @@ static void do_wipe_effect_byte(Sequence *seq,
for (int i = 0; i < y; i++) {
for (int j = 0; j < x; j++) {
- float check = check_zone(&wipezone, x, y, seq, fac);
+ float check = check_zone(&wipezone, j, i, seq, fac);
if (check) {
if (cp1) {
float rt1[4], rt2[4], tempc[4];
@@ -1742,7 +1742,7 @@ static void do_wipe_effect_float(
for (int i = 0; i < y; i++) {
for (int j = 0; j < x; j++) {
- float check = check_zone(&wipezone, x, y, seq, fac);
+ float check = check_zone(&wipezone, j, i, seq, fac);
if (check) {
if (rt1) {
rt[0] = rt1[0] * check + rt2[0] * (1 - check);
diff --git a/source/blender/sequencer/intern/strip_edit.c b/source/blender/sequencer/intern/strip_edit.c
index 60f3f35314e..2f76b6240cf 100644
--- a/source/blender/sequencer/intern/strip_edit.c
+++ b/source/blender/sequencer/intern/strip_edit.c
@@ -457,11 +457,18 @@ Sequence *SEQ_edit_strip_split(Main *bmain,
return NULL;
}
- /* Move strips in collection from seqbase to new ListBase. */
+ /* Store `F-curves`, so original ones aren't renamed. */
+ ListBase fcurves_original_backup = {NULL, NULL};
+ SEQ_animation_backup_original(scene, &fcurves_original_backup);
+
ListBase left_strips = {NULL, NULL};
SEQ_ITERATOR_FOREACH (seq, collection) {
+ /* Move strips in collection from seqbase to new ListBase. */
BLI_remlink(seqbase, seq);
BLI_addtail(&left_strips, seq);
+
+ /* Duplicate curves from backup, so they can be renamed along with split strips. */
+ SEQ_animation_duplicate(scene, seq, &fcurves_original_backup);
}
SEQ_collection_free(collection);
@@ -511,6 +518,8 @@ Sequence *SEQ_edit_strip_split(Main *bmain,
SEQ_ensure_unique_name(seq_rename, scene);
}
+ SEQ_animation_restore_original(scene, &fcurves_original_backup);
+
return return_seq;
}
diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h
index 6be3d719c64..bd7504788e1 100644
--- a/source/blender/windowmanager/WM_api.h
+++ b/source/blender/windowmanager/WM_api.h
@@ -39,6 +39,7 @@ struct MenuType;
struct PointerRNA;
struct PropertyRNA;
struct ScrArea;
+struct SelectPick_Params;
struct View3D;
struct ViewLayer;
struct bContext;
@@ -740,14 +741,33 @@ bool WM_operator_last_properties_store(struct wmOperator *op);
/* wm_operator_props.c */
void WM_operator_properties_confirm_or_exec(struct wmOperatorType *ot);
+
+/** Flags for #WM_operator_properties_filesel. */
+typedef enum eFileSel_Flag {
+ WM_FILESEL_RELPATH = 1 << 0,
+ WM_FILESEL_DIRECTORY = 1 << 1,
+ WM_FILESEL_FILENAME = 1 << 2,
+ WM_FILESEL_FILEPATH = 1 << 3,
+ WM_FILESEL_FILES = 1 << 4,
+ /** Show the properties sidebar by default. */
+ WM_FILESEL_SHOW_PROPS = 1 << 5,
+} eFileSel_Flag;
+ENUM_OPERATORS(eFileSel_Flag, WM_FILESEL_SHOW_PROPS)
+
+/** Action for #WM_operator_properties_filesel. */
+typedef enum eFileSel_Action {
+ FILE_OPENFILE = 0,
+ FILE_SAVE = 1,
+} eFileSel_Action;
+
/**
* Default properties for file-select.
*/
void WM_operator_properties_filesel(struct wmOperatorType *ot,
int filter,
short type,
- short action,
- short flag,
+ eFileSel_Action action,
+ eFileSel_Flag flag,
short display,
short sort);
/**
@@ -777,6 +797,9 @@ void WM_operator_properties_gesture_straightline(struct wmOperatorType *ot, int
* Use with #WM_gesture_circle_invoke
*/
void WM_operator_properties_gesture_circle(struct wmOperatorType *ot);
+/**
+ * See #ED_select_pick_params_from_operator to initialize parameters defined here.
+ */
void WM_operator_properties_mouse_select(struct wmOperatorType *ot);
void WM_operator_properties_select_all(struct wmOperatorType *ot);
void WM_operator_properties_select_action(struct wmOperatorType *ot,
@@ -841,16 +864,6 @@ void WM_operator_properties_checker_interval_from_op(struct wmOperator *op,
bool WM_operator_properties_checker_interval_test(const struct CheckerIntervalParams *op_params,
int depth);
-/* flags for WM_operator_properties_filesel */
-#define WM_FILESEL_RELPATH (1 << 0)
-
-#define WM_FILESEL_DIRECTORY (1 << 1)
-#define WM_FILESEL_FILENAME (1 << 2)
-#define WM_FILESEL_FILEPATH (1 << 3)
-#define WM_FILESEL_FILES (1 << 4)
-/* Show the properties sidebar by default. */
-#define WM_FILESEL_SHOW_PROPS (1 << 5)
-
/**
* Operator as a Python command (resulting string must be freed).
*
diff --git a/source/blender/windowmanager/gizmo/intern/wm_gizmo_group.c b/source/blender/windowmanager/gizmo/intern/wm_gizmo_group.c
index 00615d9d662..d7b54129caa 100644
--- a/source/blender/windowmanager/gizmo/intern/wm_gizmo_group.c
+++ b/source/blender/windowmanager/gizmo/intern/wm_gizmo_group.c
@@ -1130,7 +1130,12 @@ void WM_gizmo_group_refresh(const bContext *C, wmGizmoGroup *gzgroup)
const wmGizmoGroupType *gzgt = gzgroup->type;
if (gzgt->flag & WM_GIZMOGROUPTYPE_DELAY_REFRESH_FOR_TWEAK) {
wmGizmoMap *gzmap = gzgroup->parent_gzmap;
- wmGizmo *gz = wm_gizmomap_highlight_get(gzmap);
+ wmGizmo *gz = NULL;
+ /* Without the check for refresh, any highlighted gizmo will prevent hiding
+ * when selecting with RMB when the cursor happens to be over a gizmo. */
+ if ((gzgroup->init_flag & WM_GIZMOGROUP_INIT_REFRESH) == 0) {
+ gz = wm_gizmomap_highlight_get(gzmap);
+ }
if (!gz || gz->parent_gzgroup != gzgroup) {
wmWindow *win = CTX_wm_window(C);
ARegion *region = CTX_wm_region(C);
diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c
index 60ae4eccbbe..84c40c42adc 100644
--- a/source/blender/windowmanager/intern/wm_event_system.c
+++ b/source/blender/windowmanager/intern/wm_event_system.c
@@ -1297,6 +1297,23 @@ static wmOperator *wm_operator_create(wmWindowManager *wm,
return op;
}
+/**
+ * This isn't very nice but needed to redraw gizmos which are hidden while tweaking,
+ * See #WM_GIZMOGROUPTYPE_DELAY_REFRESH_FOR_TWEAK for details.
+ */
+static void wm_region_tag_draw_on_gizmo_delay_refresh_for_tweak(wmWindow *win, bScreen *screen)
+{
+ ED_screen_areas_iter (win, screen, area) {
+ LISTBASE_FOREACH (ARegion *, region, &area->regionbase) {
+ if (region->gizmo_map != NULL) {
+ if (WM_gizmomap_tag_delay_refresh_for_tweak_check(region->gizmo_map)) {
+ ED_region_tag_redraw(region);
+ }
+ }
+ }
+ }
+}
+
static void wm_region_mouse_co(bContext *C, wmEvent *event)
{
ARegion *region = CTX_wm_region(C);
@@ -3711,6 +3728,7 @@ void wm_event_do_handlers(bContext *C)
event->flag |= WM_EVENT_FORCE_DRAG_THRESHOLD;
}
}
+ const bool event_queue_check_drag_prev = win->event_queue_check_drag;
/* Active screen might change during handlers, update pointer. */
screen = WM_window_get_active_screen(win);
@@ -3870,6 +3888,10 @@ void wm_event_do_handlers(bContext *C)
win->event_queue_check_drag_handled = false;
}
+ if (event_queue_check_drag_prev && (win->event_queue_check_drag == false)) {
+ wm_region_tag_draw_on_gizmo_delay_refresh_for_tweak(win, screen);
+ }
+
/* Update previous mouse position for following events to use. */
copy_v2_v2_int(win->eventstate->prev_xy, event->xy);
diff --git a/source/blender/windowmanager/intern/wm_files.c b/source/blender/windowmanager/intern/wm_files.c
index 1369ee99cd2..d398b255502 100644
--- a/source/blender/windowmanager/intern/wm_files.c
+++ b/source/blender/windowmanager/intern/wm_files.c
@@ -873,7 +873,7 @@ static void file_read_reports_finalize(BlendFileReadReport *bf_reports)
RPT_WARNING,
"Proxies have been removed from Blender (%d proxies were automatically converted "
"to library overrides, %d proxies could not be converted and were cleared). "
- "Please also consider re-saving any library .blend file with the newest Blender version.",
+ "Please also consider re-saving any library .blend file with the newest Blender version",
bf_reports->count.proxies_to_lib_overrides_success,
bf_reports->count.proxies_to_lib_overrides_failures);
}
diff --git a/source/blender/windowmanager/intern/wm_operator_props.c b/source/blender/windowmanager/intern/wm_operator_props.c
index dacc17c2c1e..c048b64426a 100644
--- a/source/blender/windowmanager/intern/wm_operator_props.c
+++ b/source/blender/windowmanager/intern/wm_operator_props.c
@@ -58,12 +58,12 @@ static const EnumPropertyItem *wm_operator_properties_filesel_sort_items_itemf(
}
void WM_operator_properties_filesel(wmOperatorType *ot,
- int filter,
- short type,
- short action,
- short flag,
- short display,
- short sort)
+ const int filter,
+ const short type,
+ const eFileSel_Action action,
+ const eFileSel_Flag flag,
+ const short display,
+ const short sort)
{
PropertyRNA *prop;
diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c
index b45c638d7b9..a3d2d38136c 100644
--- a/source/blender/windowmanager/intern/wm_operators.c
+++ b/source/blender/windowmanager/intern/wm_operators.c
@@ -588,7 +588,13 @@ char *WM_context_path_resolve_property_full(const bContext *C,
if (data_path != NULL) {
if (prop != NULL) {
char *prop_str = RNA_path_property_py(ptr, prop, index);
- member_id_data_path = BLI_string_join_by_sep_charN('.', member_id, data_path, prop_str);
+ if (prop_str[0] == '[') {
+ member_id_data_path = BLI_string_joinN(member_id, ".", data_path, prop_str);
+ }
+ else {
+ member_id_data_path = BLI_string_join_by_sep_charN(
+ '.', member_id, data_path, prop_str);
+ }
MEM_freeN(prop_str);
}
else {
@@ -600,7 +606,12 @@ char *WM_context_path_resolve_property_full(const bContext *C,
else {
if (prop != NULL) {
char *prop_str = RNA_path_property_py(ptr, prop, index);
- member_id_data_path = BLI_string_join_by_sep_charN('.', member_id, prop_str);
+ if (prop_str[0] == '[') {
+ member_id_data_path = BLI_string_joinN(member_id, prop_str);
+ }
+ else {
+ member_id_data_path = BLI_string_join_by_sep_charN('.', member_id, prop_str);
+ }
MEM_freeN(prop_str);
}
else {
diff --git a/tests/python/cycles_render_tests.py b/tests/python/cycles_render_tests.py
index 598e4b6828c..10ba2ce552a 100644
--- a/tests/python/cycles_render_tests.py
+++ b/tests/python/cycles_render_tests.py
@@ -32,6 +32,11 @@ BLACKLIST_OPTIX = [
'T43865.blend',
]
+BLACKLIST_METAL = [
+ # No MNEE for Metal currently
+ "underwater_caustics.blend",
+]
+
BLACKLIST_GPU = [
# Uninvestigated differences with GPU.
'image_log.blend',
@@ -116,6 +121,8 @@ def main():
blacklist += BLACKLIST_OSL
if device == 'OPTIX':
blacklist += BLACKLIST_OPTIX
+ if device == 'METAL':
+ blacklist += BLACKLIST_METAL
from modules import render_report
report = render_report.Report('Cycles', output_dir, idiff, device, blacklist)