diff --git a/CMakeLists.txt b/CMakeLists.txt index 84d4424ec42..a35d267513e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -761,6 +761,18 @@ option(WITH_GTESTS "Enable GTest unit testing" OFF) option(WITH_OPENGL_RENDER_TESTS "Enable OpenGL render related unit testing (Experimental)" OFF) option(WITH_OPENGL_DRAW_TESTS "Enable OpenGL UI drawing related unit testing (Experimental)" OFF) option(WITH_COMPOSITOR_REALTIME_TESTS "Enable regression testing for realtime compositor" OFF) +if(UNIX AND NOT (APPLE OR HAIKU)) + option(WITH_UI_TESTS "\ +Enable user-interface tests using a headless display server. \ +Currently this depends on WITH_GHOST_WAYLAND and the weston compositor \ +(Experimental)" + OFF + ) +else() + # TODO: support running GUI tests on other platforms. + set(WITH_UI_TESTS OFF) +endif() + # NOTE: All callers of this must add `TEST_PYTHON_EXE_EXTRA_ARGS` before any other arguments. set(TEST_PYTHON_EXE "" CACHE PATH "Python executable to run unit tests") mark_as_advanced(TEST_PYTHON_EXE) @@ -1156,6 +1168,10 @@ endif() set_and_warn_incompatible(WITH_HEADLESS WITH_XR_OPENXR OFF) set_and_warn_incompatible(WITH_GHOST_SDL WITH_XR_OPENXR OFF) +if(WITH_UI_TESTS) + set_and_warn_dependency(WITH_GHOST_WAYLAND WITH_UI_TESTS OFF) +endif() + if(WITH_BUILDINFO) find_package(Git) set_and_warn_library_found("Git" GIT_FOUND WITH_BUILDINFO) diff --git a/build_files/build_environment/CMakeLists.txt b/build_files/build_environment/CMakeLists.txt index 0f705d7f501..4e3875be070 100644 --- a/build_files/build_environment/CMakeLists.txt +++ b/build_files/build_environment/CMakeLists.txt @@ -168,6 +168,7 @@ if(UNIX AND NOT APPLE) # Can be removed when the build-bot upgrades to v1.20.x or newer. include(cmake/wayland.cmake) include(cmake/wayland_libdecor.cmake) + include(cmake/wayland_weston.cmake) endif() include(cmake/shaderc_deps.cmake) include(cmake/shaderc.cmake) diff --git a/build_files/build_environment/cmake/download.cmake b/build_files/build_environment/cmake/download.cmake index 58058b60a19..f1c04ba6ef8 100644 --- a/build_files/build_environment/cmake/download.cmake +++ b/build_files/build_environment/cmake/download.cmake @@ -137,6 +137,7 @@ download_source(XR_OPENXR_SDK) download_source(WL_PROTOCOLS) download_source(WAYLAND) download_source(WAYLAND_LIBDECOR) +download_source(WAYLAND_WESTON) download_source(ISPC) download_source(GMP) download_source(POTRACE) diff --git a/build_files/build_environment/cmake/harvest.cmake b/build_files/build_environment/cmake/harvest.cmake index ebfbe9b4223..61a8745892e 100644 --- a/build_files/build_environment/cmake/harvest.cmake +++ b/build_files/build_environment/cmake/harvest.cmake @@ -191,6 +191,14 @@ else() harvest(wayland/bin wayland/bin "wayland-scanner") harvest(wayland/include wayland/include "*.h") harvest(wayland_libdecor/include wayland_libdecor/include "*.h") + # Only needed for running the WESTON compositor. + harvest(wayland/lib64 wayland/lib64 "*") + + harvest( + wayland_weston/ + wayland_weston/ + "*" + ) else() harvest(blosc/lib openvdb/lib "*.a") harvest(xml2/lib opencollada/lib "*.a") diff --git a/build_files/build_environment/cmake/ssl.cmake b/build_files/build_environment/cmake/ssl.cmake index dff24addf00..12df8ea0e14 100644 --- a/build_files/build_environment/cmake/ssl.cmake +++ b/build_files/build_environment/cmake/ssl.cmake @@ -37,16 +37,14 @@ else() PREFIX ${BUILD_DIR}/ssl CONFIGURE_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/ssl/src/external_ssl/ && ${SSL_CONFIGURE_COMMAND} --prefix=${LIBDIR}/ssl --openssldir=${LIBDIR}/ssl - # Without this: Python will use the build directories: - # To see these values in use, check the output of `ssl.get_default_verify_paths()`. - # This definition causes the following values to be set: - # - `capath='/etc/ssl/certs'` - # - `openssl_cafile='/etc/ssl/cert.pem'` - # - `openssl_capath='/etc/ssl/certs'` - # Note that the output from the command `openssl info -configdir` on the users system - # would be ideal but this is more involved. + # Without this: Python will use the build directories. + # using the system directory `/etc/ssl` might seem the obvious choice, + # there is no guarantee the version of SSL used with Blender is compatible with the systems, + # where changes to the SSL configuration format can cause SSL not to load (see #114452). + # So reference a directory known not to exist. Ideally Blender could distribute it's own SSL + # directory, but this isn't compatible with hard coded paths. # See #111132 & https://github.com/openssl/openssl/issues/20185 for details. - -DOPENSSLDIR=\\"/etc/ssl\\" + -DOPENSSLDIR=\\"/dev/null\\" no-shared no-idea no-mdc2 no-rc5 no-zlib no-ssl3 enable-unit-test no-ssl3-method enable-rfc3779 enable-cms --config=${CMAKE_CURRENT_SOURCE_DIR}/cmake/ssl.conf diff --git a/build_files/build_environment/cmake/versions.cmake b/build_files/build_environment/cmake/versions.cmake index e5ce66e7acb..893c398cac1 100644 --- a/build_files/build_environment/cmake/versions.cmake +++ b/build_files/build_environment/cmake/versions.cmake @@ -574,6 +574,13 @@ set(WAYLAND_LIBDECOR_HASH 47b59eba76faa3787f0878bf8700e912) set(WAYLAND_LIBDECOR_HASH_TYPE MD5) set(WAYLAND_LIBDECOR_HOMEPAGE https://gitlab.freedesktop.org/libdecor/libdecor) +set(WAYLAND_WESTON_VERSION 12.0.92) +set(WAYLAND_WESTON_FILE weston-${WAYLAND_WESTON_VERSION}.tar.xz) +set(WAYLAND_WESTON_URI https://gitlab.freedesktop.org/wayland/weston/-/releases/${WAYLAND_WESTON_VERSION}/downloads/weston-${WAYLAND_WESTON_VERSION}.tar.xz) +set(WAYLAND_WESTON_HASH 44542b60bf9b9fe3add904af11bbad98) +set(WAYLAND_WESTON_HASH_TYPE MD5) +set(WAYLAND_WESTON_HOMEPAGE https://wayland.freedesktop.org) + set(ISPC_VERSION v1.17.0) set(ISPC_URI https://github.com/ispc/ispc/archive/${ISPC_VERSION}.tar.gz) set(ISPC_HASH 4f476a3109332a77fe839a9014c60ca9) diff --git a/build_files/build_environment/cmake/wayland_weston.cmake b/build_files/build_environment/cmake/wayland_weston.cmake new file mode 100644 index 00000000000..ff97f4222b9 --- /dev/null +++ b/build_files/build_environment/cmake/wayland_weston.cmake @@ -0,0 +1,65 @@ +# SPDX-FileCopyrightText: 2023 Blender Authors +# +# SPDX-License-Identifier: GPL-2.0-or-later + +set(WAYLAND_WESTON_CONFIGURE_ENV ${CONFIGURE_ENV}) +set(WAYLAND_WESTON_PKG_ENV "PKG_CONFIG_PATH=\ +${LIBDIR}/wayland/lib64/pkgconfig:\ +${LIBDIR}/wayland-protocols/share/pkgconfig:\ +$PKG_CONFIG_PATH" +) + +ExternalProject_Add(external_wayland_weston + URL file://${PACKAGE_DIR}/${WAYLAND_WESTON_FILE} + URL_HASH ${WAYLAND_WESTON_HASH_TYPE}=${WAYLAND_WESTON_HASH} + DOWNLOAD_DIR ${DOWNLOAD_DIR} + PREFIX ${BUILD_DIR}/wayland_weston + + # Notes: + # - Disable nearly everything as only a simple headless server is needed for testing. + # - Keep X11 and WAYLAND back-ends enabled so it's possible + # to run the instance inside existing X11/WAYLAND sessions (for debugging). + CONFIGURE_COMMAND ${WAYLAND_WESTON_CONFIGURE_ENV} && + ${CMAKE_COMMAND} -E env ${WAYLAND_WESTON_PKG_ENV} + ${MESON} setup + ${MESON_BUILD_TYPE} + --prefix ${LIBDIR}/wayland_weston + --libdir lib + -Dbackend-default=headless # For tests. + -Dbackend-drm-screencast-vaapi=false + -Dbackend-drm=false + -Dbackend-pipewire=false + -Dbackend-rdp=false + -Dbackend-vnc=false + -Dcolor-management-lcms=false + -Ddemo-clients=false + -Ddoc=false + -Dimage-jpeg=false + -Dimage-webp=false + -Dpipewire=false + -Dremoting=false + -Dscreenshare=false + -Dshell-fullscreen=false + -Dshell-ivi=false + -Dshell-kiosk=false + -Dsimple-clients= + -Dsystemd=false + -Dtest-junit-xml=false + -Dtools= + -Dwcap-decode=false + -Dxwayland=false + ${BUILD_DIR}/wayland_weston/src/external_wayland_weston-build + ${BUILD_DIR}/wayland_weston/src/external_wayland_weston + + BUILD_COMMAND ninja + INSTALL_COMMAND ninja install + INSTALL_DIR ${LIBDIR}/wayland_weston +) + +add_dependencies( + external_wayland_weston + external_wayland_protocols + external_wayland + # Needed for `MESON`. + external_python_site_packages +) diff --git a/build_files/build_environment/linux/linux_rocky8_setup.sh b/build_files/build_environment/linux/linux_rocky8_setup.sh index 51dbe814157..b89d5726804 100644 --- a/build_files/build_environment/linux/linux_rocky8_setup.sh +++ b/build_files/build_environment/linux/linux_rocky8_setup.sh @@ -109,6 +109,20 @@ PACKAGES_FOR_LIBS=( # Required by: `external_ssl` (build dependencies). perl-IPC-Cmd perl-Pod-Html + + # Required by: `external_wayland_weston` + cairo-devel + libdrm-devel + pixman-devel + libffi-devel + libinput-devel + libevdev-devel + mesa-libEGL-devel + systemd-dev # for `libudev` (not so obvious!). + # Required by: `weston --headless` (run-time requirement for off screen rendering). + mesa-dri-drivers + mesa-libEGL + mesa-libGL ) # Additional packages needed for building Blender. diff --git a/intern/cycles/blender/addon/properties.py b/intern/cycles/blender/addon/properties.py index 7ddbb90b35a..8cbfc0a98b9 100644 --- a/intern/cycles/blender/addon/properties.py +++ b/intern/cycles/blender/addon/properties.py @@ -1013,12 +1013,6 @@ class CyclesMaterialSettings(bpy.types.PropertyGroup): default="AUTO", ) - use_transparent_shadow: BoolProperty( - name="Transparent Shadows", - description="Use transparent shadows for this material if it contains a Transparent BSDF, " - "disabling will render faster but not give accurate shadows", - default=True, - ) use_bump_map_correction: BoolProperty( name="Bump Map Correction", description="Apply corrections to solve shadow terminator artifacts caused by bump mapping", diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py index 749d32cc52a..01c88272944 100644 --- a/intern/cycles/blender/addon/ui.py +++ b/intern/cycles/blender/addon/ui.py @@ -1966,7 +1966,7 @@ class CYCLES_MATERIAL_PT_settings_surface(CyclesButtonsPanel, Panel): col = layout.column() col.prop(cmat, "displacement_method", text="Displacement") col.prop(cmat, "emission_sampling") - col.prop(cmat, "use_transparent_shadow") + col.prop(mat, "use_transparent_shadow") col.prop(cmat, "use_bump_map_correction") def draw(self, context): diff --git a/intern/cycles/blender/shader.cpp b/intern/cycles/blender/shader.cpp index 7e131ea9749..7c8c63299a5 100644 --- a/intern/cycles/blender/shader.cpp +++ b/intern/cycles/blender/shader.cpp @@ -1550,7 +1550,7 @@ void BlenderSync::sync_materials(BL::Depsgraph &b_depsgraph, bool update_all) /* settings */ PointerRNA cmat = RNA_pointer_get(&b_mat.ptr, "cycles"); shader->set_emission_sampling_method(get_emission_sampling(cmat)); - shader->set_use_transparent_shadow(get_boolean(cmat, "use_transparent_shadow")); + shader->set_use_transparent_shadow(b_mat.use_transparent_shadow()); shader->set_use_bump_map_correction(get_boolean(cmat, "use_bump_map_correction")); shader->set_heterogeneous_volume(!get_boolean(cmat, "homogeneous_volume")); shader->set_volume_sampling_method(get_volume_sampling(cmat)); diff --git a/intern/cycles/device/metal/bvh.h b/intern/cycles/device/metal/bvh.h index 75d8e326941..46c810c9b72 100644 --- a/intern/cycles/device/metal/bvh.h +++ b/intern/cycles/device/metal/bvh.h @@ -19,6 +19,9 @@ class BVHMetal : public BVH { API_AVAILABLE(macos(11.0)) id accel_struct = nil; + API_AVAILABLE(macos(11.0)) + id null_BLAS = nil; + API_AVAILABLE(macos(11.0)) vector> blas_array; diff --git a/intern/cycles/device/metal/bvh.mm b/intern/cycles/device/metal/bvh.mm index a4de673a0f5..45780b4f166 100644 --- a/intern/cycles/device/metal/bvh.mm +++ b/intern/cycles/device/metal/bvh.mm @@ -124,6 +124,10 @@ BVHMetal::~BVHMetal() stats.mem_free(accel_struct.allocatedSize); [accel_struct release]; } + + if (null_BLAS) { + [null_BLAS release]; + } } } @@ -964,6 +968,60 @@ bool BVHMetal::build_TLAS(Progress &progress, g_bvh_build_throttler.wait_for_all(); if (@available(macos 12.0, *)) { + /* Defined inside available check, for return type to be available. */ + auto make_null_BLAS = [](id device, + id queue) -> id { + MTLResourceOptions storage_mode = MTLResourceStorageModeManaged; + if (device.hasUnifiedMemory) { + storage_mode = MTLResourceStorageModeShared; + } + + id nullBuf = [device newBufferWithLength:0 options:storage_mode]; + + /* Create an acceleration structure. */ + MTLAccelerationStructureTriangleGeometryDescriptor *geomDesc = + [MTLAccelerationStructureTriangleGeometryDescriptor descriptor]; + geomDesc.vertexBuffer = nullBuf; + geomDesc.vertexBufferOffset = 0; + geomDesc.vertexStride = sizeof(float3); + geomDesc.indexBuffer = nullBuf; + geomDesc.indexBufferOffset = 0; + geomDesc.indexType = MTLIndexTypeUInt32; + geomDesc.triangleCount = 0; + geomDesc.intersectionFunctionTableOffset = 0; + geomDesc.opaque = true; + geomDesc.allowDuplicateIntersectionFunctionInvocation = false; + + MTLPrimitiveAccelerationStructureDescriptor *accelDesc = + [MTLPrimitiveAccelerationStructureDescriptor descriptor]; + accelDesc.geometryDescriptors = @[ geomDesc ]; + accelDesc.usage |= MTLAccelerationStructureUsageExtendedLimits; + + MTLAccelerationStructureSizes accelSizes = [device + accelerationStructureSizesWithDescriptor:accelDesc]; + id accel_struct = [device + newAccelerationStructureWithSize:accelSizes.accelerationStructureSize]; + id scratchBuf = [device newBufferWithLength:accelSizes.buildScratchBufferSize + options:MTLResourceStorageModePrivate]; + id sizeBuf = [device newBufferWithLength:8 options:MTLResourceStorageModeShared]; + id accelCommands = [queue commandBuffer]; + id accelEnc = + [accelCommands accelerationStructureCommandEncoder]; + [accelEnc buildAccelerationStructure:accel_struct + descriptor:accelDesc + scratchBuffer:scratchBuf + scratchBufferOffset:0]; + [accelEnc endEncoding]; + [accelCommands commit]; + [accelCommands waitUntilCompleted]; + + /* free temp resources */ + [scratchBuf release]; + [nullBuf release]; + [sizeBuf release]; + + return accel_struct; + }; uint32_t num_instances = 0; uint32_t num_motion_transforms = 0; @@ -1005,7 +1063,7 @@ bool BVHMetal::build_TLAS(Progress &progress, int blas_index = (int)[all_blas count]; instance_mapping[blas] = blas_index; if (@available(macos 12.0, *)) { - [all_blas addObject:blas->accel_struct]; + [all_blas addObject:(blas ? blas->accel_struct : null_BLAS)]; } return blas_index; } @@ -1052,22 +1110,18 @@ bool BVHMetal::build_TLAS(Progress &progress, if (!blas || !blas->accel_struct) { /* Place a degenerate instance, to ensure [[instance_id]] equals ob->get_device_index() * in our intersection functions */ - if (motion_blur) { - MTLAccelerationStructureMotionInstanceDescriptor *instances = - (MTLAccelerationStructureMotionInstanceDescriptor *)[instanceBuf contents]; - MTLAccelerationStructureMotionInstanceDescriptor &desc = instances[instance_index++]; - memset(&desc, 0x00, sizeof(desc)); + blas = nullptr; + + /* Workaround for issue in macOS <= 14.1: Insert degenerate BLAS instead of zero-filling + * the descriptor. */ + if (!null_BLAS) { + null_BLAS = make_null_BLAS(device, queue); } - else { - MTLAccelerationStructureUserIDInstanceDescriptor *instances = - (MTLAccelerationStructureUserIDInstanceDescriptor *)[instanceBuf contents]; - MTLAccelerationStructureUserIDInstanceDescriptor &desc = instances[instance_index++]; - memset(&desc, 0x00, sizeof(desc)); - } - blas_array.push_back(nil); - continue; + blas_array.push_back(null_BLAS); + } + else { + blas_array.push_back(blas->accel_struct); } - blas_array.push_back(blas->accel_struct); uint32_t accel_struct_index = get_blas_index(blas); diff --git a/intern/cycles/device/metal/device_impl.mm b/intern/cycles/device/metal/device_impl.mm index bf409ed4d33..1da437798da 100644 --- a/intern/cycles/device/metal/device_impl.mm +++ b/intern/cycles/device/metal/device_impl.mm @@ -343,6 +343,11 @@ string MetalDevice::preprocess_source(MetalPipelineType pso_type, } } + if (@available(macos 14.0, *)) { + /* Use Program Scope Global Built-ins, when available. */ + global_defines += "#define __METAL_GLOBAL_BUILTINS__\n"; + } + # ifdef WITH_CYCLES_DEBUG global_defines += "#define __KERNEL_DEBUG__\n"; # endif diff --git a/intern/cycles/kernel/device/metal/compat.h b/intern/cycles/kernel/device/metal/compat.h index 8e2e0e342ee..ccd47455dc3 100644 --- a/intern/cycles/kernel/device/metal/compat.h +++ b/intern/cycles/kernel/device/metal/compat.h @@ -108,6 +108,31 @@ using namespace metal::raytracing; /* Generate a struct containing the entry-point parameters and a "run" * method which can access them implicitly via this-> */ + +#ifdef __METAL_GLOBAL_BUILTINS__ + +#define ccl_gpu_kernel_signature(name, ...) \ +struct kernel_gpu_##name \ +{ \ + PARAMS_MAKER(__VA_ARGS__)(__VA_ARGS__) \ + void run(thread MetalKernelContext& context, \ + threadgroup atomic_int *threadgroup_array) ccl_global const; \ +}; \ +kernel void cycles_metal_##name(device const kernel_gpu_##name *params_struct, \ + constant KernelParamsMetal &ccl_restrict _launch_params_metal, \ + constant MetalAncillaries *_metal_ancillaries, \ + threadgroup atomic_int *threadgroup_array[[ threadgroup(0) ]]) { \ + MetalKernelContext context(_launch_params_metal, _metal_ancillaries); \ + params_struct->run(context, threadgroup_array); \ +} \ +void kernel_gpu_##name::run(thread MetalKernelContext& context, \ + threadgroup atomic_int *threadgroup_array) ccl_global const + +#else + +/* On macOS versions before 14.x, builtin constants (e.g. metal_global_id) must + * be accessed through attributed entrypoint parameters. */ + #define ccl_gpu_kernel_signature(name, ...) \ struct kernel_gpu_##name \ { \ @@ -149,6 +174,8 @@ void kernel_gpu_##name::run(thread MetalKernelContext& context, \ uint simd_group_index, \ uint num_simd_groups) ccl_global const +#endif /* __METAL_GLOBAL_BUILTINS__ */ + #define ccl_gpu_kernel_postfix #define ccl_gpu_kernel_call(x) context.x #define ccl_gpu_kernel_within_bounds(i,n) true @@ -365,3 +392,14 @@ constant constexpr array metal_samplers = { sampler(address::clamp_to_zero, filter::linear), sampler(address::mirrored_repeat, filter::linear), }; + +#ifdef __METAL_GLOBAL_BUILTINS__ +const uint metal_global_id [[thread_position_in_grid]]; +const ushort metal_local_id [[thread_position_in_threadgroup]]; +const ushort metal_local_size [[threads_per_threadgroup]]; +const uint metal_grid_id [[threadgroup_position_in_grid]]; +const uint simdgroup_size [[threads_per_simdgroup]]; +const uint simd_lane_index [[thread_index_in_simdgroup]]; +const uint simd_group_index [[simdgroup_index_in_threadgroup]]; +const uint num_simd_groups [[simdgroups_per_threadgroup]]; +#endif /* __METAL_GLOBAL_BUILTINS__ */ \ No newline at end of file diff --git a/intern/ghost/intern/GHOST_SystemWayland.cc b/intern/ghost/intern/GHOST_SystemWayland.cc index 819862d240f..cee553a46e8 100644 --- a/intern/ghost/intern/GHOST_SystemWayland.cc +++ b/intern/ghost/intern/GHOST_SystemWayland.cc @@ -726,7 +726,7 @@ static void gwl_primary_selection_discard_source(GWL_PrimarySelection *primary) #ifdef WITH_INPUT_IME struct GWL_SeatIME { - struct wl_surface *surface_window = nullptr; + wl_surface *surface_window = nullptr; GHOST_TEventImeData event_ime_data = { /*result_len*/ nullptr, /*composite_len*/ nullptr, @@ -806,7 +806,7 @@ struct GWL_Seat { std::unordered_set tablet_tools; #ifdef WITH_INPUT_IME - struct zwp_text_input_v3 *text_input = nullptr; + zwp_text_input_v3 *text_input = nullptr; #endif } wp; @@ -1063,7 +1063,7 @@ struct GWL_Display { zwp_pointer_constraints_v1 *pointer_constraints = nullptr; zwp_pointer_gestures_v1 *pointer_gestures = nullptr; #ifdef WITH_INPUT_IME - struct zwp_text_input_manager_v3 *text_input_manager = nullptr; + zwp_text_input_manager_v3 *text_input_manager = nullptr; #endif } wp; @@ -4566,7 +4566,7 @@ static CLG_LogRef LOG_WL_TEXT_INPUT = {"ghost.wl.handle.text_input"}; static void text_input_handle_enter(void *data, zwp_text_input_v3 * /*zwp_text_input_v3*/, - struct wl_surface *surface) + wl_surface *surface) { if (!ghost_wl_surface_own(surface)) { return; @@ -4578,7 +4578,7 @@ static void text_input_handle_enter(void *data, static void text_input_handle_leave(void *data, zwp_text_input_v3 * /*zwp_text_input_v3*/, - struct wl_surface *surface) + wl_surface *surface) { /* Can be null when closing a window. */ if (!ghost_wl_surface_own_with_null_check(surface)) { @@ -4747,7 +4747,7 @@ static void text_input_handle_done(void *data, seat->ime.has_commit_string_callback = false; } -static struct zwp_text_input_v3_listener text_input_listener = { +static zwp_text_input_v3_listener text_input_listener = { /*enter*/ text_input_handle_enter, /*leave*/ text_input_handle_leave, /*preedit_string*/ text_input_handle_preedit_string, @@ -5773,7 +5773,7 @@ static void gwl_registry_wp_text_input_manager_remove(GWL_Display *display, void * /*user_data*/, const bool /*on_exit*/) { - struct zwp_text_input_manager_v3 **value_p = &display->wp.text_input_manager; + zwp_text_input_manager_v3 **value_p = &display->wp.text_input_manager; zwp_text_input_manager_v3_destroy(*value_p); *value_p = nullptr; } diff --git a/release/freedesktop/org.blender.Blender.appdata.xml b/release/freedesktop/org.blender.Blender.metainfo.xml similarity index 96% rename from release/freedesktop/org.blender.Blender.appdata.xml rename to release/freedesktop/org.blender.Blender.metainfo.xml index bfa2cf49733..dc3833beb06 100644 --- a/release/freedesktop/org.blender.Blender.appdata.xml +++ b/release/freedesktop/org.blender.Blender.metainfo.xml @@ -22,20 +22,28 @@

https://www.blender.org + https://projects.blender.org/blender/blender/issues?q=&labels=296 + https://www.blender.org/support/faq/ https://www.blender.org/support/ - https://developer.blender.org - https://www.blender.org/foundation/donation-payment/ + https://fund.blender.org/ + https://wiki.blender.org/wiki/Process/Translate_Blender + https://projects.blender.org/blender/blender + https://www.blender.org/get-involved/ + Sculpt https://download.blender.org/demo/screenshots/blender_screenshot_1.jpg + Model https://download.blender.org/demo/screenshots/blender_screenshot_2.jpg + Animate https://download.blender.org/demo/screenshots/blender_screenshot_3.jpg + Edit & Grade https://download.blender.org/demo/screenshots/blender_screenshot_4.jpg @@ -377,5 +385,6 @@ - + + diff --git a/scripts/modules/bl_i18n_utils/bl_extract_messages.py b/scripts/modules/bl_i18n_utils/bl_extract_messages.py index ea9664b3da9..634572d0bdc 100644 --- a/scripts/modules/bl_i18n_utils/bl_extract_messages.py +++ b/scripts/modules/bl_i18n_utils/bl_extract_messages.py @@ -941,6 +941,14 @@ def dump_asset_messages(msgs, reports, settings): # Parse the asset blend files asset_files = {} + # Store assets according to this structure: + # {"basename": [ + # {"name": "Name", + # "description": "Description", + # "sockets": [ + # ("Name", "Description"), + # ]}, + # ]} bfiles = glob.glob(assets_dir + "/**/*.blend", recursive=True) for bfile in bfiles: @@ -953,11 +961,18 @@ def dump_asset_messages(msgs, reports, settings): if asset.asset_data is None: # Not an asset continue assets = asset_files.setdefault(basename, []) - assets.append((asset.name, asset.asset_data.description)) + asset_data = {"name": asset.name, + "description": asset.asset_data.description} + for interface in asset.interface.items_tree: + if interface.name == "Geometry": # Ignore common socket + continue + socket_data = asset_data.setdefault("sockets", []) + socket_data.append((interface.name, interface.description)) + assets.append(asset_data) for asset_file in sorted(asset_files): - for asset in sorted(asset_files[asset_file]): - name, description = asset + for asset in sorted(asset_files[asset_file], key=lambda a: a["name"]): + name, description = asset["name"], asset["description"] msgsrc = "Asset name from file " + asset_file process_msg(msgs, settings.DEFAULT_CONTEXT, name, msgsrc, reports, None, settings) @@ -965,6 +980,15 @@ def dump_asset_messages(msgs, reports, settings): process_msg(msgs, settings.DEFAULT_CONTEXT, description, msgsrc, reports, None, settings) + if "sockets" in asset: + for socket_name, socket_description in asset["sockets"]: + msgsrc = f"Socket name from node group {name}, file {asset_file}" + process_msg(msgs, settings.DEFAULT_CONTEXT, socket_name, msgsrc, + reports, None, settings) + msgsrc = f"Socket description from node group {name}, file {asset_file}" + process_msg(msgs, settings.DEFAULT_CONTEXT, socket_description, msgsrc, + reports, None, settings) + def dump_addon_bl_info(msgs, reports, module, settings): for prop in ('name', 'location', 'description', 'warning'): diff --git a/scripts/startup/bl_ui/node_add_menu_shader.py b/scripts/startup/bl_ui/node_add_menu_shader.py index b181dc50b19..4840da4c915 100644 --- a/scripts/startup/bl_ui/node_add_menu_shader.py +++ b/scripts/startup/bl_ui/node_add_menu_shader.py @@ -323,6 +323,21 @@ class NODE_MT_category_shader_vector(Menu): node_add_menu.draw_assets_for_catalog(layout, self.bl_label) +class NODE_MT_category_goo_engine(Menu): + bl_idname = "NODE_MT_category_goo_engine" + bl_label = "Goo Engine" + + def draw(self, _context): + layout = self.layout + node_add_menu.add_node_type(layout, "ShaderNodeShaderInfo") + node_add_menu.add_node_type(layout, "ShaderNodeScreenspaceInfo") + node_add_menu.add_node_type(layout, "ShaderNodeCurvature") + node_add_menu.add_node_type(layout, "ShaderNodeSetDepth") + node_add_menu.add_node_type(layout, "ShaderNodeSdfPrimitive") + node_add_menu.add_node_type(layout, "ShaderNodeSdfOp") + node_add_menu.add_node_type(layout, "ShaderNodeSdfVectorOp") + node_add_menu.add_node_type(layout, "ShaderNodeSdfNoise") + class NODE_MT_category_shader_script(Menu): bl_idname = "NODE_MT_category_shader_script" bl_label = "Script" @@ -359,6 +374,7 @@ class NODE_MT_shader_node_add_all(Menu): layout.menu("NODE_MT_category_shader_shader") layout.menu("NODE_MT_category_shader_texture") layout.menu("NODE_MT_category_shader_vector") + layout.menu("NODE_MT_category_goo_engine") layout.separator() layout.menu("NODE_MT_category_shader_script") layout.separator() @@ -377,6 +393,7 @@ classes = ( NODE_MT_category_shader_shader, NODE_MT_category_shader_texture, NODE_MT_category_shader_vector, + NODE_MT_category_goo_engine, NODE_MT_category_shader_script, NODE_MT_category_shader_group, ) diff --git a/scripts/startup/bl_ui/properties_data_bone.py b/scripts/startup/bl_ui/properties_data_bone.py index f818ebf3574..7507287a52b 100644 --- a/scripts/startup/bl_ui/properties_data_bone.py +++ b/scripts/startup/bl_ui/properties_data_bone.py @@ -359,8 +359,8 @@ class BONE_PT_display(BoneButtonsPanel, Panel): row.prop(bone_color.custom, "select", text="") row.prop(bone_color.custom, "active", text="") - if (pchan := context.object.pose.bones[bone.name]) and context.bone: - col.prop(pchan, "hide_outliner", text="Hide in Outliner", toggle=False) + if (pchan := context.object.pose.bones[bone.name]) and context.bone: + col.prop(pchan, "hide_outliner", text="Hide in Outliner", toggle=False) class BONE_PT_display_custom_shape(BoneButtonsPanel, Panel): diff --git a/scripts/startup/bl_ui/properties_material.py b/scripts/startup/bl_ui/properties_material.py index 592be800b75..4b208957e30 100644 --- a/scripts/startup/bl_ui/properties_material.py +++ b/scripts/startup/bl_ui/properties_material.py @@ -301,8 +301,9 @@ class EEVEE_NEXT_MATERIAL_PT_settings_surface(MaterialButtonsPanel, Panel): col.prop(mat, "use_backface_culling", text="Camera") col.prop(mat, "use_backface_culling_shadow", text="Shadow") - # TODO(fclem): Displacement option - # TODO(fclem): Transparent shadow option + layout.prop(mat, "max_vertex_displacement", text="Max Displacement") + + layout.prop(mat, "use_transparent_shadow") col = layout.column() col.prop(mat, "surface_render_method", text="Render Method") diff --git a/scripts/startup/bl_ui/properties_object.py b/scripts/startup/bl_ui/properties_object.py index 900543c5585..1dddc9e229a 100644 --- a/scripts/startup/bl_ui/properties_object.py +++ b/scripts/startup/bl_ui/properties_object.py @@ -390,6 +390,11 @@ class OBJECT_PT_visibility(ObjectButtonsPanel, Panel): col.prop(ob, "hide_render", text="Renders", toggle=False, invert_checkbox=True) if context.engine == 'BLENDER_EEVEE_NEXT': + if ob.type in {'MESH', 'CURVE', 'SURFACE', 'META', 'FONT', 'CURVES', 'POINTCLOUD', 'VOLUME'}: + layout.separator() + col = layout.column(heading="Ray Visibility") + col.prop(ob, "visible_shadow", text="Shadow", toggle=False) + if ob.type in {'MESH', 'CURVE', 'SURFACE', 'META', 'FONT', 'CURVES', 'POINTCLOUD', 'VOLUME', 'LIGHT'}: layout.separator() col = layout.column(heading="Light Probes") diff --git a/scripts/startup/bl_ui/properties_render.py b/scripts/startup/bl_ui/properties_render.py index 735e668c1a3..53b52bd90a4 100644 --- a/scripts/startup/bl_ui/properties_render.py +++ b/scripts/startup/bl_ui/properties_render.py @@ -111,8 +111,8 @@ class RENDER_PT_color_management_display_settings(RenderButtonsPanel, Panel): # Only display HDR toggle for non-Filmic display transforms. col = layout.column(align=True) sub = col.row() - sub.active = (not view.view_transform.startswith("Filmic") and - not view.view_transform.startswith("AgX")) + sub.active = (not view.view_transform.startswith("Filmic") and not view.view_transform.startswith("AgX") and not + view.view_transform.startswith("False Color")) sub.prop(view, "use_hdr_view") diff --git a/scripts/startup/bl_ui/space_userpref.py b/scripts/startup/bl_ui/space_userpref.py index 28934df5d58..fdfff953918 100644 --- a/scripts/startup/bl_ui/space_userpref.py +++ b/scripts/startup/bl_ui/space_userpref.py @@ -1077,7 +1077,7 @@ class USERPREF_PT_theme_text_style(ThemePanel, CenterAlignMixIn, Panel): col = flow.column() col.prop(font_style, "points") - col.prop(font_style, "character_weight", text="Weight") + col.prop(font_style, "character_weight", text="Weight", text_ctxt=i18n_contexts.id_text) col = flow.column(align=True) col.prop(font_style, "shadow_offset_x", text="Shadow Offset X") diff --git a/scripts/startup/goo_engine_file_warning.py b/scripts/startup/goo_engine_file_warning.py deleted file mode 100644 index ff86a29b8c0..00000000000 --- a/scripts/startup/goo_engine_file_warning.py +++ /dev/null @@ -1,62 +0,0 @@ -# ##### BEGIN GPL LICENSE BLOCK ##### -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 2 -# of the License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software Foundation, -# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -# -# ##### END GPL LICENSE BLOCK ##### - -# - -""" -Custom file version warning system, to avoid mistakes with regular blender builds and production files. -""" - -import bpy -from bpy.types import Operator -from bpy.app.handlers import persistent -import os - -script_name = ".version_warning.py" -script_content = """ -import bpy - -def draw_popup_warning(self, context): - self.layout.label(text=f"Warning: file edited in Goo Engine, data may be lost if used in standard Blender!") - -if not bpy.app.version_string.endswith('Goo Engine'): - print("File loaded, not a Goo Engine build!") - bpy.context.window_manager.popup_menu(draw_popup_warning, title="Warning", icon='ERROR') -""" - - -@persistent -def save_handler(_): - if not bpy.context.preferences.filepaths.save_version_warning: - return - text = bpy.data.texts.get(script_name) - if not text: - text = bpy.data.texts.new(script_name) - text.use_module = True - text.clear() - text.write(script_content) - -def register(): - bpy.app.handlers.save_pre.append(save_handler) - -def unregister(): - bpy.app.handlers.save_pre.remove(save_handler) - - -if __name__ == "__main__": - register() \ No newline at end of file diff --git a/source/blender/animrig/ANIM_action.hh b/source/blender/animrig/ANIM_action.hh new file mode 100644 index 00000000000..365aa11d1ad --- /dev/null +++ b/source/blender/animrig/ANIM_action.hh @@ -0,0 +1,33 @@ +/* SPDX-FileCopyrightText: 2023 Blender Authors + * + * SPDX-License-Identifier: GPL-2.0-or-later */ + +/** \file + * \ingroup animrig + * + * \brief Functions to work with Actions. + */ + +#include "RNA_types.hh" + +struct FCurve; +struct bAction; + +namespace blender::animrig { +/** + * Get (or add relevant data to be able to do so) F-Curve from the given Action, + * for the given Animation Data block. This assumes that all the destinations are valid. + */ +FCurve *action_fcurve_ensure(Main *bmain, + bAction *act, + const char group[], + PointerRNA *ptr, + const char rna_path[], + int array_index); + +/** + * Find the F-Curve from the given Action. This assumes that all the destinations are valid. + */ +FCurve *action_fcurve_find(bAction *act, const char rna_path[], int array_index); + +} // namespace blender::animrig \ No newline at end of file diff --git a/source/blender/animrig/ANIM_animdata.hh b/source/blender/animrig/ANIM_animdata.hh new file mode 100644 index 00000000000..7902f036ab2 --- /dev/null +++ b/source/blender/animrig/ANIM_animdata.hh @@ -0,0 +1,31 @@ +/* SPDX-FileCopyrightText: 2023 Blender Authors + * + * SPDX-License-Identifier: GPL-2.0-or-later */ + +/** \file + * \ingroup animrig + * + * \brief Functions to work with AnimData. + */ + +struct bAnimContext; +struct AnimData; +struct FCurve; + +namespace blender::animrig { + +/** + * Delete the F-Curve from the given AnimData block (if possible), + * as appropriate according to animation context. + */ +void animdata_fcurve_delete(bAnimContext *ac, AnimData *adt, FCurve *fcu); + +/** + * Unlink the action from animdata if it's empty. + * + * If the action has no F-Curves, unlink it from AnimData if it did not + * come from a NLA Strip being tweaked. + */ +bool animdata_remove_empty_action(AnimData *adt); + +} // namespace blender::animrig \ No newline at end of file diff --git a/source/blender/animrig/ANIM_armature_iter.hh b/source/blender/animrig/ANIM_armature_iter.hh index 48030f872f2..53288c11388 100644 --- a/source/blender/animrig/ANIM_armature_iter.hh +++ b/source/blender/animrig/ANIM_armature_iter.hh @@ -1,4 +1,4 @@ -/* SPDX-FileCopyrightText: 2023 Blender Foundation +/* SPDX-FileCopyrightText: 2023 Blender Authors * * SPDX-License-Identifier: GPL-2.0-or-later */ diff --git a/source/blender/animrig/ANIM_bone_collections.hh b/source/blender/animrig/ANIM_bone_collections.hh index 57bae41aa58..144670240fc 100644 --- a/source/blender/animrig/ANIM_bone_collections.hh +++ b/source/blender/animrig/ANIM_bone_collections.hh @@ -1,4 +1,4 @@ -/* SPDX-FileCopyrightText: 2023 Blender Foundation +/* SPDX-FileCopyrightText: 2023 Blender Authors * * SPDX-License-Identifier: GPL-2.0-or-later */ diff --git a/source/blender/animrig/ANIM_bonecolor.hh b/source/blender/animrig/ANIM_bonecolor.hh index ba3ddf9140a..c440196e5f5 100644 --- a/source/blender/animrig/ANIM_bonecolor.hh +++ b/source/blender/animrig/ANIM_bonecolor.hh @@ -1,4 +1,4 @@ -/* SPDX-FileCopyrightText: 2023 Blender Foundation +/* SPDX-FileCopyrightText: 2023 Blender Authors * * SPDX-License-Identifier: GPL-2.0-or-later */ diff --git a/source/blender/animrig/ANIM_fcurve.hh b/source/blender/animrig/ANIM_fcurve.hh index 057702c1de2..54c87782891 100644 --- a/source/blender/animrig/ANIM_fcurve.hh +++ b/source/blender/animrig/ANIM_fcurve.hh @@ -1,4 +1,4 @@ -/* SPDX-FileCopyrightText: 2023 Blender Foundation +/* SPDX-FileCopyrightText: 2023 Blender Authors * * SPDX-License-Identifier: GPL-2.0-or-later */ @@ -8,34 +8,51 @@ * \brief Functions to modify FCurves. */ -#include "RNA_types.hh" - +#include "DNA_anim_types.h" struct AnimData; struct FCurve; -struct bAction; namespace blender::animrig { - -/** - * Get (or add relevant data to be able to do so) F-Curve from the given Action, - * for the given Animation Data block. This assumes that all the destinations are valid. - */ -FCurve *action_fcurve_ensure(Main *bmain, - bAction *act, - const char group[], - PointerRNA *ptr, - const char rna_path[], - int array_index); - -/** - * Find the F-Curve from the given Action. This assumes that all the destinations are valid. - */ -FCurve *action_fcurve_find(bAction *act, const char rna_path[], int array_index); - /** * \note The caller needs to run #BKE_nla_tweakedit_remap to get NLA relative frame. * The caller should also check #BKE_fcurve_is_protected before keying. */ bool delete_keyframe_fcurve(AnimData *adt, FCurve *fcu, float cfra); +/** + * \brief Lesser Key-framing API call. + * + * Use this when validation of necessary animation data isn't necessary as it already + * exists, and there is a #BezTriple that can be directly copied into the array. + * + * This function adds a given #BezTriple to an F-Curve. It will allocate + * memory for the array if needed, and will insert the #BezTriple into a + * suitable place in chronological order. + * + * \returns The index of the keyframe array into which the bezt has been added. + * + * \note Any recalculate of the F-Curve that needs to be done will need to be done by the caller. + */ +int insert_bezt_fcurve(FCurve *fcu, const BezTriple *bezt, eInsertKeyFlags flag); + +/** + * \brief Main Key-framing API call. + * + * Use this when validation of necessary animation data isn't necessary as it + * already exists. It will insert a keyframe using the current value being keyframed. + * Returns the index at which a keyframe was added (or -1 if failed). + * + * This function is a wrapper for #insert_bezt_fcurve(), and should be used when + * adding a new keyframe to a curve, when the keyframe doesn't exist anywhere else yet. + * It returns the index at which the keyframe was added. + * + * \returns The index of the keyframe array into which the bezt has been added. + * + * \param keyframe_type: The type of keyframe (#eBezTriple_KeyframeType). + * \param flag: Optional flags (#eInsertKeyFlags) for controlling how keys get added + * and/or whether updates get done. + */ +int insert_vert_fcurve( + FCurve *fcu, float x, float y, eBezTriple_KeyframeType keyframe_type, eInsertKeyFlags flag); + } // namespace blender::animrig diff --git a/source/blender/animrig/ANIM_keyframing.hh b/source/blender/animrig/ANIM_keyframing.hh index b38b2f85f2d..10f003f5204 100644 --- a/source/blender/animrig/ANIM_keyframing.hh +++ b/source/blender/animrig/ANIM_keyframing.hh @@ -1,4 +1,4 @@ -/* SPDX-FileCopyrightText: 2023 Blender Foundation +/* SPDX-FileCopyrightText: 2023 Blender Authors * * SPDX-License-Identifier: GPL-2.0-or-later */ diff --git a/source/blender/animrig/ANIM_rna.hh b/source/blender/animrig/ANIM_rna.hh index 335d14b19ff..831b2bad1ba 100644 --- a/source/blender/animrig/ANIM_rna.hh +++ b/source/blender/animrig/ANIM_rna.hh @@ -1,4 +1,4 @@ -/* SPDX-FileCopyrightText: 2023 Blender Foundation +/* SPDX-FileCopyrightText: 2023 Blender Authors * * SPDX-License-Identifier: GPL-2.0-or-later */ diff --git a/source/blender/animrig/ANIM_visualkey.hh b/source/blender/animrig/ANIM_visualkey.hh index 5332a4fa7a6..cd3083441ce 100644 --- a/source/blender/animrig/ANIM_visualkey.hh +++ b/source/blender/animrig/ANIM_visualkey.hh @@ -1,4 +1,4 @@ -/* SPDX-FileCopyrightText: 2023 Blender Foundation +/* SPDX-FileCopyrightText: 2023 Blender Authors * * SPDX-License-Identifier: GPL-2.0-or-later */ diff --git a/source/blender/animrig/CMakeLists.txt b/source/blender/animrig/CMakeLists.txt index b2d69506874..9f2ae882225 100644 --- a/source/blender/animrig/CMakeLists.txt +++ b/source/blender/animrig/CMakeLists.txt @@ -20,7 +20,9 @@ set(INC_SYS ) set(SRC + intern/action.cc intern/anim_rna.cc + intern/animdata.cc intern/bone_collections.cc intern/bonecolor.cc intern/fcurve.cc @@ -28,6 +30,8 @@ set(SRC intern/keyframing_auto.cc intern/visualkey.cc + ANIM_action.hh + ANIM_animdata.hh ANIM_armature_iter.hh ANIM_bone_collections.h ANIM_bone_collections.hh diff --git a/source/blender/animrig/intern/action.cc b/source/blender/animrig/intern/action.cc new file mode 100644 index 00000000000..fa3df36a38f --- /dev/null +++ b/source/blender/animrig/intern/action.cc @@ -0,0 +1,86 @@ +/* SPDX-FileCopyrightText: 2023 Blender Authors + * + * SPDX-License-Identifier: GPL-2.0-or-later */ + +/** \file + * \ingroup animrig + */ + +#include "ANIM_action.hh" +#include "BKE_action.h" +#include "BKE_fcurve.h" +#include "BLI_listbase.h" +#include "BLI_string.h" +#include "DEG_depsgraph_build.hh" +#include "DNA_anim_types.h" +#include "RNA_prototypes.h" + +namespace blender::animrig { + +FCurve *action_fcurve_find(bAction *act, const char rna_path[], const int array_index) +{ + if (ELEM(nullptr, act, rna_path)) { + return nullptr; + } + return BKE_fcurve_find(&act->curves, rna_path, array_index); +} + +FCurve *action_fcurve_ensure(Main *bmain, + bAction *act, + const char group[], + PointerRNA *ptr, + const char rna_path[], + const int array_index) +{ + if (ELEM(nullptr, act, rna_path)) { + return nullptr; + } + + /* Try to find f-curve matching for this setting. + * - add if not found and allowed to add one + * TODO: add auto-grouping support? how this works will need to be resolved + */ + FCurve *fcu = BKE_fcurve_find(&act->curves, rna_path, array_index); + + if (fcu != nullptr) { + return fcu; + } + + fcu = BKE_fcurve_create(); + + fcu->flag = (FCURVE_VISIBLE | FCURVE_SELECTED); + fcu->auto_smoothing = U.auto_smoothing_new; + if (BLI_listbase_is_empty(&act->curves)) { + fcu->flag |= FCURVE_ACTIVE; + } + + fcu->rna_path = BLI_strdup(rna_path); + fcu->array_index = array_index; + + if (group) { + bActionGroup *agrp = BKE_action_group_find_name(act, group); + + if (agrp == nullptr) { + agrp = action_groups_add_new(act, group); + + /* Sync bone group colors if applicable. */ + if (ptr && (ptr->type == &RNA_PoseBone)) { + bPoseChannel *pchan = static_cast(ptr->data); + action_group_colors_set_from_posebone(agrp, pchan); + } + } + + action_groups_add_channel(act, agrp, fcu); + } + else { + BLI_addtail(&act->curves, fcu); + } + + /* New f-curve was added, meaning it's possible that it affects + * dependency graph component which wasn't previously animated. + */ + DEG_relations_tag_update(bmain); + + return fcu; +} +} // namespace blender::animrig \ No newline at end of file diff --git a/source/blender/animrig/intern/anim_rna.cc b/source/blender/animrig/intern/anim_rna.cc index 8214a2cfe16..2b0b8176550 100644 --- a/source/blender/animrig/intern/anim_rna.cc +++ b/source/blender/animrig/intern/anim_rna.cc @@ -1,4 +1,4 @@ -/* SPDX-FileCopyrightText: 2023 Blender Foundation +/* SPDX-FileCopyrightText: 2023 Blender Authors * * SPDX-License-Identifier: GPL-2.0-or-later */ diff --git a/source/blender/animrig/intern/animdata.cc b/source/blender/animrig/intern/animdata.cc new file mode 100644 index 00000000000..9b9ff598f7c --- /dev/null +++ b/source/blender/animrig/intern/animdata.cc @@ -0,0 +1,93 @@ +/* SPDX-FileCopyrightText: 2023 Blender Authors + * + * SPDX-License-Identifier: GPL-2.0-or-later */ + +/** \file + * \ingroup animrig + */ + +#include "ANIM_animdata.hh" +#include "BKE_action.h" +#include "BKE_fcurve.h" +#include "BKE_lib_id.h" +#include "BLI_listbase.h" +#include "DNA_anim_types.h" +#include "ED_anim_api.hh" + +namespace blender::animrig { + +/* -------------------------------------------------------------------- */ +/** \name Public F-Curves API + * \{ */ + +void animdata_fcurve_delete(bAnimContext *ac, AnimData *adt, FCurve *fcu) +{ + /* - If no AnimData, we've got nowhere to remove the F-Curve from + * (this doesn't guarantee that the F-Curve is in there, but at least we tried + * - If no F-Curve, there is nothing to remove + */ + if (ELEM(nullptr, adt, fcu)) { + return; + } + + /* Remove from whatever list it came from + * - Action Group + * - Action + * - Drivers + * - TODO... some others? + */ + if ((ac) && (ac->datatype == ANIMCONT_DRIVERS)) { + BLI_remlink(&adt->drivers, fcu); + } + else if (adt->action) { + bAction *act = adt->action; + + /* Remove from group or action, whichever one "owns" the F-Curve. */ + if (fcu->grp) { + bActionGroup *agrp = fcu->grp; + + /* Remove F-Curve from group+action. */ + action_groups_remove_channel(act, fcu); + + /* If group has no more channels, remove it too, + * otherwise can have many dangling groups #33541. + */ + if (BLI_listbase_is_empty(&agrp->channels)) { + BLI_freelinkN(&act->groups, agrp); + } + } + else { + BLI_remlink(&act->curves, fcu); + } + + /* If action has no more F-Curves as a result of this, unlink it from + * AnimData if it did not come from a NLA Strip being tweaked. + * + * This is done so that we don't have dangling Object+Action entries in + * channel list that are empty, and linger around long after the data they + * are for has disappeared (and probably won't come back). + */ + animdata_remove_empty_action(adt); + } + + BKE_fcurve_free(fcu); +} + +bool animdata_remove_empty_action(AnimData *adt) +{ + if (adt->action != nullptr) { + bAction *act = adt->action; + + if (BLI_listbase_is_empty(&act->curves) && (adt->flag & ADT_NLA_EDIT_ON) == 0) { + id_us_min(&act->id); + adt->action = nullptr; + return true; + } + } + + return false; +} + +/** \} */ + +} // namespace blender::animrig \ No newline at end of file diff --git a/source/blender/animrig/intern/bonecolor.cc b/source/blender/animrig/intern/bonecolor.cc index 196d7e6ba40..d0e29b39681 100644 --- a/source/blender/animrig/intern/bonecolor.cc +++ b/source/blender/animrig/intern/bonecolor.cc @@ -1,4 +1,4 @@ -/* SPDX-FileCopyrightText: 2023 Blender Foundation +/* SPDX-FileCopyrightText: 2023 Blender Authors * * SPDX-License-Identifier: GPL-2.0-or-later */ diff --git a/source/blender/animrig/intern/fcurve.cc b/source/blender/animrig/intern/fcurve.cc index b1c1131fd0a..51efc3ccc2d 100644 --- a/source/blender/animrig/intern/fcurve.cc +++ b/source/blender/animrig/intern/fcurve.cc @@ -1,4 +1,4 @@ -/* SPDX-FileCopyrightText: 2023 Blender Foundation +/* SPDX-FileCopyrightText: 2023 Blender Authors * * SPDX-License-Identifier: GPL-2.0-or-later */ @@ -6,104 +6,301 @@ * \ingroup animrig */ +#include +#include + +#include "ANIM_animdata.hh" #include "ANIM_fcurve.hh" -#include "BKE_action.h" #include "BKE_fcurve.h" -#include "BLI_listbase.h" -#include "BLI_string.h" -#include "DEG_depsgraph_build.hh" #include "DNA_anim_types.h" #include "ED_anim_api.hh" -#include "RNA_prototypes.h" +#include "MEM_guardedalloc.h" namespace blender::animrig { -FCurve *action_fcurve_find(bAction *act, const char rna_path[], const int array_index) -{ - if (ELEM(nullptr, act, rna_path)) { - return nullptr; - } - return BKE_fcurve_find(&act->curves, rna_path, array_index); -} - -FCurve *action_fcurve_ensure(Main *bmain, - bAction *act, - const char group[], - PointerRNA *ptr, - const char rna_path[], - const int array_index) -{ - bActionGroup *agrp; - FCurve *fcu; - - if (ELEM(nullptr, act, rna_path)) { - return nullptr; - } - - /* try to find f-curve matching for this setting - * - add if not found and allowed to add one - * TODO: add auto-grouping support? how this works will need to be resolved - */ - fcu = BKE_fcurve_find(&act->curves, rna_path, array_index); - - if (fcu == nullptr) { - fcu = BKE_fcurve_create(); - - fcu->flag = (FCURVE_VISIBLE | FCURVE_SELECTED); - fcu->auto_smoothing = U.auto_smoothing_new; - if (BLI_listbase_is_empty(&act->curves)) { - fcu->flag |= FCURVE_ACTIVE; - } - - fcu->rna_path = BLI_strdup(rna_path); - fcu->array_index = array_index; - - if (group) { - agrp = BKE_action_group_find_name(act, group); - - if (agrp == nullptr) { - agrp = action_groups_add_new(act, group); - - /* sync bone group colors if applicable */ - if (ptr && (ptr->type == &RNA_PoseBone)) { - bPoseChannel *pchan = static_cast(ptr->data); - action_group_colors_set_from_posebone(agrp, pchan); - } - } - - action_groups_add_channel(act, agrp, fcu); - } - else { - BLI_addtail(&act->curves, fcu); - } - - /* New f-curve was added, meaning it's possible that it affects - * dependency graph component which wasn't previously animated. - */ - DEG_relations_tag_update(bmain); - } - - return fcu; -} - bool delete_keyframe_fcurve(AnimData *adt, FCurve *fcu, float cfra) { bool found; - int i; - i = BKE_fcurve_bezt_binarysearch_index(fcu->bezt, cfra, fcu->totvert, &found); - if (found) { - /* Delete the key at the index (will sanity check + do recalc afterwards). */ - BKE_fcurve_delete_key(fcu, i); - BKE_fcurve_handles_recalc(fcu); - - /* Empty curves get automatically deleted. */ - if (BKE_fcurve_is_empty(fcu)) { - ANIM_fcurve_delete_from_animdata(nullptr, adt, fcu); - } - - return true; + const int index = BKE_fcurve_bezt_binarysearch_index(fcu->bezt, cfra, fcu->totvert, &found); + if (!found) { + return false; } - return false; + + /* Delete the key at the index (will sanity check + do recalc afterwards). */ + BKE_fcurve_delete_key(fcu, index); + BKE_fcurve_handles_recalc(fcu); + + /* Empty curves get automatically deleted. */ + if (BKE_fcurve_is_empty(fcu)) { + animdata_fcurve_delete(nullptr, adt, fcu); + } + + return true; } + +/* ************************************************** */ +/* KEYFRAME INSERTION */ + +/* -------------- BezTriple Insertion -------------------- */ + +/* Change the Y position of a keyframe to match the input, adjusting handles. */ +static void replace_bezt_keyframe_ypos(BezTriple *dst, const BezTriple *bezt) +{ + /* Just change the values when replacing, so as to not overwrite handles. */ + float dy = bezt->vec[1][1] - dst->vec[1][1]; + + /* Just apply delta value change to the handle values. */ + dst->vec[0][1] += dy; + dst->vec[1][1] += dy; + dst->vec[2][1] += dy; + + dst->f1 = bezt->f1; + dst->f2 = bezt->f2; + dst->f3 = bezt->f3; + + /* TODO: perform some other operations? */ +} + +int insert_bezt_fcurve(FCurve *fcu, const BezTriple *bezt, eInsertKeyFlags flag) +{ + int i = 0; + + /* Are there already keyframes? */ + if (fcu->bezt) { + bool replace; + i = BKE_fcurve_bezt_binarysearch_index(fcu->bezt, bezt->vec[1][0], fcu->totvert, &replace); + + /* Replace an existing keyframe? */ + if (replace) { + /* 'i' may in rare cases exceed arraylen. */ + if ((i >= 0) && (i < fcu->totvert)) { + if (flag & INSERTKEY_OVERWRITE_FULL) { + fcu->bezt[i] = *bezt; + } + else { + replace_bezt_keyframe_ypos(&fcu->bezt[i], bezt); + } + + if (flag & INSERTKEY_CYCLE_AWARE) { + /* If replacing an end point of a cyclic curve without offset, + * modify the other end too. */ + if (ELEM(i, 0, fcu->totvert - 1) && BKE_fcurve_get_cycle_type(fcu) == FCU_CYCLE_PERFECT) + { + replace_bezt_keyframe_ypos(&fcu->bezt[i == 0 ? fcu->totvert - 1 : 0], bezt); + } + } + } + } + /* Keyframing modes allow not replacing the keyframe. */ + else if ((flag & INSERTKEY_REPLACE) == 0) { + /* Insert new - if we're not restricted to replacing keyframes only. */ + BezTriple *newb = static_cast( + MEM_callocN((fcu->totvert + 1) * sizeof(BezTriple), "beztriple")); + + /* Add the beztriples that should occur before the beztriple to be pasted + * (originally in fcu). */ + if (i > 0) { + memcpy(newb, fcu->bezt, i * sizeof(BezTriple)); + } + + /* Add beztriple to paste at index i. */ + *(newb + i) = *bezt; + + /* Add the beztriples that occur after the beztriple to be pasted (originally in fcu). */ + if (i < fcu->totvert) { + memcpy(newb + i + 1, fcu->bezt + i, (fcu->totvert - i) * sizeof(BezTriple)); + } + + /* Replace (+ free) old with new, only if necessary to do so. */ + MEM_freeN(fcu->bezt); + fcu->bezt = newb; + + fcu->totvert++; + } + else { + return -1; + } + } + /* No keyframes yet, but can only add if... + * 1) keyframing modes say that keyframes can only be replaced, so adding new ones won't know + * 2) there are no samples on the curve + * NOTE: maybe we may want to allow this later when doing samples -> bezt conversions, + * but for now, having both is asking for trouble + */ + else if ((flag & INSERTKEY_REPLACE) == 0 && (fcu->fpt == nullptr)) { + /* Create new keyframes array. */ + fcu->bezt = static_cast(MEM_callocN(sizeof(BezTriple), "beztriple")); + *(fcu->bezt) = *bezt; + fcu->totvert = 1; + } + /* Cannot add anything. */ + else { + /* Return error code -1 to prevent any misunderstandings. */ + return -1; + } + + /* We need to return the index, so that some tools which do post-processing can + * detect where we added the BezTriple in the array. + */ + return i; +} + +/** + * Update the FCurve to allow insertion of `bezt` without modifying the curve shape. + * + * Checks whether it is necessary to apply Bezier subdivision due to involvement of non-auto + * handles. If necessary, changes `bezt` handles from Auto to Aligned. + * + * \param bezt: key being inserted + * \param prev: keyframe before that key + * \param next: keyframe after that key + */ +static void subdivide_nonauto_handles(const FCurve *fcu, + BezTriple *bezt, + BezTriple *prev, + BezTriple *next) +{ + if (prev->ipo != BEZT_IPO_BEZ || bezt->ipo != BEZT_IPO_BEZ) { + return; + } + + /* Don't change Vector handles, or completely auto regions. */ + const bool bezt_auto = BEZT_IS_AUTOH(bezt) || (bezt->h1 == HD_VECT && bezt->h2 == HD_VECT); + const bool prev_auto = BEZT_IS_AUTOH(prev) || (prev->h2 == HD_VECT); + const bool next_auto = BEZT_IS_AUTOH(next) || (next->h1 == HD_VECT); + if (bezt_auto && prev_auto && next_auto) { + return; + } + + /* Subdivide the curve. */ + float delta; + if (!BKE_fcurve_bezt_subdivide_handles(bezt, prev, next, &delta)) { + return; + } + + /* Decide when to force auto to manual. */ + if (!BEZT_IS_AUTOH(bezt)) { + return; + } + if ((prev_auto || next_auto) && fcu->auto_smoothing == FCURVE_SMOOTH_CONT_ACCEL) { + const float hx = bezt->vec[1][0] - bezt->vec[0][0]; + const float dx = bezt->vec[1][0] - prev->vec[1][0]; + + /* This mode always uses 1/3 of key distance for handle x size. */ + const bool auto_works_well = fabsf(hx - dx / 3.0f) < 0.001f; + if (auto_works_well) { + return; + } + } + + /* Turn off auto mode. */ + bezt->h1 = bezt->h2 = HD_ALIGN; +} + +int insert_vert_fcurve( + FCurve *fcu, float x, float y, eBezTriple_KeyframeType keyframe_type, eInsertKeyFlags flag) +{ + BezTriple beztr = {{{0}}}; + uint oldTot = fcu->totvert; + int a; + + /* Set all three points, for nicer start position. + * NOTE: +/- 1 on vec.x for left and right handles is so that 'free' handles work ok... + */ + beztr.vec[0][0] = x - 1.0f; + beztr.vec[0][1] = y; + beztr.vec[1][0] = x; + beztr.vec[1][1] = y; + beztr.vec[2][0] = x + 1.0f; + beztr.vec[2][1] = y; + beztr.f1 = beztr.f2 = beztr.f3 = SELECT; + + /* Set default handle types and interpolation mode. */ + if (flag & INSERTKEY_NO_USERPREF) { + /* For Py-API, we want scripts to have predictable behavior, + * hence the option to not depend on the userpref defaults. + */ + beztr.h1 = beztr.h2 = HD_AUTO_ANIM; + beztr.ipo = BEZT_IPO_BEZ; + } + else { + /* For UI usage - defaults should come from the user-preferences and/or tool-settings. */ + beztr.h1 = beztr.h2 = U.keyhandles_new; /* Use default handle type here. */ + + /* Use default interpolation mode, with exceptions for int/discrete values. */ + beztr.ipo = U.ipo_new; + } + + /* Interpolation type used is constrained by the type of values the curve can take. */ + if (fcu->flag & FCURVE_DISCRETE_VALUES) { + beztr.ipo = BEZT_IPO_CONST; + } + else if ((beztr.ipo == BEZT_IPO_BEZ) && (fcu->flag & FCURVE_INT_VALUES)) { + beztr.ipo = BEZT_IPO_LIN; + } + + /* Set keyframe type value (supplied), which should come from the scene + * settings in most cases. */ + BEZKEYTYPE(&beztr) = keyframe_type; + + /* Set default values for "easing" interpolation mode settings. + * NOTE: Even if these modes aren't currently used, if users switch + * to these later, we want these to work in a sane way out of + * the box. + */ + + /* "back" easing - This value used to be used when overshoot=0, but that + * introduced discontinuities in how the param worked. */ + beztr.back = 1.70158f; + + /* "elastic" easing - Values here were hand-optimized for a default duration of + * ~10 frames (typical mograph motion length) */ + beztr.amplitude = 0.8f; + beztr.period = 4.1f; + + /* Add temp beztriple to keyframes. */ + a = insert_bezt_fcurve(fcu, &beztr, flag); + BKE_fcurve_active_keyframe_set(fcu, &fcu->bezt[a]); + + /* If `a` is negative return to avoid segfaults. */ + if (a < 0) { + return -1; + } + + /* Set handle-type and interpolation. */ + if ((fcu->totvert > 2) && (flag & INSERTKEY_REPLACE) == 0) { + BezTriple *bezt = (fcu->bezt + a); + + /* Set interpolation from previous (if available), + * but only if we didn't just replace some keyframe: + * - Replacement is indicated by no-change in number of verts. + * - When replacing, the user may have specified some interpolation that should be kept. + */ + if (fcu->totvert > oldTot) { + if (a > 0) { + bezt->ipo = (bezt - 1)->ipo; + } + else if (a < fcu->totvert - 1) { + bezt->ipo = (bezt + 1)->ipo; + } + + if (0 < a && a < (fcu->totvert - 1) && (flag & INSERTKEY_OVERWRITE_FULL) == 0) { + subdivide_nonauto_handles(fcu, bezt, bezt - 1, bezt + 1); + } + } + } + + /* Don't recalculate handles if fast is set. + * - this is a hack to make importers faster + * - we may calculate twice (due to auto-handle needing to be calculated twice) + */ + if ((flag & INSERTKEY_FAST) == 0) { + BKE_fcurve_handles_recalc(fcu); + } + + /* Return the index at which the keyframe was added. */ + return a; +} + } // namespace blender::animrig diff --git a/source/blender/animrig/intern/keyframing.cc b/source/blender/animrig/intern/keyframing.cc index 8cc3ad36710..51f21080676 100644 --- a/source/blender/animrig/intern/keyframing.cc +++ b/source/blender/animrig/intern/keyframing.cc @@ -1,4 +1,4 @@ -/* SPDX-FileCopyrightText: 2023 Blender Foundation +/* SPDX-FileCopyrightText: 2023 Blender Authors * * SPDX-License-Identifier: GPL-2.0-or-later */ @@ -9,6 +9,8 @@ #include #include +#include "ANIM_action.hh" +#include "ANIM_animdata.hh" #include "ANIM_fcurve.hh" #include "ANIM_keyframing.hh" #include "ANIM_rna.hh" @@ -31,7 +33,6 @@ #include "DEG_depsgraph.hh" #include "DEG_depsgraph_query.hh" #include "DNA_anim_types.h" -#include "ED_anim_api.hh" #include "ED_keyframing.hh" #include "MEM_guardedalloc.h" #include "RNA_access.hh" @@ -936,7 +937,7 @@ int clear_keyframe(Main *bmain, continue; } - ANIM_fcurve_delete_from_animdata(nullptr, adt, fcu); + animdata_fcurve_delete(nullptr, adt, fcu); key_count++; } diff --git a/source/blender/animrig/intern/keyframing_auto.cc b/source/blender/animrig/intern/keyframing_auto.cc index 9382ad3260f..12b0e0e34d8 100644 --- a/source/blender/animrig/intern/keyframing_auto.cc +++ b/source/blender/animrig/intern/keyframing_auto.cc @@ -1,4 +1,4 @@ -/* SPDX-FileCopyrightText: 2023 Blender Foundation +/* SPDX-FileCopyrightText: 2023 Blender Authors * * SPDX-License-Identifier: GPL-2.0-or-later */ diff --git a/source/blender/animrig/intern/visualkey.cc b/source/blender/animrig/intern/visualkey.cc index ffa62af292e..34a6ea45e31 100644 --- a/source/blender/animrig/intern/visualkey.cc +++ b/source/blender/animrig/intern/visualkey.cc @@ -1,4 +1,4 @@ -/* SPDX-FileCopyrightText: 2023 Blender Foundation +/* SPDX-FileCopyrightText: 2023 Blender Authors * * SPDX-License-Identifier: GPL-2.0-or-later */ @@ -23,8 +23,6 @@ #include "DNA_object_types.h" #include "DNA_rigidbody_types.h" -#include "ED_keyframing.hh" - #include "RNA_access.hh" #include "RNA_prototypes.h" #include "RNA_types.hh" diff --git a/source/blender/blenfont/intern/blf_font.cc b/source/blender/blenfont/intern/blf_font.cc index cc7d76b70f9..563de55e242 100644 --- a/source/blender/blenfont/intern/blf_font.cc +++ b/source/blender/blenfont/intern/blf_font.cc @@ -56,7 +56,7 @@ BatchBLF g_batch; -/* freetype2 handle ONLY for this file! */ +/* `freetype2` handle ONLY for this file! */ static FT_Library ft_lib = nullptr; static FTC_Manager ftc_manager = nullptr; static FTC_CMapCache ftc_charmap_cache = nullptr; @@ -163,8 +163,8 @@ static ft_pix blf_unscaled_F26Dot6_to_pixels(FontBLF *font, FT_Pos value) /* Scale value by font size using integer-optimized multiplication. */ FT_Long scaled = FT_MulFix(value, font->ft_size->metrics.x_scale); - /* Copied from FreeType's FT_Get_Kerning (with FT_KERNING_DEFAULT), scaling down */ - /* kerning distances at small PPEM values so that they don't become too big. */ + /* Copied from FreeType's FT_Get_Kerning (with FT_KERNING_DEFAULT), scaling down. */ + /* Kerning distances at small PPEM values so that they don't become too big. */ if (font->ft_size->metrics.x_ppem < 25) { scaled = FT_MulDiv(scaled, font->ft_size->metrics.x_ppem, 25); } @@ -270,7 +270,7 @@ void blf_batch_draw_begin(FontBLF *font) } } else { - /* flush cache */ + /* Flush cache. */ blf_batch_draw(); g_batch.font = font; g_batch.simple_shader = simple_shader; @@ -332,7 +332,7 @@ void blf_batch_draw() GPUTexture *texture = blf_batch_cache_texture_load(); GPU_vertbuf_data_len_set(g_batch.verts, g_batch.glyph_len); - GPU_vertbuf_use(g_batch.verts); /* send data */ + GPU_vertbuf_use(g_batch.verts); /* Send data. */ GPU_batch_program_set_builtin(g_batch.batch, GPU_SHADER_TEXT); GPU_batch_texture_bind(g_batch.batch, "glyph", texture); @@ -342,7 +342,7 @@ void blf_batch_draw() GPU_texture_unbind(texture); - /* restart to 1st vertex data pointers */ + /* Restart to 1st vertex data pointers. */ GPU_vertbuf_attr_get_raw_data(g_batch.verts, g_batch.pos_loc, &g_batch.pos_step); GPU_vertbuf_attr_get_raw_data(g_batch.verts, g_batch.col_loc, &g_batch.col_step); GPU_vertbuf_attr_get_raw_data(g_batch.verts, g_batch.offset_loc, &g_batch.offset_step); @@ -442,15 +442,15 @@ static void blf_font_draw_ex(FontBLF *font, ResultBLF *r_info, const ft_pix pen_y) { + if (str_len == 0) { + /* Early exit, don't do any immediate-mode GPU operations. */ + return; + } + GlyphBLF *g = nullptr; ft_pix pen_x = 0; size_t i = 0; - if (str_len == 0) { - /* early output, don't do any IMM OpenGL. */ - return; - } - blf_batch_draw_begin(font); while ((i < str_len) && str[i]) { @@ -458,7 +458,7 @@ static void blf_font_draw_ex(FontBLF *font, if (UNLIKELY(g == nullptr)) { continue; } - /* do not return this loop if clipped, we want every character tested */ + /* Do not return this loop if clipped, we want every character tested. */ blf_glyph_draw(font, gc, g, ft_pix_to_int_floor(pen_x), ft_pix_to_int_floor(pen_y)); pen_x += g->advance_x; } @@ -497,7 +497,7 @@ int blf_font_draw_mono( if (UNLIKELY(g == nullptr)) { continue; } - /* do not return this loop if clipped, we want every character tested */ + /* Do not return this loop if clipped, we want every character tested. */ blf_glyph_draw(font, gc, g, ft_pix_to_int_floor(pen_x), ft_pix_to_int_floor(pen_y)); const int col = UNLIKELY(g->c == '\t') ? (tab_columns - (columns % tab_columns)) : @@ -641,10 +641,10 @@ static void blf_font_draw_buffer_ex(FontBLF *font, ft_pix pen_y_basis = ft_pix_from_int(font->pos[1]) + pen_y; size_t i = 0; - /* buffer specific vars */ + /* Buffer specific variables. */ FontBufInfoBLF *buf_info = &font->buf_info; - /* another buffer specific call for color conversion */ + /* Another buffer specific call for color conversion. */ while ((i < str_len) && str[i]) { g = blf_glyph_from_utf8_and_step(font, gc, g, str, str_len, &i, &pen_x); @@ -687,7 +687,8 @@ static bool blf_font_width_to_strlen_glyph_process(FontBLF *font, const int width_i) { if (UNLIKELY(g == nullptr)) { - return false; /* continue the calling loop. */ + /* Continue the calling loop. */ + return false; } if (g && pen_x && !(font->flags & BLF_MONOSPACED)) { @@ -946,19 +947,19 @@ void blf_font_boundbox_foreach_glyph(FontBLF *font, BLF_GlyphBoundsFn user_fn, void *user_data) { - GlyphBLF *g = nullptr; - ft_pix pen_x = 0; - size_t i = 0, i_curr; - if (str_len == 0 || str[0] == 0) { - /* early output. */ + /* Early exit. */ return; } + GlyphBLF *g = nullptr; + ft_pix pen_x = 0; + size_t i = 0; + GlyphCacheBLF *gc = blf_glyph_cache_acquire(font); while ((i < str_len) && str[i]) { - i_curr = i; + const size_t i_curr = i; g = blf_glyph_from_utf8_and_step(font, gc, g, str, str_len, &i, &pen_x); if (UNLIKELY(g == nullptr)) { @@ -1103,8 +1104,8 @@ static void blf_font_wrap_apply(FontBLF *font, // printf("%s wrapping (%d, %d) `%s`:\n", __func__, str_len, strlen(str), str); while ((i < str_len) && str[i]) { - /* wrap vars */ - size_t i_curr = i; + /* Wrap variables. */ + const size_t i_curr = i; bool do_draw = false; g = blf_glyph_from_utf8_and_step(font, gc, g_prev, str, str_len, &i, &pen_x); @@ -1126,7 +1127,7 @@ static void blf_font_wrap_apply(FontBLF *font, do_draw = true; } else if (UNLIKELY(((i < str_len) && str[i]) == 0)) { - /* need check here for trailing newline, else we draw it */ + /* Need check here for trailing newline, else we draw it. */ wrap.last[0] = i + ((g->c != '\n') ? 1 : 0); wrap.last[1] = i; do_draw = true; @@ -1142,8 +1143,13 @@ static void blf_font_wrap_apply(FontBLF *font, } if (UNLIKELY(do_draw)) { - // printf("(%03d..%03d) `%.*s`\n", - // wrap.start, wrap.last[0], (wrap.last[0] - wrap.start) - 1, &str[wrap.start]); +#if 0 + printf("(%03d..%03d) `%.*s`\n", + wrap.start, + wrap.last[0], + (wrap.last[0] - wrap.start) - 1, + &str[wrap.start]); +#endif callback(font, gc, &str[wrap.start], (wrap.last[0] - wrap.start) - 1, pen_y, userdata); wrap.start = wrap.last[0]; @@ -1163,14 +1169,14 @@ static void blf_font_wrap_apply(FontBLF *font, if (r_info) { r_info->lines = lines; - /* width of last line only (with wrapped lines) */ + /* Width of last line only (with wrapped lines). */ r_info->width = ft_pix_to_int(pen_x_next); } blf_glyph_cache_release(font); } -/* blf_font_draw__wrap */ +/** Utility for #blf_font_draw__wrap. */ static void blf_font_draw__wrap_cb(FontBLF *font, GlyphCacheBLF *gc, const char *str, @@ -1185,7 +1191,7 @@ void blf_font_draw__wrap(FontBLF *font, const char *str, const size_t str_len, R blf_font_wrap_apply(font, str, str_len, r_info, blf_font_draw__wrap_cb, nullptr); } -/* blf_font_boundbox__wrap */ +/** Utility for #blf_font_boundbox__wrap. */ static void blf_font_boundbox_wrap_cb(FontBLF *font, GlyphCacheBLF *gc, const char *str, @@ -1210,7 +1216,7 @@ void blf_font_boundbox__wrap( blf_font_wrap_apply(font, str, str_len, r_info, blf_font_boundbox_wrap_cb, box); } -/* blf_font_draw_buffer__wrap */ +/** Utility for #blf_font_draw_buffer__wrap. */ static void blf_font_draw_buffer__wrap_cb(FontBLF *font, GlyphCacheBLF *gc, const char *str, @@ -1237,8 +1243,8 @@ void blf_font_draw_buffer__wrap(FontBLF *font, static ft_pix blf_font_height_max_ft_pix(FontBLF *font) { blf_ensure_size(font); - /* Metrics.height is rounded to pixel. Force minimum of one pixel. */ - return MAX2((ft_pix)font->ft_size->metrics.height, ft_pix_from_int(1)); + /* #Metrics::height is rounded to pixel. Force minimum of one pixel. */ + return std::max((ft_pix)font->ft_size->metrics.height, ft_pix_from_int(1)); } int blf_font_height_max(FontBLF *font) @@ -1249,8 +1255,8 @@ int blf_font_height_max(FontBLF *font) static ft_pix blf_font_width_max_ft_pix(FontBLF *font) { blf_ensure_size(font); - /* Metrics.max_advance is rounded to pixel. Force minimum of one pixel. */ - return MAX2((ft_pix)font->ft_size->metrics.max_advance, ft_pix_from_int(1)); + /* #Metrics::max_advance is rounded to pixel. Force minimum of one pixel. */ + return std::max((ft_pix)font->ft_size->metrics.max_advance, ft_pix_from_int(1)); } int blf_font_width_max(FontBLF *font) @@ -1299,7 +1305,7 @@ int blf_font_init() nullptr, &ftc_manager); if (err == FT_Err_Ok) { - /* Create a charmap cache to speed up glyph index lookups. */ + /* Create a character-map cache to speed up glyph index lookups. */ err = FTC_CMapCache_New(ftc_manager, &ftc_charmap_cache); } } @@ -1342,7 +1348,8 @@ static void blf_font_fill(FontBLF *font) font->m[i] = 0; } - /* annoying bright color so we can see where to add BLF_color calls */ + /* Use an easily identifiable bright color (yellow) + * so its clear when #BLF_color calls are missing. */ font->color[0] = 255; font->color[1] = 255; font->color[2] = 0; @@ -1377,8 +1384,10 @@ static void blf_font_fill(FontBLF *font) font->buf_info.col_init[3] = 0; } -/* Note that the data the following function creates is not yet used. - * But do not remove it as it will be used in the near future - Harley */ +/** + * NOTE(@Harley): that the data the following function creates is not yet used. + * But do not remove it as it will be used in the near future. + */ static void blf_font_metrics(FT_Face face, FontMetrics *metrics) { /* Members with non-zero defaults. */ diff --git a/source/blender/blenfont/intern/blf_glyph.cc b/source/blender/blenfont/intern/blf_glyph.cc index d5fba595516..f03fd9e3f2e 100644 --- a/source/blender/blenfont/intern/blf_glyph.cc +++ b/source/blender/blenfont/intern/blf_glyph.cc @@ -1134,11 +1134,11 @@ static FT_GlyphSlot blf_glyph_render(FontBLF *settings_font, /* Style targets are on the settings_font. */ float weight_target = float(settings_font->char_weight); if (settings_font->flags & BLF_BOLD) { - weight_target = MIN2(weight_target + 300.0f, 900.0f); + weight_target = std::min(weight_target + 300.0f, 900.0f); } float slant_target = settings_font->char_slant; if (settings_font->flags & BLF_ITALIC) { - slant_target = MIN2(slant_target + 8.0f, 15.0f); + slant_target = std::min(slant_target + 8.0f, 15.0f); } float width_target = settings_font->char_width; float spacing_target = settings_font->char_spacing; @@ -1281,7 +1281,7 @@ static void blf_glyph_calc_rect_test(rcti *rect, GlyphBLF *g, const int x, const * width used by BLF_width. This allows that the text slightly * overlaps the clipping border to achieve better alignment. */ rect->xmin = x + g->pos[0] + 1; - rect->xmax = x + MIN2(ft_pix_to_int(g->advance_x), g->dims[0]); + rect->xmax = x + std::min(ft_pix_to_int(g->advance_x), g->dims[0]); rect->ymin = y; rect->ymax = rect->ymin - g->dims[1]; } diff --git a/source/blender/blenfont/intern/blf_thumbs.cc b/source/blender/blenfont/intern/blf_thumbs.cc index 31ca0d33f3e..de7534a557e 100644 --- a/source/blender/blenfont/intern/blf_thumbs.cc +++ b/source/blender/blenfont/intern/blf_thumbs.cc @@ -365,7 +365,7 @@ bool BLF_thumb_preview(const char *filename, uchar *buf, int w, int h, int /*cha int height = ft_pix_to_int((ft_pix)face->size->metrics.ascender - (ft_pix)face->size->metrics.descender); - width = MAX2(width, height); + width = std::max(width, height); /* Fill up to 96% horizontally or vertically. */ float font_size = MIN3(float(w), @@ -410,7 +410,7 @@ bool BLF_thumb_preview(const char *filename, uchar *buf, int w, int h, int /*cha if (dest_col >= 0 && dest_col < w) { uchar *source = &face->glyph->bitmap.buffer[y * int(face->glyph->bitmap.width) + x]; uchar *dest = &buf[dest_row * w * 4 + (dest_col * 4 + 3)]; - *dest = uchar(MIN2((uint(*dest) + uint(*source)), 255u)); + *dest = uchar(std::min((uint(*dest) + uint(*source)), 255u)); } } } diff --git a/source/blender/blenkernel/BKE_blender_version.h b/source/blender/blenkernel/BKE_blender_version.h index 238f9e57d08..8fbe1acd022 100644 --- a/source/blender/blenkernel/BKE_blender_version.h +++ b/source/blender/blenkernel/BKE_blender_version.h @@ -29,7 +29,7 @@ extern "C" { /* Blender file format version. */ #define BLENDER_FILE_VERSION BLENDER_VERSION -#define BLENDER_FILE_SUBVERSION 4 +#define BLENDER_FILE_SUBVERSION 5 /* Minimum Blender version that supports reading file written with the current * version. Older Blender versions will test this and cancel loading the file, showing a warning to diff --git a/source/blender/blenkernel/BKE_node_tree_anonymous_attributes.hh b/source/blender/blenkernel/BKE_node_tree_anonymous_attributes.hh index 30a0344ef78..f71c6aefbfa 100644 --- a/source/blender/blenkernel/BKE_node_tree_anonymous_attributes.hh +++ b/source/blender/blenkernel/BKE_node_tree_anonymous_attributes.hh @@ -8,8 +8,11 @@ #include "DNA_node_types.h" +#include "BLI_array.hh" #include "BLI_bit_group_vector.hh" +#include "BLI_resource_scope.hh" #include "BLI_vector.hh" +#include "BLI_vector_set.hh" #include "NOD_node_declaration.hh" diff --git a/source/blender/blenkernel/intern/anim_sys.cc b/source/blender/blenkernel/intern/anim_sys.cc index 782b999b1f9..7ca0d43eb69 100644 --- a/source/blender/blenkernel/intern/anim_sys.cc +++ b/source/blender/blenkernel/intern/anim_sys.cc @@ -1197,7 +1197,7 @@ static void nlaeval_snapshot_init(NlaEvalSnapshot *snapshot, NlaEvalSnapshot *base) { snapshot->base = base; - snapshot->size = MAX2(16, nlaeval->num_channels); + snapshot->size = std::max(16, nlaeval->num_channels); snapshot->channels = static_cast( MEM_callocN(sizeof(*snapshot->channels) * snapshot->size, "NlaEvalSnapshot::channels")); } diff --git a/source/blender/blenkernel/intern/attribute.cc b/source/blender/blenkernel/intern/attribute.cc index 68c20c91d4e..16d3ed4b967 100644 --- a/source/blender/blenkernel/intern/attribute.cc +++ b/source/blender/blenkernel/intern/attribute.cc @@ -270,8 +270,8 @@ void BKE_id_attribute_calc_unique_name(ID *id, const char *name, char *outname) const int name_maxncpy = CustomData_name_maxncpy_calc(name); /* Set default name if none specified. - * NOTE: We only call IFACE_() if needed to avoid locale lookup overhead. */ - BLI_strncpy_utf8(outname, (name && name[0]) ? name : IFACE_("Attribute"), name_maxncpy); + * NOTE: We only call DATA_() if needed to avoid locale lookup overhead. */ + BLI_strncpy_utf8(outname, (name && name[0]) ? name : DATA_("Attribute"), name_maxncpy); const char *defname = ""; /* Dummy argument, never used as `name` is never zero length. */ BLI_uniquename_cb(unique_name_cb, &data, defname, '.', outname, name_maxncpy); diff --git a/source/blender/blenkernel/intern/bake_items_paths.cc b/source/blender/blenkernel/intern/bake_items_paths.cc index 6945dacebfc..4f7d38dd752 100644 --- a/source/blender/blenkernel/intern/bake_items_paths.cc +++ b/source/blender/blenkernel/intern/bake_items_paths.cc @@ -1,4 +1,4 @@ -/* SPDX-FileCopyrightText: 2023 Blender Foundation +/* SPDX-FileCopyrightText: 2023 Blender Authors * * SPDX-License-Identifier: GPL-2.0-or-later */ diff --git a/source/blender/blenkernel/intern/boids.cc b/source/blender/blenkernel/intern/boids.cc index d0a37d6da9f..889e143e0ee 100644 --- a/source/blender/blenkernel/intern/boids.cc +++ b/source/blender/blenkernel/intern/boids.cc @@ -275,7 +275,7 @@ static bool rule_avoid_collision(BoidRule *rule, mul_v3_fl(bbd->wanted_co, (1.0f - t) * val->personal_space * pa->size); bbd->wanted_speed = sqrtf(t) * len_v3(pa->prev_state.vel); - bbd->wanted_speed = MAX2(bbd->wanted_speed, val->min_speed); + bbd->wanted_speed = std::max(bbd->wanted_speed, val->min_speed); return true; } @@ -1321,7 +1321,7 @@ void boid_body(BoidBrainData *bbd, ParticleData *pa) new_speed = MAX2(bbd->wanted_speed, old_speed - val.max_acc); } else { - new_speed = MIN2(bbd->wanted_speed, old_speed + val.max_acc); + new_speed = std::min(bbd->wanted_speed, old_speed + val.max_acc); } /* combine direction and speed */ @@ -1333,7 +1333,7 @@ void boid_body(BoidBrainData *bbd, ParticleData *pa) float len2 = dot_v2v2(new_vel, new_vel); float root; - len2 = MAX2(len2, val.min_speed * val.min_speed); + len2 = std::max(len2, val.min_speed * val.min_speed); root = sasqrt(new_speed * new_speed - len2); new_vel[2] = new_vel[2] < 0.0f ? -root : root; @@ -1367,7 +1367,7 @@ void boid_body(BoidBrainData *bbd, ParticleData *pa) if (ELEM(bpa->data.mode, eBoidMode_OnLand, eBoidMode_Climbing)) { float length = normalize_v3(force); - length = MAX2(0.0f, length - boids->land_stick_force); + length = std::max(0.0f, length - boids->land_stick_force); mul_v3_fl(force, length); } diff --git a/source/blender/blenkernel/intern/collision.cc b/source/blender/blenkernel/intern/collision.cc index bf633e784e0..3a60bb81efa 100644 --- a/source/blender/blenkernel/intern/collision.cc +++ b/source/blender/blenkernel/intern/collision.cc @@ -757,7 +757,7 @@ static int cloth_collision_response_static(ClothModifierData *clmd, } if ((magrelVel < 0.1f * d * time_multiplier) && (d > ALMOST_ZERO)) { - repulse = MIN2(d / time_multiplier, 0.1f * d * time_multiplier - magrelVel); + repulse = std::min(d / time_multiplier, 0.1f * d * time_multiplier - magrelVel); /* Stay on the safe side and clamp repulse. */ if (impulse > ALMOST_ZERO) { diff --git a/source/blender/blenkernel/intern/customdata.cc b/source/blender/blenkernel/intern/customdata.cc index 0788076332a..534ff4a8b99 100644 --- a/source/blender/blenkernel/intern/customdata.cc +++ b/source/blender/blenkernel/intern/customdata.cc @@ -2427,7 +2427,7 @@ void CustomData_ensure_data_is_mutable(CustomDataLayer *layer, const int totelem ensure_layer_data_is_mutable(*layer, totelem); } -void CustomData_ensure_layers_are_mutable(struct CustomData *data, int totelem) +void CustomData_ensure_layers_are_mutable(CustomData *data, int totelem) { for (const int i : IndexRange(data->totlayer)) { ensure_layer_data_is_mutable(data->layers[i], totelem); diff --git a/source/blender/blenkernel/intern/fcurve_test.cc b/source/blender/blenkernel/intern/fcurve_test.cc index 8c585f36db6..7b93a1ccce0 100644 --- a/source/blender/blenkernel/intern/fcurve_test.cc +++ b/source/blender/blenkernel/intern/fcurve_test.cc @@ -7,6 +7,8 @@ #include "BKE_fcurve.h" +#include "ANIM_fcurve.hh" + #include "ED_keyframing.hh" #include "DNA_anim_types.h" @@ -14,6 +16,7 @@ #include "BLI_math_vector_types.hh" namespace blender::bke::tests { +using namespace blender::animrig; /* Epsilon for floating point comparisons. */ static const float EPSILON = 1e-7f; diff --git a/source/blender/blenkernel/intern/fluid.cc b/source/blender/blenkernel/intern/fluid.cc index 793e43613b9..5539a80b62c 100644 --- a/source/blender/blenkernel/intern/fluid.cc +++ b/source/blender/blenkernel/intern/fluid.cc @@ -450,7 +450,7 @@ static void manta_set_domain_from_mesh(FluidDomainSettings *fds, fds->base_res[1] = max_ii(int(size[1] * scale + 0.5f), 4); fds->base_res[2] = max_ii(int(size[2] * scale + 0.5f), 4); } - else if (size[1] >= MAX2(size[0], size[2])) { + else if (size[1] >= std::max(size[0], size[2])) { scale = res / size[1]; fds->scale = size[1] / fabsf(ob->scale[1]); fds->base_res[0] = max_ii(int(size[0] * scale + 0.5f), 4); @@ -736,8 +736,8 @@ static void bb_combineMaps(FluidObjectBB *output, for (i = 0; i < 3; i++) { if (bb1.valid) { - output->min[i] = MIN2(bb1.min[i], bb2->min[i]); - output->max[i] = MAX2(bb1.max[i], bb2->max[i]); + output->min[i] = std::min(bb1.min[i], bb2->min[i]); + output->max[i] = std::max(bb1.max[i], bb2->max[i]); } else { output->min[i] = bb2->min[i]; @@ -783,14 +783,15 @@ static void bb_combineMaps(FluidObjectBB *output, x - bb2->min[0], bb2->res[0], y - bb2->min[1], bb2->res[1], z - bb2->min[2]); /* Values. */ - output->numobjs[index_out] = MAX2(bb2->numobjs[index_in], output->numobjs[index_out]); + output->numobjs[index_out] = std::max(bb2->numobjs[index_in], + output->numobjs[index_out]); if (output->influence && bb2->influence) { if (additive) { output->influence[index_out] += bb2->influence[index_in] * sample_size; } else { - output->influence[index_out] = MAX2(bb2->influence[index_in], - output->influence[index_out]); + output->influence[index_out] = std::max(bb2->influence[index_in], + output->influence[index_out]); } } output->distances[index_out] = MIN2(bb2->distances[index_in], @@ -2481,7 +2482,7 @@ BLI_INLINE void apply_inflow_fields(FluidFlowSettings *ffs, /* Set emission value for smoke inflow. * Ensure that emission value is "maximized". */ if (emission_in) { - emission_in[index] = MAX2(emission_value, emission_in[index]); + emission_in[index] = std::max(emission_value, emission_in[index]); } /* Set inflow for smoke from here on. */ @@ -2502,13 +2503,13 @@ BLI_INLINE void apply_inflow_fields(FluidFlowSettings *ffs, if (density && density_in) { if (ffs->type != FLUID_FLOW_TYPE_FIRE && dens_flow > density[index]) { /* Use MAX2 to preserve values from other emitters at this cell. */ - density_in[index] = MAX2(dens_flow, density_in[index]); + density_in[index] = std::max(dens_flow, density_in[index]); } } if (fuel && fuel_in) { if (ffs->type != FLUID_FLOW_TYPE_SMOKE && fuel_flow && fuel_flow > fuel[index]) { /* Use MAX2 to preserve values from other emitters at this cell. */ - fuel_in[index] = MAX2(fuel_flow, fuel_in[index]); + fuel_in[index] = std::max(fuel_flow, fuel_in[index]); } } } @@ -4414,7 +4415,7 @@ float BKE_fluid_get_velocity_at(Object *ob, float position[3], float velocity[3] if (manta_smoke_has_fuel(fds->fluid)) { fuel = BLI_voxel_sample_trilinear(manta_smoke_get_fuel(fds->fluid), fds->res, pos); } - return MAX2(density, fuel); + return std::max(density, fuel); } return -1.0f; } diff --git a/source/blender/blenkernel/intern/fmodifier.cc b/source/blender/blenkernel/intern/fmodifier.cc index 8fba3cb446f..af53dadd214 100644 --- a/source/blender/blenkernel/intern/fmodifier.cc +++ b/source/blender/blenkernel/intern/fmodifier.cc @@ -6,6 +6,7 @@ * \ingroup bke */ +#include /* For `min/max`. */ #include #include #include @@ -1327,7 +1328,7 @@ uint evaluate_fmodifiers_storage_size_per_modifier(ListBase *modifiers) continue; } - max_size = MAX2(max_size, fmi->storage_size); + max_size = std::max(max_size, fmi->storage_size); } return max_size; diff --git a/source/blender/blenkernel/intern/gpencil_geom_legacy.cc b/source/blender/blenkernel/intern/gpencil_geom_legacy.cc index cfe499a3a63..c815f067037 100644 --- a/source/blender/blenkernel/intern/gpencil_geom_legacy.cc +++ b/source/blender/blenkernel/intern/gpencil_geom_legacy.cc @@ -1717,7 +1717,7 @@ float BKE_gpencil_stroke_segment_length(const bGPDstroke *gps, } int index = MAX2(start_index, 0) + 1; - int last_index = MIN2(end_index, gps->totpoints - 1) + 1; + int last_index = std::min(end_index, gps->totpoints - 1) + 1; float *last_pt = &gps->points[index - 1].x; float total_length = 0.0f; @@ -3560,8 +3560,8 @@ void BKE_gpencil_stroke_join(bGPDstroke *gps_a, if (smooth) { const int sample_points = 8; /* Get the segment to smooth using n points on each side of the join. */ - int start = MAX2(0, totpoints_a - sample_points); - int end = MIN2(gps_a->totpoints - 1, start + (sample_points * 2)); + int start = std::max(0, totpoints_a - sample_points); + int end = std::min(gps_a->totpoints - 1, start + (sample_points * 2)); const int len = (end - start); float step = 1.0f / ((len / 2) + 1); diff --git a/source/blender/blenkernel/intern/grease_pencil.cc b/source/blender/blenkernel/intern/grease_pencil.cc index 4757f136717..4c3faa0b81d 100644 --- a/source/blender/blenkernel/intern/grease_pencil.cc +++ b/source/blender/blenkernel/intern/grease_pencil.cc @@ -1939,7 +1939,7 @@ static std::string unique_node_name(const GreasePencil &grease_pencil, { using namespace blender; char unique_name[MAX_NAME]; - BLI_strncpy(unique_name, name.c_str(), MAX_NAME); + STRNCPY(unique_name, name.c_str()); VectorSet names = get_node_names(grease_pencil); unique_node_name_ex(names, default_name, unique_name); return unique_name; diff --git a/source/blender/blenkernel/intern/mask_evaluate.cc b/source/blender/blenkernel/intern/mask_evaluate.cc index dcdcfc9aa36..5d7789ffed2 100644 --- a/source/blender/blenkernel/intern/mask_evaluate.cc +++ b/source/blender/blenkernel/intern/mask_evaluate.cc @@ -8,6 +8,7 @@ * Functions for evaluating the mask beziers into points for the outline and feather. */ +#include /* For `min/max`. */ #include #include @@ -57,7 +58,7 @@ uint BKE_mask_spline_resolution(MaskSpline *spline, int width, int height) len = a + b + c; cur_resol = len / max_segment; - resol = MAX2(resol, cur_resol); + resol = std::max(resol, cur_resol); if (resol >= MASK_RESOL_MAX) { break; diff --git a/source/blender/blenkernel/intern/mask_rasterize.cc b/source/blender/blenkernel/intern/mask_rasterize.cc index a9eb71d5872..438ccdb23b9 100644 --- a/source/blender/blenkernel/intern/mask_rasterize.cc +++ b/source/blender/blenkernel/intern/mask_rasterize.cc @@ -50,6 +50,8 @@ * - Campbell */ +#include /* For `min/max`. */ + #include "CLG_log.h" #include "MEM_guardedalloc.h" @@ -630,7 +632,7 @@ void BKE_maskrasterize_handle_init(MaskRasterHandle *mr_handle, const uint resol_a = BKE_mask_spline_resolution(spline, width, height) / 4; const uint resol_b = BKE_mask_spline_feather_resolution(spline, width, height) / 4; - const uint resol = CLAMPIS(MAX2(resol_a, resol_b), 4, 512); + const uint resol = CLAMPIS(std::max(resol_a, resol_b), 4, 512); diff_points = BKE_mask_spline_differentiate_with_resolution(spline, resol, &tot_diff_point); diff --git a/source/blender/blenkernel/intern/mesh_normals.cc b/source/blender/blenkernel/intern/mesh_normals.cc index 640075689f3..5aa268c6c3a 100644 --- a/source/blender/blenkernel/intern/mesh_normals.cc +++ b/source/blender/blenkernel/intern/mesh_normals.cc @@ -23,6 +23,7 @@ #include "BLI_array_utils.hh" #include "BLI_bit_vector.hh" #include "BLI_linklist.h" +#include "BLI_math_base.hh" #include "BLI_math_vector.hh" #include "BLI_memarena.h" #include "BLI_span.hh" @@ -243,7 +244,7 @@ static void accumulate_face_normal_to_vert(const Span positions, } /* Calculate angle between the two face edges incident on this vertex. */ - const float fac = saacos(-dot_v3v3(edvec_prev, edvec_next)); + const float fac = math::safe_acos_approx(-dot_v3v3(edvec_prev, edvec_next)); const float vnor_add[3] = {face_normal[0] * fac, face_normal[1] * fac, face_normal[2] * fac}; float *vnor = vert_normals[face_verts[i_curr]]; @@ -535,7 +536,7 @@ static CornerNormalSpace lnor_space_define(const float lnor[3], if (!edge_vectors.is_empty()) { float alpha = 0.0f; for (const float3 &vec : edge_vectors) { - alpha += saacosf(dot_v3v3(vec, lnor)); + alpha += math::safe_acos_approx(dot_v3v3(vec, lnor)); } /* This piece of code shall only be called for more than one loop. */ /* NOTE: In theory, this could be `count > 2`, @@ -546,8 +547,8 @@ static CornerNormalSpace lnor_space_define(const float lnor[3], lnor_space.ref_alpha = alpha / float(edge_vectors.size()); } else { - lnor_space.ref_alpha = (saacosf(dot_v3v3(vec_ref, lnor)) + - saacosf(dot_v3v3(vec_other, lnor))) / + lnor_space.ref_alpha = (math::safe_acos_approx(dot_v3v3(vec_ref, lnor)) + + math::safe_acos_approx(dot_v3v3(vec_other, lnor))) / 2.0f; } @@ -567,7 +568,7 @@ static CornerNormalSpace lnor_space_define(const float lnor[3], /* Beta is angle between ref_vec and other_vec, around lnor. */ dtp = dot_v3v3(lnor_space.vec_ref, vec_other); if (LIKELY(dtp < LNOR_SPACE_TRIGO_THRESHOLD)) { - const float beta = saacos(dtp); + const float beta = math::safe_acos_approx(dtp); lnor_space.ref_beta = (dot_v3v3(lnor_space.vec_ortho, vec_other) < 0.0f) ? pi2 - beta : beta; } else { @@ -698,7 +699,7 @@ short2 lnor_space_custom_normal_to_data(const CornerNormalSpace &lnor_space, float vec[3], cos_beta; float alpha; - alpha = saacosf(cos_alpha); + alpha = math::safe_acos_approx(cos_alpha); if (alpha > lnor_space.ref_alpha) { /* Note we could stick to [0, pi] range here, * but makes decoding more complex, not worth it. */ @@ -716,7 +717,7 @@ short2 lnor_space_custom_normal_to_data(const CornerNormalSpace &lnor_space, cos_beta = dot_v3v3(lnor_space.vec_ref, vec); if (cos_beta < LNOR_SPACE_TRIGO_THRESHOLD) { - float beta = saacosf(cos_beta); + float beta = math::safe_acos_approx(cos_beta); if (dot_v3v3(lnor_space.vec_ortho, vec) < 0.0f) { beta = pi2 - beta; } @@ -1097,7 +1098,8 @@ static void split_loop_nor_fan_do(LoopSplitTaskDataCommon *common_data, /* Code similar to accumulate_vertex_normals_poly_v3. */ /* Calculate angle between the two face edges incident on this vertex. */ - lnor += face_normals[loop_to_face[mlfan_curr_index]] * saacos(math::dot(vec_curr, vec_prev)); + lnor += face_normals[loop_to_face[mlfan_curr_index]] * + math::safe_acos_approx(math::dot(vec_curr, vec_prev)); processed_corners.append(mlfan_vert_index); diff --git a/source/blender/blenkernel/intern/multires.cc b/source/blender/blenkernel/intern/multires.cc index 93ebab4d521..768487085c5 100644 --- a/source/blender/blenkernel/intern/multires.cc +++ b/source/blender/blenkernel/intern/multires.cc @@ -532,9 +532,9 @@ void multiresModifier_set_levels_from_disps(MultiresModifierData *mmd, Object *o if (mdisp) { mmd->totlvl = get_levels_from_disps(ob); - mmd->lvl = MIN2(mmd->sculptlvl, mmd->totlvl); - mmd->sculptlvl = MIN2(mmd->sculptlvl, mmd->totlvl); - mmd->renderlvl = MIN2(mmd->renderlvl, mmd->totlvl); + mmd->lvl = std::min(mmd->sculptlvl, mmd->totlvl); + mmd->sculptlvl = std::min(mmd->sculptlvl, mmd->totlvl); + mmd->renderlvl = std::min(mmd->renderlvl, mmd->totlvl); } } diff --git a/source/blender/blenkernel/intern/particle.cc b/source/blender/blenkernel/intern/particle.cc index 3ae5a490d5e..8c389cfb7fa 100644 --- a/source/blender/blenkernel/intern/particle.cc +++ b/source/blender/blenkernel/intern/particle.cc @@ -492,12 +492,12 @@ static ParticleCacheKey **psys_alloc_path_cache_buffers(ListBase *bufs, int tot, ParticleCacheKey **cache; int i, totkey, totbufkey; - tot = MAX2(tot, 1); + tot = std::max(tot, 1); totkey = 0; cache = static_cast(MEM_callocN(tot * sizeof(void *), "PathCacheArray")); while (totkey < tot) { - totbufkey = MIN2(tot - totkey, PATH_CACHE_BUF_SIZE); + totbufkey = std::min(tot - totkey, PATH_CACHE_BUF_SIZE); buf = static_cast(MEM_callocN(sizeof(LinkData), "PathCacheLinkData")); buf->data = MEM_callocN(sizeof(ParticleCacheKey) * totbufkey * totkeys, "ParticleCacheKey"); @@ -1309,8 +1309,8 @@ static void init_particle_interpolation(Object *ob, pind->dietime = pa ? pa->dietime : (pind->cache->endframe + 1); if (get_pointcache_times_for_particle(pind->cache, pa - psys->particles, &start, &dietime)) { - pind->birthtime = MAX2(pind->birthtime, start); - pind->dietime = MIN2(pind->dietime, dietime); + pind->birthtime = std::max(pind->birthtime, start); + pind->dietime = std::min(pind->dietime, dietime); } } else { @@ -3352,7 +3352,7 @@ void psys_cache_paths(ParticleSimulationData *sim, float cfra, const bool use_re if (part->draw & PART_ABS_PATH_TIME) { birthtime = MAX2(pind.birthtime, part->path_start); - dietime = MIN2(pind.dietime, part->path_end); + dietime = std::min(pind.dietime, part->path_end); } else { float tb = pind.birthtime; @@ -3674,7 +3674,7 @@ void psys_cache_edit_paths(Depsgraph *depsgraph, return; } - segments = MAX2(segments, 4); + segments = std::max(segments, 4); if (!cache || edit->totpoint != edit->totcached) { /* Clear out old and create new empty path cache. */ @@ -4934,7 +4934,7 @@ bool psys_get_particle_state(ParticleSimulationData *sim, } } - cfra = MIN2(cfra, pa->dietime); + cfra = std::min(cfra, pa->dietime); } if (sim->psys->flag & PSYS_KEYED) { diff --git a/source/blender/blenkernel/intern/particle_child.cc b/source/blender/blenkernel/intern/particle_child.cc index e4a9b5f2b72..82562ce7d9b 100644 --- a/source/blender/blenkernel/intern/particle_child.cc +++ b/source/blender/blenkernel/intern/particle_child.cc @@ -526,7 +526,7 @@ void do_kink(ParticleKey *state, sub_v3_v3v3(par_vec, state->co, state_co); length = normalize_v3(par_vec); - mul_v3_fl(par_vec, MIN2(length, amplitude / 2.0f)); + mul_v3_fl(par_vec, std::min(length, amplitude / 2.0f)); add_v3_v3v3(state_co, par_co, y_vec); add_v3_v3(state_co, z_vec); diff --git a/source/blender/blenkernel/intern/particle_distribute.cc b/source/blender/blenkernel/intern/particle_distribute.cc index 17064548bd6..bba5890c739 100644 --- a/source/blender/blenkernel/intern/particle_distribute.cc +++ b/source/blender/blenkernel/intern/particle_distribute.cc @@ -128,11 +128,11 @@ static void distribute_grid(Mesh *mesh, ParticleSystem *psys) /* float errors grrr. */ size[(axis + 1) % 3] = MIN2(size[(axis + 1) % 3], res); - size[(axis + 2) % 3] = MIN2(size[(axis + 2) % 3], res); + size[(axis + 2) % 3] = std::min(size[(axis + 2) % 3], res); - size[0] = MAX2(size[0], 1); - size[1] = MAX2(size[1], 1); - size[2] = MAX2(size[2], 1); + size[0] = std::max(size[0], 1); + size[1] = std::max(size[1], 1); + size[2] = std::max(size[2], 1); /* no full offset for flat/thin objects */ min[0] += d < delta[0] ? d / 2.0f : delta[0] / 2.0f; diff --git a/source/blender/blenkernel/intern/particle_system.cc b/source/blender/blenkernel/intern/particle_system.cc index 5b323abddec..821021b49d1 100644 --- a/source/blender/blenkernel/intern/particle_system.cc +++ b/source/blender/blenkernel/intern/particle_system.cc @@ -1132,7 +1132,7 @@ void reset_particle(ParticleSimulationData *sim, ParticleData *pa, float dtime, (sim->psys->pointcache->mem_cache.first)) { float dietime = psys_get_dietime_from_cache(sim->psys->pointcache, p); - pa->dietime = MIN2(pa->dietime, dietime); + pa->dietime = std::min(pa->dietime, dietime); } if (pa->time > cfra) { @@ -3003,7 +3003,7 @@ static int collision_response(ParticleSimulationData *sim, /* Convert to angular velocity. */ cross_v3_v3v3(ave, vr_tan, pce->nor); - mul_v3_fl(ave, 1.0f / MAX2(pa->size, 0.001f)); + mul_v3_fl(ave, 1.0f / std::max(pa->size, 0.001f)); /* only friction will cause change in linear & angular velocity */ interp_v3_v3v3(pa->state.ave, pa->state.ave, ave, frict); @@ -4688,8 +4688,8 @@ void psys_changed_type(Object *ob, ParticleSystem *psys) else { free_hair(ob, psys, 1); - CLAMP(part->path_start, 0.0f, MAX2(100.0f, part->end + part->lifetime)); - CLAMP(part->path_end, 0.0f, MAX2(100.0f, part->end + part->lifetime)); + CLAMP(part->path_start, 0.0f, std::max(100.0f, part->end + part->lifetime)); + CLAMP(part->path_end, 0.0f, std::max(100.0f, part->end + part->lifetime)); } psys_reset(psys, PSYS_RESET_ALL); diff --git a/source/blender/blenkernel/intern/pointcache.cc b/source/blender/blenkernel/intern/pointcache.cc index 3c5d43dd621..f98fe50b8fc 100644 --- a/source/blender/blenkernel/intern/pointcache.cc +++ b/source/blender/blenkernel/intern/pointcache.cc @@ -410,8 +410,8 @@ static void ptcache_particle_interpolate(int index, } cfra = MIN2(cfra, pa->dietime); - cfra1 = MIN2(cfra1, pa->dietime); - cfra2 = MIN2(cfra2, pa->dietime); + cfra1 = std::min(cfra1, pa->dietime); + cfra2 = std::min(cfra2, pa->dietime); if (cfra1 == cfra2) { return; @@ -2372,7 +2372,7 @@ int BKE_ptcache_read(PTCacheID *pid, float cfra, bool no_extrapolate_old) pid->cache->flag &= ~PTCACHE_FRAMES_SKIPPED; } - BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_AFTER, MAX2(cfrai, pid->cache->last_exact)); + BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_AFTER, std::max(cfrai, pid->cache->last_exact)); } return ret; @@ -2653,7 +2653,7 @@ void BKE_ptcache_id_clear(PTCacheID *pid, int mode, uint cfra) if (strstr(de->d_name, ext)) { /* Do we have the right extension? */ if (STREQLEN(filepath, de->d_name, len)) { /* Do we have the right prefix. */ if (mode == PTCACHE_CLEAR_ALL) { - pid->cache->last_exact = MIN2(pid->cache->startframe, 0); + pid->cache->last_exact = std::min(pid->cache->startframe, 0); BLI_path_join(path_full, sizeof(path_full), path, de->d_name); BLI_delete(path_full, false, false); } @@ -2688,7 +2688,7 @@ void BKE_ptcache_id_clear(PTCacheID *pid, int mode, uint cfra) if (mode == PTCACHE_CLEAR_ALL) { /* We want startframe if the cache starts before zero. */ - pid->cache->last_exact = MIN2(pid->cache->startframe, 0); + pid->cache->last_exact = std::min(pid->cache->startframe, 0); for (; pm; pm = pm->next) { ptcache_mem_clear(pm); } @@ -2803,7 +2803,7 @@ void BKE_ptcache_id_time( time = BKE_scene_ctime_get(scene); nexttime = BKE_scene_frame_to_ctime(scene, scene->r.cfra + 1); - *timescale = MAX2(nexttime - time, 0.0f); + *timescale = std::max(nexttime - time, 0.0f); } if (startframe && endframe) { @@ -3219,7 +3219,7 @@ void BKE_ptcache_bake(PTCacheBaker *baker) BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0); } - startframe = MAX2(cache->last_exact, cache->startframe); + startframe = std::max(cache->last_exact, cache->startframe); if (bake) { endframe = cache->endframe; @@ -3603,8 +3603,8 @@ void BKE_ptcache_load_external(PTCacheID *pid) if (frame != -1) { if (frame) { - start = MIN2(start, frame); - end = MAX2(end, frame); + start = std::min(start, frame); + end = std::max(end, frame); } else { info = 1; @@ -3774,7 +3774,7 @@ void BKE_ptcache_invalidate(PointCache *cache) if (cache) { cache->flag &= ~PTCACHE_SIMULATION_VALID; cache->simframe = 0; - cache->last_exact = MIN2(cache->startframe, 0); + cache->last_exact = std::min(cache->startframe, 0); } } diff --git a/source/blender/blenkernel/intern/rigidbody.cc b/source/blender/blenkernel/intern/rigidbody.cc index 0aa861b5790..0300de863ef 100644 --- a/source/blender/blenkernel/intern/rigidbody.cc +++ b/source/blender/blenkernel/intern/rigidbody.cc @@ -501,7 +501,7 @@ static rbCollisionShape *rigidbody_validate_sim_shape_helper(RigidBodyWorld *rbw if (ELEM(rbo->shape, RB_SHAPE_CAPSULE, RB_SHAPE_CYLINDER, RB_SHAPE_CONE)) { /* take radius as largest x/y dimension, and height as z-dimension */ - radius = MAX2(size[0], size[1]); + radius = std::max(size[0], size[1]); height = size[2]; } else if (rbo->shape == RB_SHAPE_SPHERE) { diff --git a/source/blender/blenkernel/intern/subdiv_modifier.cc b/source/blender/blenkernel/intern/subdiv_modifier.cc index 795dbe6bb80..c6a559340ee 100644 --- a/source/blender/blenkernel/intern/subdiv_modifier.cc +++ b/source/blender/blenkernel/intern/subdiv_modifier.cc @@ -97,7 +97,7 @@ static bool is_subdivision_evaluation_possible_on_gpu() return false; } - if (!(GPU_compute_shader_support())) { + if (!GPU_compute_shader_support()) { return false; } diff --git a/source/blender/blenkernel/intern/subsurf_ccg.cc b/source/blender/blenkernel/intern/subsurf_ccg.cc index 6443890a3e6..94cbdb83924 100644 --- a/source/blender/blenkernel/intern/subsurf_ccg.cc +++ b/source/blender/blenkernel/intern/subsurf_ccg.cc @@ -94,7 +94,7 @@ static CCGSubSurf *_getSubSurf(CCGSubSurf *prevSS, int subdivLevels, int numLaye int normalOffset = 0; /* (subdivLevels == 0) is not allowed */ - subdivLevels = MAX2(subdivLevels, 1); + subdivLevels = std::max(subdivLevels, 1); if (prevSS) { int oldUseAging; diff --git a/source/blender/blenkernel/intern/text.cc b/source/blender/blenkernel/intern/text.cc index 9eac59c470e..e7d7b93fb20 100644 --- a/source/blender/blenkernel/intern/text.cc +++ b/source/blender/blenkernel/intern/text.cc @@ -2113,7 +2113,7 @@ static bool txt_select_unprefix(Text *text, const char *remove, const bool requi if (text->curl == text->sell) { if (changed) { - text->selc = MAX2(text->selc - indentlen, 0); + text->selc = std::max(text->selc - indentlen, 0); } break; } @@ -2123,7 +2123,7 @@ static bool txt_select_unprefix(Text *text, const char *remove, const bool requi } if (unindented_first) { - text->curc = MAX2(text->curc - indentlen, 0); + text->curc = std::max(text->curc - indentlen, 0); } while (num > 0) { diff --git a/source/blender/blenkernel/intern/unit.cc b/source/blender/blenkernel/intern/unit.cc index d69e0c83d78..71854bdf646 100644 --- a/source/blender/blenkernel/intern/unit.cc +++ b/source/blender/blenkernel/intern/unit.cc @@ -6,6 +6,7 @@ * \ingroup bke */ +#include /* For `min/max`. */ #include #include #include @@ -1673,17 +1674,17 @@ static const bUnitDef *get_preferred_display_unit_if_used(int type, PreferredUni if (units.length == USER_UNIT_ADAPTIVE) { return nullptr; } - return usys->units + MIN2(units.length, max_offset); + return usys->units + std::min(units.length, max_offset); case B_UNIT_MASS: if (units.mass == USER_UNIT_ADAPTIVE) { return nullptr; } - return usys->units + MIN2(units.mass, max_offset); + return usys->units + std::min(units.mass, max_offset); case B_UNIT_TIME: if (units.time == USER_UNIT_ADAPTIVE) { return nullptr; } - return usys->units + MIN2(units.time, max_offset); + return usys->units + std::min(units.time, max_offset); case B_UNIT_ROTATION: if (units.rotation == 0) { return usys->units + 0; @@ -1696,7 +1697,7 @@ static const bUnitDef *get_preferred_display_unit_if_used(int type, PreferredUni if (units.temperature == USER_UNIT_ADAPTIVE) { return nullptr; } - return usys->units + MIN2(units.temperature, max_offset); + return usys->units + std::min(units.temperature, max_offset); default: break; } diff --git a/source/blender/blenlib/BLI_math_base.hh b/source/blender/blenlib/BLI_math_base.hh index 6176f9724bf..dfed31bd5cf 100644 --- a/source/blender/blenlib/BLI_math_base.hh +++ b/source/blender/blenlib/BLI_math_base.hh @@ -192,6 +192,24 @@ template inline T safe_acos(const T &a) return math::acos((a)); } +/* Faster/approximate version of acosf. Max error 4.51803e-5 (0.00258 degrees).*/ +inline float safe_acos_approx(float x) +{ + const float f = fabsf(x); + /* clamp and crush denormals. */ + const float m = (f < 1.0f) ? 1.0f - (1.0f - f) : 1.0f; + /* Based on http://www.pouet.net/topic.php?which=9132&page=2 + * 85% accurate (ULP 0) + * Examined 2130706434 values of acos: + * 15.2000597 avg ULP diff, 4492 max ULP, 4.51803e-05 max error // without "denormal crush" + * Examined 2130706434 values of acos: + * 15.2007108 avg ULP diff, 4492 max ULP, 4.51803e-05 max error // with "denormal crush" + */ + const float a = sqrtf(1.0f - m) * + (1.5707963267f + m * (-0.213300989f + m * (0.077980478f + m * -0.02164095f))); + return x < 0 ? (float)M_PI - a : a; +} + template inline T asin(const T &a) { return std::asin(a); diff --git a/source/blender/blenlib/BLI_math_geom.h b/source/blender/blenlib/BLI_math_geom.h index f14a3776f7a..f23c49d23ea 100644 --- a/source/blender/blenlib/BLI_math_geom.h +++ b/source/blender/blenlib/BLI_math_geom.h @@ -788,14 +788,8 @@ bool isect_ray_line_v3(const float ray_origin[3], /* Point in polygon. */ -bool isect_point_poly_v2(const float pt[2], - const float verts[][2], - unsigned int nr, - bool use_holes); -bool isect_point_poly_v2_int(const int pt[2], - const int verts[][2], - unsigned int nr, - bool use_holes); +bool isect_point_poly_v2(const float pt[2], const float verts[][2], unsigned int nr); +bool isect_point_poly_v2_int(const int pt[2], const int verts[][2], unsigned int nr); /** * Point in quad - only convex quads. diff --git a/source/blender/blenlib/CMakeLists.txt b/source/blender/blenlib/CMakeLists.txt index 594ff99e515..cf087d4f68f 100644 --- a/source/blender/blenlib/CMakeLists.txt +++ b/source/blender/blenlib/CMakeLists.txt @@ -101,7 +101,7 @@ set(SRC intern/math_color.c intern/math_color_blend_inline.c intern/math_color_inline.c - intern/math_geom.c + intern/math_geom.cc intern/math_geom_inline.c intern/math_interp.c intern/math_matrix.c diff --git a/source/blender/blenlib/intern/BLI_filelist.cc b/source/blender/blenlib/intern/BLI_filelist.cc index 407223311a2..c3da3ae9353 100644 --- a/source/blender/blenlib/intern/BLI_filelist.cc +++ b/source/blender/blenlib/intern/BLI_filelist.cc @@ -48,7 +48,7 @@ * Ordering function for sorting lists of files/directories. Returns -1 if * entry1 belongs before entry2, 0 if they are equal, 1 if they should be swapped. */ -static int direntry_cmp(struct direntry *entry1, struct direntry *entry2) +static int direntry_cmp(direntry *entry1, direntry *entry2) { /* type is equal to stat.st_mode */ @@ -101,14 +101,14 @@ static int direntry_cmp(struct direntry *entry1, struct direntry *entry2) } struct BuildDirCtx { - struct direntry *files; /* array[files_num] */ + direntry *files; /* array[files_num] */ int files_num; }; /** * Scans the directory named *dirname and appends entries for its contents to files. */ -static void bli_builddir(struct BuildDirCtx *dir_ctx, const char *dirname) +static void bli_builddir(BuildDirCtx *dir_ctx, const char *dirname) { DIR *dir = opendir(dirname); if (UNLIKELY(dir == nullptr)) { @@ -121,7 +121,7 @@ static void bli_builddir(struct BuildDirCtx *dir_ctx, const char *dirname) ListBase dirbase = {nullptr, nullptr}; int newnum = 0; - const struct dirent *fname; + const dirent *fname; bool has_current = false, has_parent = false; char dirname_with_slash[FILE_MAXDIR + 1]; @@ -136,7 +136,7 @@ static void bli_builddir(struct BuildDirCtx *dir_ctx, const char *dirname) } while ((fname = readdir(dir)) != nullptr) { - struct dirlink *const dlink = (struct dirlink *)malloc(sizeof(dirlink)); + dirlink *const dlink = (dirlink *)malloc(sizeof(dirlink)); if (dlink != nullptr) { dlink->name = BLI_strdup(fname->d_name); if (FILENAME_IS_PARENT(dlink->name)) { @@ -155,7 +155,7 @@ static void bli_builddir(struct BuildDirCtx *dir_ctx, const char *dirname) STRNCPY(pardir, dirname); if (BLI_path_parent_dir(pardir) && (BLI_access(pardir, R_OK) == 0)) { - struct dirlink *const dlink = (struct dirlink *)malloc(sizeof(dirlink)); + dirlink *const dlink = (dirlink *)malloc(sizeof(dirlink)); if (dlink != nullptr) { dlink->name = BLI_strdup(FILENAME_PARENT); BLI_addhead(&dirbase, dlink); @@ -164,7 +164,7 @@ static void bli_builddir(struct BuildDirCtx *dir_ctx, const char *dirname) } } if (!has_current) { - struct dirlink *const dlink = (struct dirlink *)malloc(sizeof(dirlink)); + dirlink *const dlink = (dirlink *)malloc(sizeof(dirlink)); if (dlink != nullptr) { dlink->name = BLI_strdup(FILENAME_CURRENT); BLI_addhead(&dirbase, dlink); @@ -186,7 +186,7 @@ static void bli_builddir(struct BuildDirCtx *dir_ctx, const char *dirname) } if (dir_ctx->files == nullptr) { - dir_ctx->files = (struct direntry *)MEM_mallocN(newnum * sizeof(direntry), __func__); + dir_ctx->files = (direntry *)MEM_mallocN(newnum * sizeof(direntry), __func__); } if (UNLIKELY(dir_ctx->files == nullptr)) { @@ -194,8 +194,8 @@ static void bli_builddir(struct BuildDirCtx *dir_ctx, const char *dirname) dir_ctx->files_num = 0; } else { - struct dirlink *dlink = (dirlink *)dirbase.first; - struct direntry *file = &dir_ctx->files[dir_ctx->files_num]; + dirlink *dlink = (dirlink *)dirbase.first; + direntry *file = &dir_ctx->files[dir_ctx->files_num]; while (dlink) { memset(file, 0, sizeof(direntry)); @@ -226,9 +226,9 @@ static void bli_builddir(struct BuildDirCtx *dir_ctx, const char *dirname) closedir(dir); } -uint BLI_filelist_dir_contents(const char *dirname, struct direntry **r_filelist) +uint BLI_filelist_dir_contents(const char *dirname, direntry **r_filelist) { - struct BuildDirCtx dir_ctx; + BuildDirCtx dir_ctx; dir_ctx.files_num = 0; dir_ctx.files = nullptr; @@ -322,7 +322,7 @@ void BLI_filelist_entry_owner_to_string(const struct stat *st, UNUSED_VARS(st); BLI_strncpy(r_owner, "unknown", FILELIST_DIRENTRY_OWNER_LEN); #else - struct passwd *pwuser = getpwuid(st->st_uid); + passwd *pwuser = getpwuid(st->st_uid); if (pwuser) { BLI_strncpy(r_owner, pwuser->pw_name, sizeof(*r_owner) * FILELIST_DIRENTRY_OWNER_LEN); @@ -348,8 +348,8 @@ void BLI_filelist_entry_datetime_to_string(const struct stat *st, if (r_is_today || r_is_yesterday) { /* `localtime()` has only one buffer so need to get data out before called again. */ - const time_t ts_now = time(NULL); - struct tm *today = localtime(&ts_now); + const time_t ts_now = time(nullptr); + tm *today = localtime(&ts_now); today_year = today->tm_year; today_yday = today->tm_yday; @@ -368,7 +368,7 @@ void BLI_filelist_entry_datetime_to_string(const struct stat *st, } const time_t ts_mtime = ts; - const struct tm *tm = localtime(st ? &st->st_mtime : &ts_mtime); + const tm *tm = localtime(st ? &st->st_mtime : &ts_mtime); const time_t zero = 0; /* Prevent impossible dates in windows. */ @@ -395,7 +395,7 @@ void BLI_filelist_entry_datetime_to_string(const struct stat *st, } } -void BLI_filelist_entry_duplicate(struct direntry *dst, const struct direntry *src) +void BLI_filelist_entry_duplicate(direntry *dst, const direntry *src) { *dst = *src; if (dst->relname) { @@ -406,8 +406,8 @@ void BLI_filelist_entry_duplicate(struct direntry *dst, const struct direntry *s } } -void BLI_filelist_duplicate(struct direntry **dest_filelist, - struct direntry *const src_filelist, +void BLI_filelist_duplicate(direntry **dest_filelist, + direntry *const src_filelist, const uint nrentries) { uint i; @@ -415,13 +415,13 @@ void BLI_filelist_duplicate(struct direntry **dest_filelist, *dest_filelist = static_cast( MEM_mallocN(sizeof(**dest_filelist) * size_t(nrentries), __func__)); for (i = 0; i < nrentries; i++) { - struct direntry *const src = &src_filelist[i]; - struct direntry *dst = &(*dest_filelist)[i]; + direntry *const src = &src_filelist[i]; + direntry *dst = &(*dest_filelist)[i]; BLI_filelist_entry_duplicate(dst, src); } } -void BLI_filelist_entry_free(struct direntry *entry) +void BLI_filelist_entry_free(direntry *entry) { if (entry->relname) { MEM_freeN((void *)entry->relname); @@ -431,7 +431,7 @@ void BLI_filelist_entry_free(struct direntry *entry) } } -void BLI_filelist_free(struct direntry *filelist, const uint nrentries) +void BLI_filelist_free(direntry *filelist, const uint nrentries) { uint i; for (i = 0; i < nrentries; i++) { diff --git a/source/blender/blenlib/intern/bit_ref.cc b/source/blender/blenlib/intern/bit_ref.cc index b6bc02dfd7d..c9572477a68 100644 --- a/source/blender/blenlib/intern/bit_ref.cc +++ b/source/blender/blenlib/intern/bit_ref.cc @@ -1,4 +1,4 @@ -/* SPDX-FileCopyrightText: 2023 Blender Foundation +/* SPDX-FileCopyrightText: 2023 Blender Authors * * SPDX-License-Identifier: GPL-2.0-or-later */ diff --git a/source/blender/blenlib/intern/cpp_type.cc b/source/blender/blenlib/intern/cpp_type.cc index ee17924bc05..7d590a8a663 100644 --- a/source/blender/blenlib/intern/cpp_type.cc +++ b/source/blender/blenlib/intern/cpp_type.cc @@ -1,4 +1,4 @@ -/* SPDX-FileCopyrightText: 2023 Blender Foundation +/* SPDX-FileCopyrightText: 2023 Blender Authors * * SPDX-License-Identifier: GPL-2.0-or-later */ diff --git a/source/blender/blenlib/intern/fileops_c.cc b/source/blender/blenlib/intern/fileops_c.cc index d0cda1617ca..c51f2b2a74c 100644 --- a/source/blender/blenlib/intern/fileops_c.cc +++ b/source/blender/blenlib/intern/fileops_c.cc @@ -862,9 +862,9 @@ static int recursive_operation(const char *startfrom, RecursiveOp_Callback callback_dir_post) { struct stat st; - char *from = NULL, *to = nullptr; - char *from_path = NULL, *to_path = nullptr; - struct dirent **dirlist = nullptr; + char *from = nullptr, *to = nullptr; + char *from_path = nullptr, *to_path = nullptr; + dirent **dirlist = nullptr; size_t from_alloc_len = -1, to_alloc_len = -1; int i, n = 0, ret = 0; @@ -916,7 +916,7 @@ static int recursive_operation(const char *startfrom, } for (i = 0; i < n; i++) { - const struct dirent *const dirent = dirlist[i]; + const dirent *const dirent = dirlist[i]; if (FILENAME_IS_CURRPAR(dirent->d_name)) { continue; @@ -1062,8 +1062,8 @@ static int delete_soft(const char *file, const char **error_message) char *xdg_current_desktop = getenv("XDG_CURRENT_DESKTOP"); char *xdg_session_desktop = getenv("XDG_SESSION_DESKTOP"); - if ((xdg_current_desktop != NULL && STREQ(xdg_current_desktop, "KDE")) || - (xdg_session_desktop != NULL && STREQ(xdg_session_desktop, "KDE"))) + if ((xdg_current_desktop != nullptr && STREQ(xdg_current_desktop, "KDE")) || + (xdg_session_desktop != nullptr && STREQ(xdg_session_desktop, "KDE"))) { args[0] = "kioclient5"; args[1] = "move"; diff --git a/source/blender/blenlib/intern/hash_tables.cc b/source/blender/blenlib/intern/hash_tables.cc index f0c36eab60e..a0760c42e3f 100644 --- a/source/blender/blenlib/intern/hash_tables.cc +++ b/source/blender/blenlib/intern/hash_tables.cc @@ -1,4 +1,4 @@ -/* SPDX-FileCopyrightText: 2023 Blender Foundation +/* SPDX-FileCopyrightText: 2023 Blender Authors * * SPDX-License-Identifier: GPL-2.0-or-later */ diff --git a/source/blender/blenlib/intern/index_range.cc b/source/blender/blenlib/intern/index_range.cc index 559f4fd6797..315a14e2790 100644 --- a/source/blender/blenlib/intern/index_range.cc +++ b/source/blender/blenlib/intern/index_range.cc @@ -1,4 +1,4 @@ -/* SPDX-FileCopyrightText: 2023 Blender Foundation +/* SPDX-FileCopyrightText: 2023 Blender Authors * * SPDX-License-Identifier: GPL-2.0-or-later */ diff --git a/source/blender/blenlib/intern/lasso_2d.c b/source/blender/blenlib/intern/lasso_2d.c index 18b0d141743..8a20dbe2c25 100644 --- a/source/blender/blenlib/intern/lasso_2d.c +++ b/source/blender/blenlib/intern/lasso_2d.c @@ -48,7 +48,7 @@ bool BLI_lasso_is_point_inside(const int mcoords[][2], } const int pt[2] = {sx, sy}; - return isect_point_poly_v2_int(pt, mcoords, mcoords_len, true); + return isect_point_poly_v2_int(pt, mcoords, mcoords_len); } bool BLI_lasso_is_edge_inside(const int mcoords[][2], diff --git a/source/blender/blenlib/intern/math_basis_types.cc b/source/blender/blenlib/intern/math_basis_types.cc index a3e6422d1c4..d99e4aba2a6 100644 --- a/source/blender/blenlib/intern/math_basis_types.cc +++ b/source/blender/blenlib/intern/math_basis_types.cc @@ -1,4 +1,4 @@ -/* SPDX-FileCopyrightText: 2023 Blender Foundation +/* SPDX-FileCopyrightText: 2023 Blender Authors * * SPDX-License-Identifier: GPL-2.0-or-later */ diff --git a/source/blender/blenlib/intern/math_geom.c b/source/blender/blenlib/intern/math_geom.cc similarity index 95% rename from source/blender/blenlib/intern/math_geom.c rename to source/blender/blenlib/intern/math_geom.cc index 93839a6b65b..996711a0855 100644 --- a/source/blender/blenlib/intern/math_geom.c +++ b/source/blender/blenlib/intern/math_geom.cc @@ -6,11 +6,11 @@ * \ingroup bli */ +#include "BLI_array.hh" #include "BLI_math_base.h" +#include "BLI_math_base.hh" #include "BLI_math_geom.h" -#include "MEM_guardedalloc.h" - #include "BLI_math_bits.h" #include "BLI_math_matrix.h" #include "BLI_math_rotation.h" @@ -654,7 +654,7 @@ void aabb_get_near_far_from_plane(const float plane_no[3], /** \name dist_squared_to_ray_to_aabb and helpers * \{ */ -void dist_squared_ray_to_aabb_v3_precalc(struct DistRayAABB_Precalc *neasrest_precalc, +void dist_squared_ray_to_aabb_v3_precalc(DistRayAABB_Precalc *neasrest_precalc, const float ray_origin[3], const float ray_direction[3]) { @@ -668,7 +668,7 @@ void dist_squared_ray_to_aabb_v3_precalc(struct DistRayAABB_Precalc *neasrest_pr } } -float dist_squared_ray_to_aabb_v3(const struct DistRayAABB_Precalc *data, +float dist_squared_ray_to_aabb_v3(const DistRayAABB_Precalc *data, const float bb_min[3], const float bb_max[3], float r_point[3], @@ -764,7 +764,7 @@ float dist_squared_ray_to_aabb_v3_simple(const float ray_origin[3], float r_point[3], float *r_depth) { - struct DistRayAABB_Precalc data; + DistRayAABB_Precalc data; dist_squared_ray_to_aabb_v3_precalc(&data, ray_origin, ray_direction); return dist_squared_ray_to_aabb_v3(&data, bb_min, bb_max, r_point, r_depth); } @@ -775,7 +775,7 @@ float dist_squared_ray_to_aabb_v3_simple(const float ray_origin[3], /** \name dist_squared_to_projected_aabb and helpers * \{ */ -void dist_squared_to_projected_aabb_precalc(struct DistProjectedAABBPrecalc *precalc, +void dist_squared_to_projected_aabb_precalc(DistProjectedAABBPrecalc *precalc, const float projmat[4][4], const float winsize[2], const float mval[2]) @@ -827,7 +827,7 @@ void dist_squared_to_projected_aabb_precalc(struct DistProjectedAABBPrecalc *pre } } -float dist_squared_to_projected_aabb(struct DistProjectedAABBPrecalc *data, +float dist_squared_to_projected_aabb(DistProjectedAABBPrecalc *data, const float bbmin[3], const float bbmax[3], bool r_axis_closest[3]) @@ -963,7 +963,7 @@ float dist_squared_to_projected_aabb_simple(const float projmat[4][4], const float bbmin[3], const float bbmax[3]) { - struct DistProjectedAABBPrecalc data; + DistProjectedAABBPrecalc data; dist_squared_to_projected_aabb_precalc(&data, projmat, winsize, mval); bool dummy[3] = {true, true, true}; @@ -1071,14 +1071,14 @@ int isect_seg_seg_v2_int(const int v1[2], const int v2[2], const int v3[2], cons { float div, lambda, mu; - div = (float)((v2[0] - v1[0]) * (v4[1] - v3[1]) - (v2[1] - v1[1]) * (v4[0] - v3[0])); + div = float((v2[0] - v1[0]) * (v4[1] - v3[1]) - (v2[1] - v1[1]) * (v4[0] - v3[0])); if (div == 0.0f) { return ISECT_LINE_LINE_COLINEAR; } - lambda = (float)((v1[1] - v3[1]) * (v4[0] - v3[0]) - (v1[0] - v3[0]) * (v4[1] - v3[1])) / div; + lambda = float((v1[1] - v3[1]) * (v4[0] - v3[0]) - (v1[0] - v3[0]) * (v4[1] - v3[1])) / div; - mu = (float)((v1[1] - v3[1]) * (v2[0] - v1[0]) - (v1[0] - v3[0]) * (v2[1] - v1[1])) / div; + mu = float((v1[1] - v3[1]) * (v2[0] - v1[0]) - (v1[0] - v3[0]) * (v2[1] - v1[1])) / div; if (lambda >= 0.0f && lambda <= 1.0f && mu >= 0.0f && mu <= 1.0f) { if (lambda == 0.0f || lambda == 1.0f || mu == 0.0f || mu == 1.0f) { @@ -1121,9 +1121,9 @@ int isect_seg_seg_v2(const float v1[2], const float v2[2], const float v3[2], co return ISECT_LINE_LINE_COLINEAR; } - lambda = ((float)(v1[1] - v3[1]) * (v4[0] - v3[0]) - (v1[0] - v3[0]) * (v4[1] - v3[1])) / div; + lambda = (float(v1[1] - v3[1]) * (v4[0] - v3[0]) - (v1[0] - v3[0]) * (v4[1] - v3[1])) / div; - mu = ((float)(v1[1] - v3[1]) * (v2[0] - v1[0]) - (v1[0] - v3[0]) * (v2[1] - v1[1])) / div; + mu = (float(v1[1] - v3[1]) * (v2[0] - v1[0]) - (v1[0] - v3[0]) * (v2[1] - v1[1])) / div; if (lambda >= 0.0f && lambda <= 1.0f && mu >= 0.0f && mu <= 1.0f) { if (lambda == 0.0f || lambda == 1.0f || mu == 0.0f || mu == 1.0f) { @@ -1360,16 +1360,14 @@ int isect_line_sphere_v3(const float l1[3], float r_p1[3], float r_p2[3]) { - /* adapted for use in blender by Campbell Barton - 2011 + /* Adapted for use in blender by Campbell Barton, 2011. * - * atelier iebele abel - 2001 - * * http://www.iebele.nl + * `Atelier Iebele Abel ` - 2001. * * sphere_line_intersection function adapted from: * http://astronomy.swin.edu.au/pbourke/geometry/sphereline - * Paul Bourke - */ + * `Paul Bourke `. */ const float ldir[3] = { l2[0] - l1[0], @@ -1463,10 +1461,7 @@ int isect_line_sphere_v2(const float l1[2], return -1; } -bool isect_point_poly_v2(const float pt[2], - const float verts[][2], - const uint nr, - const bool UNUSED(use_holes)) +bool isect_point_poly_v2(const float pt[2], const float verts[][2], const uint nr) { /* Keep in sync with #isect_point_poly_v2_int. */ @@ -1483,10 +1478,7 @@ bool isect_point_poly_v2(const float pt[2], } return isect; } -bool isect_point_poly_v2_int(const int pt[2], - const int verts[][2], - const uint nr, - const bool UNUSED(use_holes)) +bool isect_point_poly_v2_int(const int pt[2], const int verts[][2], const uint nr) { /* Keep in sync with #isect_point_poly_v2. */ @@ -1790,7 +1782,7 @@ bool isect_ray_tri_epsilon_v3(const float ray_origin[3], return true; } -void isect_ray_tri_watertight_v3_precalc(struct IsectRayPrecalc *isect_precalc, +void isect_ray_tri_watertight_v3_precalc(IsectRayPrecalc *isect_precalc, const float ray_direction[3]) { float inv_dir_z; @@ -1818,7 +1810,7 @@ void isect_ray_tri_watertight_v3_precalc(struct IsectRayPrecalc *isect_precalc, } bool isect_ray_tri_watertight_v3(const float ray_origin[3], - const struct IsectRayPrecalc *isect_precalc, + const IsectRayPrecalc *isect_precalc, const float v0[3], const float v1[3], const float v2[3], @@ -1868,7 +1860,7 @@ bool isect_ray_tri_watertight_v3(const float ray_origin[3], /* Calculate scaled z-coordinates of vertices and use them to calculate * the hit distance. */ - const int sign_det = (float_as_int(det) & (int)0x80000000); + const int sign_det = (float_as_int(det) & int(0x80000000)); const float t = (u * a_kz + v * b_kz + w * c_kz) * sz; const float sign_t = xor_fl(t, sign_det); if ((sign_t < 0.0f) @@ -1901,7 +1893,7 @@ bool isect_ray_tri_watertight_v3_simple(const float ray_origin[3], float *r_lambda, float r_uv[2]) { - struct IsectRayPrecalc isect_precalc; + IsectRayPrecalc isect_precalc; isect_ray_tri_watertight_v3_precalc(&isect_precalc, ray_direction); return isect_ray_tri_watertight_v3(ray_origin, &isect_precalc, v0, v1, v2, r_lambda, r_uv); } @@ -2259,9 +2251,9 @@ bool isect_tri_tri_v3_ex(const float tri_a[3][3], sub_v3db_v3fl_v3fl(bc, tri_a[2], tri_a[1]); cross_v3_v3v3_db(plane_a, ba, bc); plane_a[3] = -dot_v3db_v3fl(plane_a, tri_a[1]); - side[1][0] = (float)(dot_v3db_v3fl(plane_a, tri_b[0]) + plane_a[3]); - side[1][1] = (float)(dot_v3db_v3fl(plane_a, tri_b[1]) + plane_a[3]); - side[1][2] = (float)(dot_v3db_v3fl(plane_a, tri_b[2]) + plane_a[3]); + side[1][0] = float(dot_v3db_v3fl(plane_a, tri_b[0]) + plane_a[3]); + side[1][1] = float(dot_v3db_v3fl(plane_a, tri_b[1]) + plane_a[3]); + side[1][2] = float(dot_v3db_v3fl(plane_a, tri_b[2]) + plane_a[3]); if (!side[1][0] && !side[1][1] && !side[1][2]) { /* Coplanar case is not supported. */ @@ -2280,9 +2272,9 @@ bool isect_tri_tri_v3_ex(const float tri_a[3][3], sub_v3db_v3fl_v3fl(bc, tri_b[2], tri_b[1]); cross_v3_v3v3_db(plane_b, ba, bc); plane_b[3] = -dot_v3db_v3fl(plane_b, tri_b[1]); - side[0][0] = (float)(dot_v3db_v3fl(plane_b, tri_a[0]) + plane_b[3]); - side[0][1] = (float)(dot_v3db_v3fl(plane_b, tri_a[1]) + plane_b[3]); - side[0][2] = (float)(dot_v3db_v3fl(plane_b, tri_a[2]) + plane_b[3]); + side[0][0] = float(dot_v3db_v3fl(plane_b, tri_a[0]) + plane_b[3]); + side[0][1] = float(dot_v3db_v3fl(plane_b, tri_a[1]) + plane_b[3]); + side[0][2] = float(dot_v3db_v3fl(plane_b, tri_a[2]) + plane_b[3]); if ((side[0][0] && side[0][1] && side[0][2]) && (side[0][0] < 0.0f) == (side[0][1] < 0.0f) && (side[0][0] < 0.0f) == (side[0][2] < 0.0f)) @@ -2332,13 +2324,13 @@ bool isect_tri_tri_v3_ex(const float tri_a[3][3], SWAP(int, tri_i[0], tri_i[2]); } - range[i].min = (float)(dot_b + offset0); - range[i].max = (float)(dot_b + offset1); + range[i].min = float(dot_b + offset0); + range[i].max = float(dot_b + offset1); interp_v3_v3v3(range[i].loc[0], tri[tri_i[1]], tri[tri_i[0]], fac0); interp_v3_v3v3(range[i].loc[1], tri[tri_i[1]], tri[tri_i[2]], fac1); } else { - range[i].min = range[i].max = (float)dot_b; + range[i].min = range[i].max = float(dot_b); copy_v3_v3(range[i].loc[0], tri[tri_i[1]]); copy_v3_v3(range[i].loc[1], tri[tri_i[1]]); } @@ -3028,12 +3020,12 @@ bool isect_ray_ray_epsilon_v3(const float ray_origin_a[3], sub_v3_v3v3(t, ray_origin_b, ray_origin_a); sub_v3_v3v3(c, n, t); - if (r_lambda_a != NULL) { + if (r_lambda_a != nullptr) { cross_v3_v3v3(cray, c, ray_direction_b); *r_lambda_a = dot_v3v3(cray, n) / nlen; } - if (r_lambda_b != NULL) { + if (r_lambda_b != nullptr) { cross_v3_v3v3(cray, c, ray_direction_a); *r_lambda_b = dot_v3v3(cray, n) / nlen; } @@ -3066,7 +3058,7 @@ bool isect_aabb_aabb_v3(const float min1[3], min2[1] < max1[1] && min2[2] < max1[2]); } -void isect_ray_aabb_v3_precalc(struct IsectRayAABB_Precalc *data, +void isect_ray_aabb_v3_precalc(IsectRayAABB_Precalc *data, const float ray_origin[3], const float ray_direction[3]) { @@ -3081,7 +3073,7 @@ void isect_ray_aabb_v3_precalc(struct IsectRayAABB_Precalc *data, data->sign[2] = data->ray_inv_dir[2] < 0.0f; } -bool isect_ray_aabb_v3(const struct IsectRayAABB_Precalc *data, +bool isect_ray_aabb_v3(const IsectRayAABB_Precalc *data, const float bb_min[3], const float bb_max[3], float *tmin_out) @@ -3142,17 +3134,17 @@ bool isect_ray_aabb_v3_simple(const float orig[3], { double t[6]; float hit_dist[2]; - const double invdirx = (dir[0] > 1e-35f || dir[0] < -1e-35f) ? 1.0 / (double)dir[0] : DBL_MAX; - const double invdiry = (dir[1] > 1e-35f || dir[1] < -1e-35f) ? 1.0 / (double)dir[1] : DBL_MAX; - const double invdirz = (dir[2] > 1e-35f || dir[2] < -1e-35f) ? 1.0 / (double)dir[2] : DBL_MAX; - t[0] = (double)(bb_min[0] - orig[0]) * invdirx; - t[1] = (double)(bb_max[0] - orig[0]) * invdirx; - t[2] = (double)(bb_min[1] - orig[1]) * invdiry; - t[3] = (double)(bb_max[1] - orig[1]) * invdiry; - t[4] = (double)(bb_min[2] - orig[2]) * invdirz; - t[5] = (double)(bb_max[2] - orig[2]) * invdirz; - hit_dist[0] = (float)fmax(fmax(fmin(t[0], t[1]), fmin(t[2], t[3])), fmin(t[4], t[5])); - hit_dist[1] = (float)fmin(fmin(fmax(t[0], t[1]), fmax(t[2], t[3])), fmax(t[4], t[5])); + const double invdirx = (dir[0] > 1e-35f || dir[0] < -1e-35f) ? 1.0 / double(dir[0]) : DBL_MAX; + const double invdiry = (dir[1] > 1e-35f || dir[1] < -1e-35f) ? 1.0 / double(dir[1]) : DBL_MAX; + const double invdirz = (dir[2] > 1e-35f || dir[2] < -1e-35f) ? 1.0 / double(dir[2]) : DBL_MAX; + t[0] = double(bb_min[0] - orig[0]) * invdirx; + t[1] = double(bb_max[0] - orig[0]) * invdirx; + t[2] = double(bb_min[1] - orig[1]) * invdiry; + t[3] = double(bb_max[1] - orig[1]) * invdiry; + t[4] = double(bb_min[2] - orig[2]) * invdirz; + t[5] = double(bb_max[2] - orig[2]) * invdirz; + hit_dist[0] = float(fmax(fmax(fmin(t[0], t[1]), fmin(t[2], t[3])), fmin(t[4], t[5]))); + hit_dist[1] = float(fmin(fmin(fmax(t[0], t[1]), fmax(t[2], t[3])), fmax(t[4], t[5]))); if ((hit_dist[1] < 0.0f) || (hit_dist[0] > hit_dist[1])) { return false; } @@ -3323,17 +3315,17 @@ int isect_point_tri_v2_int( { float v1[2], v2[2], v3[2], p[2]; - v1[0] = (float)x1; - v1[1] = (float)y1; + v1[0] = float(x1); + v1[1] = float(y1); - v2[0] = (float)x1; - v2[1] = (float)y2; + v2[0] = float(x1); + v2[1] = float(y2); - v3[0] = (float)x2; - v3[1] = (float)y1; + v3[0] = float(x2); + v3[1] = float(y1); - p[0] = (float)a; - p[1] = (float)b; + p[0] = float(a); + p[1] = float(b); return isect_point_tri_v2(p, v1, v2, v3); } @@ -3953,11 +3945,11 @@ int interp_sparse_array(float *array, const int list_size, const float skipval) float valid_last = skipval; int valid_ofs = 0; - float *array_up = MEM_callocN(sizeof(float) * (size_t)list_size, "interp_sparse_array up"); - float *array_down = MEM_callocN(sizeof(float) * (size_t)list_size, "interp_sparse_array up"); + blender::Array array_up(list_size); + blender::Array array_down(list_size); - int *ofs_tot_up = MEM_callocN(sizeof(int) * (size_t)list_size, "interp_sparse_array tup"); - int *ofs_tot_down = MEM_callocN(sizeof(int) * (size_t)list_size, "interp_sparse_array tdown"); + blender::Array ofs_tot_up(list_size); + blender::Array ofs_tot_down(list_size); for (i = 0; i < list_size; i++) { if (array[i] == skipval) { @@ -3988,9 +3980,9 @@ int interp_sparse_array(float *array, const int list_size, const float skipval) for (i = 0; i < list_size; i++) { if (array[i] == skipval) { if (array_up[i] != skipval && array_down[i] != skipval) { - array[i] = ((array_up[i] * (float)ofs_tot_down[i]) + - (array_down[i] * (float)ofs_tot_up[i])) / - (float)(ofs_tot_down[i] + ofs_tot_up[i]); + array[i] = ((array_up[i] * float(ofs_tot_down[i])) + + (array_down[i] * float(ofs_tot_up[i]))) / + float(ofs_tot_down[i] + ofs_tot_up[i]); } else if (array_up[i] != skipval) { array[i] = array_up[i]; @@ -4001,12 +3993,6 @@ int interp_sparse_array(float *array, const int list_size, const float skipval) } } - MEM_freeN(array_up); - MEM_freeN(array_down); - - MEM_freeN(ofs_tot_up); - MEM_freeN(ofs_tot_down); - return 1; } @@ -4041,8 +4027,7 @@ struct Double2_Len { /* Mean value weights - smooth interpolation weights for polygons with * more than 3 vertices */ -static float mean_value_half_tan_v3(const struct Float3_Len *d_curr, - const struct Float3_Len *d_next) +static float mean_value_half_tan_v3(const Float3_Len *d_curr, const Float3_Len *d_next) { float cross[3]; cross_v3_v3v3(cross, d_curr->dir, d_next->dir); @@ -4068,8 +4053,7 @@ static float mean_value_half_tan_v3(const struct Float3_Len *d_curr, * do not indicate a point "inside" the polygon. * To resolve this, doubles are used. */ -static double mean_value_half_tan_v2_db(const struct Double2_Len *d_curr, - const struct Double2_Len *d_next) +static double mean_value_half_tan_v2_db(const Double2_Len *d_curr, const Double2_Len *d_next) { /* Different from the 3d version but still correct. */ const double area = cross_v2v2_db(d_curr->dir, d_next->dir); @@ -4106,7 +4090,7 @@ void interp_weights_poly_v3(float *w, float v[][3], const int n, const float co[ float totweight = 0.0f; int i_curr, i_next; char ix_flag = 0; - struct Float3_Len d_curr, d_next; + Float3_Len d_curr, d_next; /* loop over 'i_next' */ i_curr = n - 1; @@ -4149,7 +4133,7 @@ void interp_weights_poly_v3(float *w, float v[][3], const int n, const float co[ } if (ix_flag) { - memset(w, 0, sizeof(*w) * (size_t)n); + memset(w, 0, sizeof(*w) * size_t(n)); if (ix_flag & IS_POINT_IX) { w[i_curr] = 1.0f; @@ -4191,7 +4175,7 @@ void interp_weights_poly_v2(float *w, float v[][2], const int n, const float co[ float totweight = 0.0f; int i_curr, i_next; char ix_flag = 0; - struct Double2_Len d_curr, d_next; + Double2_Len d_curr, d_next; /* loop over 'i_next' */ i_curr = n - 1; @@ -4222,7 +4206,7 @@ void interp_weights_poly_v2(float *w, float v[][2], const int n, const float co[ d_curr = d_next; DIR_V2_SET(&d_next, v_next, co); ht = mean_value_half_tan_v2_db(&d_curr, &d_next); - w[i_curr] = (d_curr.len == 0.0) ? 0.0f : (float)((ht_prev + ht) / d_curr.len); + w[i_curr] = (d_curr.len == 0.0) ? 0.0f : float((ht_prev + ht) / d_curr.len); totweight += w[i_curr]; /* step */ @@ -4234,7 +4218,7 @@ void interp_weights_poly_v2(float *w, float v[][2], const int n, const float co[ } if (ix_flag) { - memset(w, 0, sizeof(*w) * (size_t)n); + memset(w, 0, sizeof(*w) * size_t(n)); if (ix_flag & IS_POINT_IX) { w[i_curr] = 1.0f; @@ -4312,8 +4296,8 @@ void resolve_tri_uv_v2( if (IS_ZERO(det) == 0) { const double x[2] = {st[0] - st2[0], st[1] - st2[1]}; - r_uv[0] = (float)((d * x[0] - b * x[1]) / det); - r_uv[1] = (float)(((-c) * x[0] + a * x[1]) / det); + r_uv[0] = float((d * x[0] - b * x[1]) / det); + r_uv[1] = float(((-c) * x[0] + a * x[1]) / det); } else { zero_v2(r_uv); @@ -4342,8 +4326,8 @@ void resolve_tri_uv_v3( if (IS_ZERO(det) == 0) { float w; - w = (float)((d00 * d21 - d01 * d20) / det); - r_uv[1] = (float)((d11 * d20 - d01 * d21) / det); + w = float((d00 * d21 - d01 * d20) / det); + r_uv[1] = float((d11 * d20 - d01 * d21) / det); r_uv[0] = 1.0f - r_uv[1] - w; } else { @@ -4358,7 +4342,7 @@ void resolve_quad_uv_v2(float r_uv[2], const float st2[2], const float st3[2]) { - resolve_quad_uv_v2_deriv(r_uv, NULL, st, st0, st1, st2, st3); + resolve_quad_uv_v2_deriv(r_uv, nullptr, st, st0, st1, st2, st3); } void resolve_quad_uv_v2_deriv(float r_uv[2], @@ -4379,10 +4363,9 @@ void resolve_quad_uv_v2_deriv(float r_uv[2], const double a = (st0[0] - st[0]) * (st0[1] - st3[1]) - (st0[1] - st[1]) * (st0[0] - st3[0]); /* B = ( (p0 - p) X (p1 - p2) + (p1 - p) X (p0 - p3) ) / 2 */ - const double b = 0.5 * (double)(((st0[0] - st[0]) * (st1[1] - st2[1]) - - (st0[1] - st[1]) * (st1[0] - st2[0])) + - ((st1[0] - st[0]) * (st0[1] - st3[1]) - - (st1[1] - st[1]) * (st0[0] - st3[0]))); + const double b = + 0.5 * double(((st0[0] - st[0]) * (st1[1] - st2[1]) - (st0[1] - st[1]) * (st1[0] - st2[0])) + + ((st1[0] - st[0]) * (st0[1] - st3[1]) - (st1[1] - st[1]) * (st0[0] - st3[0]))); /* C = (p1-p) X (p1-p2) */ const double fC = (st1[0] - st[0]) * (st1[1] - st2[1]) - (st1[1] - st[1]) * (st1[0] - st2[0]); @@ -4394,7 +4377,7 @@ void resolve_quad_uv_v2_deriv(float r_uv[2], if (IS_ZERO(denom) != 0) { const double fDen = a - fC; if (IS_ZERO(fDen) == 0) { - r_uv[0] = (float)(a / fDen); + r_uv[0] = float(a / fDen); } } else { @@ -4402,7 +4385,7 @@ void resolve_quad_uv_v2_deriv(float r_uv[2], const double desc = sqrt(desc_sq < 0.0 ? 0.0 : desc_sq); const double s = signed_area > 0 ? (-1.0) : 1.0; - r_uv[0] = (float)(((a - b) + s * desc) / denom); + r_uv[0] = float(((a - b) + s * desc) / denom); } /* find UV such that @@ -4419,9 +4402,8 @@ void resolve_quad_uv_v2_deriv(float r_uv[2], } if (IS_ZERO(denom) == 0) { - r_uv[1] = (float)((double)((1.0f - r_uv[0]) * (st0[i] - st[i]) + - r_uv[0] * (st1[i] - st[i])) / - denom); + r_uv[1] = float(double((1.0f - r_uv[0]) * (st0[i] - st[i]) + r_uv[0] * (st1[i] - st[i])) / + denom); } } @@ -4443,10 +4425,10 @@ void resolve_quad_uv_v2_deriv(float r_uv[2], if (!IS_ZERO(denom)) { double inv_denom = 1.0 / denom; - r_deriv[0][0] = (float)((double)-t[1] * inv_denom); - r_deriv[0][1] = (float)((double)t[0] * inv_denom); - r_deriv[1][0] = (float)((double)s[1] * inv_denom); - r_deriv[1][1] = (float)((double)-s[0] * inv_denom); + r_deriv[0][0] = float(double(-t[1]) * inv_denom); + r_deriv[0][1] = float(double(t[0]) * inv_denom); + r_deriv[1][0] = float(double(s[1]) * inv_denom); + r_deriv[1][1] = float(double(-s[0]) * inv_denom); } } } @@ -4467,10 +4449,9 @@ float resolve_quad_u_v2(const float st[2], const double a = (st0[0] - st[0]) * (st0[1] - st3[1]) - (st0[1] - st[1]) * (st0[0] - st3[0]); /* B = ( (p0 - p) X (p1 - p2) + (p1 - p) X (p0 - p3) ) / 2 */ - const double b = 0.5 * (double)(((st0[0] - st[0]) * (st1[1] - st2[1]) - - (st0[1] - st[1]) * (st1[0] - st2[0])) + - ((st1[0] - st[0]) * (st0[1] - st3[1]) - - (st1[1] - st[1]) * (st0[0] - st3[0]))); + const double b = + 0.5 * double(((st0[0] - st[0]) * (st1[1] - st2[1]) - (st0[1] - st[1]) * (st1[0] - st2[0])) + + ((st1[0] - st[0]) * (st0[1] - st3[1]) - (st1[1] - st[1]) * (st0[0] - st3[0]))); /* C = (p1-p) X (p1-p2) */ const double fC = (st1[0] - st[0]) * (st1[1] - st2[1]) - (st1[1] - st[1]) * (st1[0] - st2[0]); @@ -4479,7 +4460,7 @@ float resolve_quad_u_v2(const float st[2], if (IS_ZERO(denom) != 0) { const double fDen = a - fC; if (IS_ZERO(fDen) == 0) { - return (float)(a / fDen); + return float(a / fDen); } return 0.0f; @@ -4489,7 +4470,7 @@ float resolve_quad_u_v2(const float st[2], const double desc = sqrt(desc_sq < 0.0 ? 0.0 : desc_sq); const double s = signed_area > 0 ? (-1.0) : 1.0; - return (float)(((a - b) + s * desc) / denom); + return float(((a - b) + s * desc) / denom); } #undef IS_ZERO @@ -4745,14 +4726,14 @@ void projmat_from_subregion(const float projmat[4][4], const int y_max, float r_projmat[4][4]) { - float rect_width = (float)(x_max - x_min); - float rect_height = (float)(y_max - y_min); + float rect_width = float(x_max - x_min); + float rect_height = float(y_max - y_min); - float x_sca = (float)win_size[0] / rect_width; - float y_sca = (float)win_size[1] / rect_height; + float x_sca = float(win_size[0]) / rect_width; + float y_sca = float(win_size[1]) / rect_height; - float x_fac = (float)((x_min + x_max) - win_size[0]) / rect_width; - float y_fac = (float)((y_min + y_max) - win_size[1]) / rect_height; + float x_fac = float((x_min + x_max) - win_size[0]) / rect_width; + float y_fac = float((y_min + y_max) - win_size[1]) / rect_height; copy_m4_m4(r_projmat, projmat); r_projmat[0][0] *= x_sca; @@ -4959,7 +4940,7 @@ bool map_to_tube(float *r_u, float *r_v, const float x, const float y, const flo } else { /* The "Regular" case, just compute the coordinate. */ - *r_u = snap_coordinate(atan2f(x, -y) / (float)(2.0f * M_PI)); + *r_u = snap_coordinate(atan2f(x, -y) / float(2.0f * M_PI)); } *r_v = (z + 1.0f) / 2.0f; return regular; @@ -4976,9 +4957,9 @@ bool map_to_sphere(float *r_u, float *r_v, const float x, const float y, const f } else { /* The "Regular" case, just compute the coordinate. */ - *r_u = snap_coordinate(atan2f(x, -y) / (float)(2.0f * M_PI)); + *r_u = snap_coordinate(atan2f(x, -y) / float(2.0f * M_PI)); } - *r_v = snap_coordinate(atan2f(len_xy, -z) / (float)M_PI); + *r_v = snap_coordinate(atan2f(len_xy, -z) / float(M_PI)); return regular; } @@ -5035,7 +5016,7 @@ void accumulate_vertex_normals_tri_v3(float n1[3], for (i = 0; i < nverts; i++) { const float *cur_edge = vdiffs[i]; - const float fac = saacos(-dot_v3v3(cur_edge, prev_edge)); + const float fac = blender::math::safe_acos_approx(-dot_v3v3(cur_edge, prev_edge)); /* accumulate */ madd_v3_v3fl(vn[i], f_no, fac); @@ -5055,7 +5036,7 @@ void accumulate_vertex_normals_v3(float n1[3], const float co4[3]) { float vdiffs[4][3]; - const int nverts = (n4 != NULL && co4 != NULL) ? 4 : 3; + const int nverts = (n4 != nullptr && co4 != nullptr) ? 4 : 3; /* compute normalized edge vectors */ sub_v3_v3v3(vdiffs[0], co2, co1); @@ -5082,7 +5063,7 @@ void accumulate_vertex_normals_v3(float n1[3], for (i = 0; i < nverts; i++) { const float *cur_edge = vdiffs[i]; - const float fac = saacos(-dot_v3v3(cur_edge, prev_edge)); + const float fac = blender::math::safe_acos_approx(-dot_v3v3(cur_edge, prev_edge)); /* accumulate */ madd_v3_v3fl(vn[i], f_no, fac); @@ -5114,7 +5095,7 @@ void accumulate_vertex_normals_poly_v3(float **vertnos, /* calculate angle between the two poly edges incident on * this vertex */ - const float fac = saacos(-dot_v3v3(cur_edge, prev_edge)); + const float fac = blender::math::safe_acos_approx(-dot_v3v3(cur_edge, prev_edge)); /* accumulate */ madd_v3_v3fl(vertnos[i], polyno, fac); @@ -5226,7 +5207,7 @@ void vcloud_estimate_transform_v3(const int list_size, } } if (!weight || !rweight) { - accu_weight = accu_rweight = (float)list_size; + accu_weight = accu_rweight = float(list_size); } mul_v3_fl(accu_com, 1.0f / accu_weight); @@ -5740,8 +5721,8 @@ float form_factor_quad(const float p[3], dot3 = dot_v3v3(n, g2); dot4 = dot_v3v3(n, g3); - result = (a1 * dot1 + a2 * dot2 + a3 * dot3 + a4 * dot4) * 0.5f / (float)M_PI; - result = MAX2(result, 0.0f); + result = (a1 * dot1 + a2 * dot2 + a3 * dot3 + a4 * dot4) * 0.5f / float(M_PI); + result = std::max(result, 0.0f); return result; } diff --git a/source/blender/blenlib/intern/path_util.cc b/source/blender/blenlib/intern/path_util.cc index bb6e0deee23..3fadfbb895a 100644 --- a/source/blender/blenlib/intern/path_util.cc +++ b/source/blender/blenlib/intern/path_util.cc @@ -7,6 +7,7 @@ * Various string, file, list operations. */ +#include /* For `min/max`. */ #include #include #include @@ -76,7 +77,7 @@ int BLI_path_sequence_decode(const char *path, const char *const lslash = BLI_path_slash_rfind(path); const char *const extension = BLI_path_extension_or_end(lslash ? lslash : path); const uint lslash_len = lslash != nullptr ? int(lslash - path) : 0; - const uint name_end = (uint)(extension - path); + const uint name_end = uint(extension - path); for (i = name_end - 1; i >= int(lslash_len); i--) { if (isdigit(path[i])) { @@ -108,7 +109,7 @@ int BLI_path_sequence_decode(const char *path, if (r_digits_len) { *r_digits_len = nume - nums + 1; } - return (int)ret; + return int(ret); } } @@ -135,7 +136,7 @@ void BLI_path_sequence_encode(char *path, { BLI_string_debug_size(path, path_maxncpy); - BLI_snprintf(path, path_maxncpy, "%s%.*d%s", head, numlen, MAX2(0, pic), tail); + BLI_snprintf(path, path_maxncpy, "%s%.*d%s", head, numlen, std::max(0, pic), tail); } /** @@ -963,7 +964,7 @@ bool BLI_path_frame(char *path, size_t path_maxncpy, int frame, int digits) if (path_frame_chars_find_range(path, &ch_sta, &ch_end)) { char frame_str[FILENAME_FRAME_CHARS_MAX + 1]; /* One for null. */ - const int ch_span = MIN2(ch_end - ch_sta, FILENAME_FRAME_CHARS_MAX); + const int ch_span = std::min(ch_end - ch_sta, FILENAME_FRAME_CHARS_MAX); SNPRINTF(frame_str, "%.*d", ch_span, frame); BLI_string_replace_range(path, path_maxncpy, ch_sta, ch_end, frame_str); return true; @@ -983,7 +984,7 @@ bool BLI_path_frame_range(char *path, size_t path_maxncpy, int sta, int end, int if (path_frame_chars_find_range(path, &ch_sta, &ch_end)) { char frame_str[(FILENAME_FRAME_CHARS_MAX * 2) + 1 + 1]; /* One for null, one for the '-' */ - const int ch_span = MIN2(ch_end - ch_sta, FILENAME_FRAME_CHARS_MAX); + const int ch_span = std::min(ch_end - ch_sta, FILENAME_FRAME_CHARS_MAX); SNPRINTF(frame_str, "%.*d-%.*d", ch_span, sta, ch_span, end); BLI_string_replace_range(path, path_maxncpy, ch_sta, ch_end, frame_str); return true; @@ -1166,7 +1167,7 @@ bool BLI_path_abs(char path[FILE_MAX], const char *basepath) if (lslash) { /* Length up to and including last `/`. */ - const int baselen = (int)(lslash - base) + 1; + const int baselen = int(lslash - base) + 1; /* Use path for temp storage here, we copy back over it right away. */ BLI_strncpy(path, tmp + 2, FILE_MAX); /* Strip `//` prefix. */ @@ -1581,7 +1582,7 @@ void BLI_path_split_dir_file(const char *filepath, const char *basename = BLI_path_basename(filepath); if (basename != filepath) { const size_t dir_size = (basename - filepath) + 1; - BLI_strncpy(dir, filepath, MIN2(dir_maxncpy, dir_size)); + BLI_strncpy(dir, filepath, std::min(dir_maxncpy, dir_size)); } else { dir[0] = '\0'; @@ -1595,7 +1596,7 @@ void BLI_path_split_dir_part(const char *filepath, char *dir, const size_t dir_m const char *basename = BLI_path_basename(filepath); if (basename != filepath) { const size_t dir_size = (basename - filepath) + 1; - BLI_strncpy(dir, filepath, MIN2(dir_maxncpy, dir_size)); + BLI_strncpy(dir, filepath, std::min(dir_maxncpy, dir_size)); } else { dir[0] = '\0'; diff --git a/source/blender/blenlib/intern/storage.cc b/source/blender/blenlib/intern/storage.cc index 2c9a3aabd7c..7b90e0d23ce 100644 --- a/source/blender/blenlib/intern/storage.cc +++ b/source/blender/blenlib/intern/storage.cc @@ -172,7 +172,7 @@ double BLI_dir_free_space(const char *dir) } # endif - return ((double(disk.f_bsize)) * (double(disk.f_bfree))); + return double(disk.f_bsize) * double(disk.f_bfree); #endif } @@ -563,7 +563,7 @@ LinkNode *BLI_file_read_as_lines(const char *filepath) } BLI_fseek(fp, 0, SEEK_END); - size = (size_t)BLI_ftell(fp); + size = size_t(BLI_ftell(fp)); BLI_fseek(fp, 0, SEEK_SET); if (UNLIKELY(size == size_t(-1))) { diff --git a/source/blender/blenlib/intern/string_ref.cc b/source/blender/blenlib/intern/string_ref.cc index 1e466753c68..5c26361d0e0 100644 --- a/source/blender/blenlib/intern/string_ref.cc +++ b/source/blender/blenlib/intern/string_ref.cc @@ -1,4 +1,4 @@ -/* SPDX-FileCopyrightText: 2023 Blender Foundation +/* SPDX-FileCopyrightText: 2023 Blender Authors * * SPDX-License-Identifier: GPL-2.0-or-later */ diff --git a/source/blender/blenlib/intern/string_utf8.cc b/source/blender/blenlib/intern/string_utf8.cc index 097103289ac..b06cc85d9b5 100644 --- a/source/blender/blenlib/intern/string_utf8.cc +++ b/source/blender/blenlib/intern/string_utf8.cc @@ -319,7 +319,7 @@ BLI_INLINE char *str_utf8_copy_max_bytes_impl(char *dst, const char *src, size_t /* Cast to `uint8_t` is a no-op, quiets array subscript of type `char` warning. * No need to check `src` points to a nil byte as this will return from the switch statement. */ size_t utf8_size; - while ((utf8_size = (size_t)utf8_char_compute_skip(*src)) < dst_maxncpy) { + while ((utf8_size = size_t(utf8_char_compute_skip(*src))) < dst_maxncpy) { dst_maxncpy -= utf8_size; /* Prefer more compact block. */ /* NOLINTBEGIN: bugprone-assignment-in-if-condition */ @@ -356,7 +356,7 @@ size_t BLI_strncpy_utf8_rlen(char *__restrict dst, const char *__restrict src, s char *r_dst = dst; dst = str_utf8_copy_max_bytes_impl(dst, src, dst_maxncpy); - return (size_t)(dst - r_dst); + return size_t(dst - r_dst); } /* -------------------------------------------------------------------- */ @@ -371,7 +371,7 @@ size_t BLI_strncpy_wchar_as_utf8(char *__restrict dst, size_t len = 0; while (*src && len < dst_maxncpy) { - len += BLI_str_utf8_from_unicode((uint)*src++, dst + len, dst_maxncpy - len); + len += BLI_str_utf8_from_unicode(uint(*src++), dst + len, dst_maxncpy - len); } dst[len] = '\0'; /* Return the correct length when part of the final byte did not fit into the string. */ @@ -386,7 +386,7 @@ size_t BLI_wstrlen_utf8(const wchar_t *src) size_t len = 0; while (*src) { - len += BLI_str_utf8_from_unicode_len((uint)*src++); + len += BLI_str_utf8_from_unicode_len(uint(*src++)); } return len; @@ -401,7 +401,7 @@ size_t BLI_strlen_utf8_ex(const char *strc, size_t *r_len_bytes) strc += BLI_str_utf8_size_safe(strc); } - *r_len_bytes = (size_t)(strc - strc_orig); + *r_len_bytes = size_t(strc - strc_orig); return len; } @@ -418,7 +418,7 @@ size_t BLI_strnlen_utf8_ex(const char *strc, const size_t strc_maxlen, size_t *r const char *strc_end = strc + strc_maxlen; while (true) { - size_t step = (size_t)BLI_str_utf8_size_safe(strc); + size_t step = size_t(BLI_str_utf8_size_safe(strc)); if (!*strc || strc + step > strc_end) { break; } @@ -426,7 +426,7 @@ size_t BLI_strnlen_utf8_ex(const char *strc, const size_t strc_maxlen, size_t *r len++; } - *r_len_bytes = (size_t)(strc - strc_orig); + *r_len_bytes = size_t(strc - strc_orig); return len; } @@ -762,7 +762,7 @@ uint BLI_str_utf8_as_unicode_step_or_error(const char *__restrict p, const size_t p_len, size_t *__restrict index) { - const uchar c = (uchar) * (p += *index); + const uchar c = uchar(*(p += *index)); BLI_assert(*index < p_len); BLI_assert(c != '\0'); @@ -788,7 +788,7 @@ uint BLI_str_utf8_as_unicode_step_safe(const char *__restrict p, { uint result = BLI_str_utf8_as_unicode_step_or_error(p, p_len, index); if (UNLIKELY(result == BLI_UTF8_ERR)) { - result = (uint)p[*index]; + result = uint(p[*index]); *index += 1; } BLI_assert(*index <= p_len); @@ -854,10 +854,10 @@ size_t BLI_str_utf8_from_unicode(uint c, char *dst, const size_t dst_maxncpy) } for (uint i = len - 1; i > 0; i--) { - dst[i] = (char)((c & 0x3f) | 0x80); + dst[i] = char((c & 0x3f) | 0x80); c >>= 6; } - dst[0] = (char)(c | first); + dst[0] = char(c | first); return len; } @@ -883,7 +883,7 @@ size_t BLI_str_utf8_as_utf32(char32_t *__restrict dst_w, else { *dst_w = '?'; const char *src_c_next = BLI_str_find_next_char_utf8(src_c + index, src_c_end); - index = (size_t)(src_c_next - src_c); + index = size_t(src_c_next - src_c); } dst_w++; len++; @@ -903,7 +903,7 @@ size_t BLI_str_utf32_as_utf8(char *__restrict dst, size_t len = 0; while (*src && len < dst_maxncpy) { - len += BLI_str_utf8_from_unicode((uint)*src++, dst + len, dst_maxncpy - len); + len += BLI_str_utf8_from_unicode(uint(*src++), dst + len, dst_maxncpy - len); } dst[len] = '\0'; /* Return the correct length when part of the final byte did not fit into the string. */ @@ -919,7 +919,7 @@ size_t BLI_str_utf32_as_utf8_len_ex(const char32_t *src, const size_t src_maxlen const char32_t *src_end = src + src_maxlen; while ((src < src_end) && *src) { - len += BLI_str_utf8_from_unicode_len((uint)*src++); + len += BLI_str_utf8_from_unicode_len(uint(*src++)); } return len; @@ -930,7 +930,7 @@ size_t BLI_str_utf32_as_utf8_len(const char32_t *src) size_t len = 0; while (*src) { - len += BLI_str_utf8_from_unicode_len((uint)*src++); + len += BLI_str_utf8_from_unicode_len(uint(*src++)); } return len; @@ -987,7 +987,7 @@ size_t BLI_str_partition_ex_utf8(const char *str, const char **r_suf, const bool from_right) { - const size_t str_len = end ? (size_t)(end - str) : strlen(str); + const size_t str_len = end ? size_t(end - str) : strlen(str); if (end == nullptr) { end = str + str_len; } @@ -1003,7 +1003,7 @@ size_t BLI_str_partition_ex_utf8(const char *str, str + index)) { size_t index_ofs = 0; - const uint c = BLI_str_utf8_as_unicode_step_or_error(sep, (size_t)(end - sep), &index_ofs); + const uint c = BLI_str_utf8_as_unicode_step_or_error(sep, size_t(end - sep), &index_ofs); if (UNLIKELY(c == BLI_UTF8_ERR)) { break; } @@ -1014,7 +1014,7 @@ size_t BLI_str_partition_ex_utf8(const char *str, /* `suf` is already correct in case from_right is true. */ *r_sep = sep; *r_suf = from_right ? suf : (char *)(str + index); - return (size_t)(sep - str); + return size_t(sep - str); } } @@ -1063,7 +1063,7 @@ int BLI_str_utf8_offset_from_index(const char *str, const size_t str_len, const UNUSED_VARS(code); index++; } - return (int)offset; + return int(offset); } int BLI_str_utf8_offset_to_column(const char *str, const size_t str_len, const int offset_target) @@ -1092,7 +1092,7 @@ int BLI_str_utf8_offset_from_column(const char *str, const size_t str_len, const } offset = offset_next; } - return (int)offset; + return int(offset); } int BLI_str_utf8_offset_to_column_with_tabs(const char *str, @@ -1129,7 +1129,7 @@ int BLI_str_utf8_offset_from_column_with_tabs(const char *str, } offset = offset_next; } - return (int)offset; + return int(offset); } /** \} */ diff --git a/source/blender/blenlib/intern/string_utils.cc b/source/blender/blenlib/intern/string_utils.cc index 9dee1a128d9..2841c39a369 100644 --- a/source/blender/blenlib/intern/string_utils.cc +++ b/source/blender/blenlib/intern/string_utils.cc @@ -114,11 +114,11 @@ bool BLI_string_replace_table_exact(char *string, size_t BLI_string_replace_range( char *string, size_t string_maxncpy, int src_beg, int src_end, const char *dst) { - int string_len = (int)strlen(string); + int string_len = int(strlen(string)); BLI_assert(src_beg <= src_end); BLI_assert(src_end <= string_len); const int src_len = src_end - src_beg; - int dst_len = (int)strlen(dst); + int dst_len = int(strlen(dst)); if (src_len < dst_len) { /* Grow, first handle special cases. */ @@ -140,13 +140,13 @@ size_t BLI_string_replace_range( } /* Grow. */ - memmove(string + (src_end + ofs), string + src_end, (size_t)(string_len - src_end) + 1); + memmove(string + (src_end + ofs), string + src_end, size_t(string_len - src_end) + 1); string_len += ofs; } else if (src_len > dst_len) { /* Shrink. */ const int ofs = src_len - dst_len; - memmove(string + (src_end - ofs), string + src_end, (size_t)(string_len - src_end) + 1); + memmove(string + (src_end - ofs), string + src_end, size_t(string_len - src_end) + 1); string_len -= ofs; } else { /* Simple case, no resizing. */ @@ -157,7 +157,7 @@ size_t BLI_string_replace_range( memcpy(string + src_beg, dst, size_t(dst_len)); } BLI_assert(string[string_len] == '\0'); - return (size_t)string_len; + return size_t(string_len); } /** \} */ @@ -178,7 +178,7 @@ size_t BLI_string_split_name_number(const char *name, while (a--) { if (name[a] == delim) { r_name_left[a] = '\0'; /* truncate left part here */ - *r_number = (int)atol(name + a + 1); + *r_number = int(atol(name + a + 1)); /* casting down to an int, can overflow for large numbers */ if (*r_number < 0) { *r_number = 0; @@ -562,7 +562,7 @@ size_t BLI_string_join_array(char *result, } } *c = '\0'; - return (size_t)(c - result); + return size_t(c - result); } size_t BLI_string_join_array_by_sep_char( @@ -589,7 +589,7 @@ size_t BLI_string_join_array_by_sep_char( } } *c = '\0'; - return (size_t)(c - result); + return size_t(c - result); } char *BLI_string_join_arrayN(const char *strings[], uint strings_num) diff --git a/source/blender/blenlib/intern/task_range.cc b/source/blender/blenlib/intern/task_range.cc index 1bc856292a0..0ff589d929c 100644 --- a/source/blender/blenlib/intern/task_range.cc +++ b/source/blender/blenlib/intern/task_range.cc @@ -105,7 +105,7 @@ void BLI_task_parallel_range(const int start, /* Multithreading. */ if (settings->use_threading && BLI_task_scheduler_num_threads() > 1) { RangeTask task(func, userdata, settings); - const size_t grainsize = MAX2(settings->min_iter_per_thread, 1); + const size_t grainsize = std::max(settings->min_iter_per_thread, 1); const tbb::blocked_range range(start, stop, grainsize); blender::lazy_threading::send_hint(); diff --git a/source/blender/blenlib/intern/vector.cc b/source/blender/blenlib/intern/vector.cc index e17dcb5c77a..47c2667a8d0 100644 --- a/source/blender/blenlib/intern/vector.cc +++ b/source/blender/blenlib/intern/vector.cc @@ -1,4 +1,4 @@ -/* SPDX-FileCopyrightText: 2023 Blender Foundation +/* SPDX-FileCopyrightText: 2023 Blender Authors * * SPDX-License-Identifier: GPL-2.0-or-later */ diff --git a/source/blender/blenlib/intern/virtual_array.cc b/source/blender/blenlib/intern/virtual_array.cc index 75bc5d71664..c935a7a1b67 100644 --- a/source/blender/blenlib/intern/virtual_array.cc +++ b/source/blender/blenlib/intern/virtual_array.cc @@ -1,4 +1,4 @@ -/* SPDX-FileCopyrightText: 2023 Blender Foundation +/* SPDX-FileCopyrightText: 2023 Blender Authors * * SPDX-License-Identifier: GPL-2.0-or-later */ diff --git a/source/blender/blenloader/intern/readfile.cc b/source/blender/blenloader/intern/readfile.cc index 33182d74dd2..9a86ae3bdb2 100644 --- a/source/blender/blenloader/intern/readfile.cc +++ b/source/blender/blenloader/intern/readfile.cc @@ -702,7 +702,7 @@ static BHeadN *get_bhead(FileData *fd) else { /* MIN2 is only to quiet '-Warray-bounds' compiler warning. */ BLI_assert(sizeof(bhead) == sizeof(bhead4)); - memcpy(&bhead, &bhead4, MIN2(sizeof(bhead), sizeof(bhead4))); + memcpy(&bhead, &bhead4, std::min(sizeof(bhead), sizeof(bhead4))); } } else { @@ -725,7 +725,7 @@ static BHeadN *get_bhead(FileData *fd) else { /* MIN2 is only to quiet `-Warray-bounds` compiler warning. */ BLI_assert(sizeof(bhead) == sizeof(bhead8)); - memcpy(&bhead, &bhead8, MIN2(sizeof(bhead), sizeof(bhead8))); + memcpy(&bhead, &bhead8, std::min(sizeof(bhead), sizeof(bhead8))); } } else { diff --git a/source/blender/blenloader/intern/versioning_250.cc b/source/blender/blenloader/intern/versioning_250.cc index 271091c4299..98a1bc574a2 100644 --- a/source/blender/blenloader/intern/versioning_250.cc +++ b/source/blender/blenloader/intern/versioning_250.cc @@ -961,7 +961,7 @@ void blo_do_versions_250(FileData *fd, Library * /*lib*/, Main *bmain) key->refkey) { data = static_cast(key->refkey->data); - tot = MIN2(me->totvert, key->refkey->totelem); + tot = std::min(me->totvert, key->refkey->totelem); MVert *verts = (MVert *)CustomData_get_layer_for_write( &me->vert_data, CD_MVERT, me->totvert); for (a = 0; a < tot; a++, data += 3) { @@ -976,7 +976,7 @@ void blo_do_versions_250(FileData *fd, Library * /*lib*/, Main *bmain) key->refkey) { data = static_cast(key->refkey->data); - tot = MIN2(lt->pntsu * lt->pntsv * lt->pntsw, key->refkey->totelem); + tot = std::min(lt->pntsu * lt->pntsv * lt->pntsw, key->refkey->totelem); for (a = 0; a < tot; a++, data += 3) { copy_v3_v3(lt->def[a].vec, data); diff --git a/source/blender/blenloader/intern/versioning_260.cc b/source/blender/blenloader/intern/versioning_260.cc index f980070f304..53bac42b943 100644 --- a/source/blender/blenloader/intern/versioning_260.cc +++ b/source/blender/blenloader/intern/versioning_260.cc @@ -2557,7 +2557,7 @@ void blo_do_versions_260(FileData *fd, Library * /*lib*/, Main *bmain) if (!MAIN_VERSION_FILE_ATLEAST(bmain, 268, 1)) { LISTBASE_FOREACH (Brush *, brush, &bmain->brushes) { - brush->spacing = MAX2(1, brush->spacing); + brush->spacing = std::max(1, brush->spacing); } } diff --git a/source/blender/blenloader/intern/versioning_300.cc b/source/blender/blenloader/intern/versioning_300.cc index 490f6cf8905..ba9743aa64f 100644 --- a/source/blender/blenloader/intern/versioning_300.cc +++ b/source/blender/blenloader/intern/versioning_300.cc @@ -122,12 +122,12 @@ static void version_idproperty_move_data_int(IDPropertyUIDataInt *ui_data, IDProperty *soft_min = IDP_GetPropertyFromGroup(prop_ui_data, "soft_min"); if (soft_min != nullptr) { ui_data->soft_min = IDP_coerce_to_int_or_zero(soft_min); - ui_data->soft_min = MIN2(ui_data->soft_min, ui_data->min); + ui_data->soft_min = std::min(ui_data->soft_min, ui_data->min); } IDProperty *soft_max = IDP_GetPropertyFromGroup(prop_ui_data, "soft_max"); if (soft_max != nullptr) { ui_data->soft_max = IDP_coerce_to_int_or_zero(soft_max); - ui_data->soft_max = MAX2(ui_data->soft_max, ui_data->max); + ui_data->soft_max = std::max(ui_data->soft_max, ui_data->max); } IDProperty *step = IDP_GetPropertyFromGroup(prop_ui_data, "step"); if (step != nullptr) { @@ -163,12 +163,12 @@ static void version_idproperty_move_data_float(IDPropertyUIDataFloat *ui_data, IDProperty *soft_min = IDP_GetPropertyFromGroup(prop_ui_data, "soft_min"); if (soft_min != nullptr) { ui_data->soft_min = IDP_coerce_to_double_or_zero(soft_min); - ui_data->soft_min = MAX2(ui_data->soft_min, ui_data->min); + ui_data->soft_min = std::max(ui_data->soft_min, ui_data->min); } IDProperty *soft_max = IDP_GetPropertyFromGroup(prop_ui_data, "soft_max"); if (soft_max != nullptr) { ui_data->soft_max = IDP_coerce_to_double_or_zero(soft_max); - ui_data->soft_max = MIN2(ui_data->soft_max, ui_data->max); + ui_data->soft_max = std::min(ui_data->soft_max, ui_data->max); } IDProperty *step = IDP_GetPropertyFromGroup(prop_ui_data, "step"); if (step != nullptr) { diff --git a/source/blender/blenloader/intern/versioning_400.cc b/source/blender/blenloader/intern/versioning_400.cc index d39a370b112..eed551712d5 100644 --- a/source/blender/blenloader/intern/versioning_400.cc +++ b/source/blender/blenloader/intern/versioning_400.cc @@ -47,11 +47,13 @@ #include "BKE_animsys.h" #include "BKE_armature.h" #include "BKE_attribute.h" +#include "BKE_collection.h" #include "BKE_curve.h" #include "BKE_effect.h" #include "BKE_grease_pencil.hh" #include "BKE_idprop.hh" #include "BKE_main.h" +#include "BKE_material.h" #include "BKE_mesh_legacy_convert.hh" #include "BKE_node.hh" #include "BKE_node_runtime.hh" @@ -298,6 +300,30 @@ static void version_principled_bsdf_update_animdata(ID *owner_id, bNodeTree *ntr } } +static void versioning_eevee_shadow_settings(Object *object) +{ + /** EEVEE no longer uses the Material::blend_shadow property. + * Instead, it uses Object::visibility_flag for disabling shadow casting + */ + + short *material_len = BKE_object_material_len_p(object); + if (!material_len) { + return; + } + + using namespace blender; + bool hide_shadows = *material_len > 0; + for (int i : IndexRange(*material_len)) { + Material *material = BKE_object_material_get(object, i + 1); + if (!material || material->blend_shadow != MA_BS_NONE) { + hide_shadows = false; + } + } + + /* Enable the hide_shadow flag only if there's not any shadow casting material. */ + SET_FLAG_FROM_TEST(object->visibility_flag, hide_shadows, OB_HIDE_SHADOW); +} + void do_versions_after_linking_400(FileData *fd, Main *bmain) { if (!MAIN_VERSION_FILE_ATLEAST(bmain, 400, 9)) { @@ -382,6 +408,16 @@ void do_versions_after_linking_400(FileData *fd, Main *bmain) BKE_mesh_legacy_face_map_to_generic(bmain); } + if (!MAIN_VERSION_FILE_ATLEAST(bmain, 401, 5)) { + Scene *scene = static_cast(bmain->scenes.first); + bool is_cycles = scene && STREQ(scene->r.engine, RE_engine_id_CYCLES); + if (!is_cycles) { + LISTBASE_FOREACH (Object *, object, &bmain->objects) { + versioning_eevee_shadow_settings(object); + } + } + } + /** * Versioning code until next subversion bump goes here. * @@ -1783,6 +1819,29 @@ void blo_do_versions_400(FileData *fd, Library * /*lib*/, Main *bmain) } } + if (!MAIN_VERSION_FILE_ATLEAST(bmain, 401, 5)) { + /* Unify Material::blend_shadow and Cycles.use_transparent_shadows into the + * Material::blend_flag. */ + Scene *scene = static_cast(bmain->scenes.first); + bool is_cycles = scene && STREQ(scene->r.engine, RE_engine_id_CYCLES); + if (is_cycles) { + LISTBASE_FOREACH (Material *, material, &bmain->materials) { + bool transparent_shadows = true; + if (IDProperty *cmat = version_cycles_properties_from_ID(&material->id)) { + transparent_shadows = version_cycles_property_boolean( + cmat, "use_transparent_shadow", true); + } + SET_FLAG_FROM_TEST(material->blend_flag, transparent_shadows, MA_BL_TRANSPARENT_SHADOW); + } + } + else { + LISTBASE_FOREACH (Material *, material, &bmain->materials) { + bool transparent_shadow = material->blend_shadow != MA_BS_SOLID; + SET_FLAG_FROM_TEST(material->blend_flag, transparent_shadow, MA_BL_TRANSPARENT_SHADOW); + } + } + } + /** * Versioning code until next subversion bump goes here. * diff --git a/source/blender/blenloader/intern/versioning_defaults.cc b/source/blender/blenloader/intern/versioning_defaults.cc index cafaac62034..6717966cc7e 100644 --- a/source/blender/blenloader/intern/versioning_defaults.cc +++ b/source/blender/blenloader/intern/versioning_defaults.cc @@ -547,8 +547,7 @@ void BLO_update_defaults_startup_blend(Main *bmain, const char *app_template) LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) { blo_update_defaults_scene(bmain, scene); - if (app_template && - (STREQ(app_template, "Video_Editing") || STREQ(app_template, "2D_Animation"))) { + if (app_template && STR_ELEM(app_template, "Video_Editing", "2D_Animation")) { /* Filmic is too slow, use standard until it is optimized. */ STRNCPY(scene->view_settings.view_transform, "Standard"); STRNCPY(scene->view_settings.look, "None"); diff --git a/source/blender/blenloader/intern/versioning_legacy.cc b/source/blender/blenloader/intern/versioning_legacy.cc index 41582ca6339..5edf95c03ea 100644 --- a/source/blender/blenloader/intern/versioning_legacy.cc +++ b/source/blender/blenloader/intern/versioning_legacy.cc @@ -2259,7 +2259,7 @@ void blo_do_versions_pre250(FileData *fd, Library *lib, Main *bmain) /* convert settings from old particle system */ /* general settings */ - part->totpart = MIN2(paf->totpart, 100000); + part->totpart = std::min(paf->totpart, 100000); part->sta = paf->sta; part->end = paf->end; part->lifetime = paf->lifetime; @@ -2503,8 +2503,8 @@ void blo_do_versions_pre250(FileData *fd, Library *lib, Main *bmain) * use it for the number of divisions per segment */ if (nu->pntsv > 1) { - nu->resolu = MAX2(1, int((float(nu->resolu) / float(nu->pntsu)) + 0.5f)); - nu->resolv = MAX2(1, int((float(nu->resolv) / float(nu->pntsv)) + 0.5f)); + nu->resolu = std::max(1, int((float(nu->resolu) / float(nu->pntsu)) + 0.5f)); + nu->resolv = std::max(1, int((float(nu->resolv) / float(nu->pntsv)) + 0.5f)); } } } diff --git a/source/blender/blenloader/intern/writefile.cc b/source/blender/blenloader/intern/writefile.cc index ae2274d2276..cb54da01cb7 100644 --- a/source/blender/blenloader/intern/writefile.cc +++ b/source/blender/blenloader/intern/writefile.cc @@ -78,7 +78,7 @@ #include "CLG_log.h" -/* allow writefile to use deprecated functionality (for forward compatibility code) */ +/* Allow writefile to use deprecated functionality (for forward compatibility code). */ #define DNA_DEPRECATED_ALLOW #include "DNA_collection_types.h" @@ -101,7 +101,7 @@ #include "BKE_blender_version.h" #include "BKE_bpath.h" -#include "BKE_global.h" /* for G */ +#include "BKE_global.h" /* For #Global `G`. */ #include "BKE_idprop.h" #include "BKE_idtype.h" #include "BKE_layer.h" @@ -471,7 +471,7 @@ static void writedata_do_write(WriteData *wd, const void *mem, size_t memlen) return; } - /* memory based save */ + /* Memory based save. */ if (wd->use_memfile) { BLO_memfile_chunk_add(&wd->mem, static_cast(mem), memlen); } @@ -532,8 +532,8 @@ static void mywrite(WriteData *wd, const void *adr, size_t len) writedata_do_write(wd, adr, len); } else { - /* if we have a single big chunk, write existing data in - * buffer and write out big chunk in smaller pieces */ + /* If we have a single big chunk, write existing data in + * buffer and write out big chunk in smaller pieces. */ if (len > wd->buffer.chunk_size) { if (wd->buffer.used_len != 0) { writedata_do_write(wd, wd->buffer.buf, wd->buffer.used_len); @@ -541,7 +541,7 @@ static void mywrite(WriteData *wd, const void *adr, size_t len) } do { - size_t writelen = MIN2(len, wd->buffer.chunk_size); + size_t writelen = std::min(len, wd->buffer.chunk_size); writedata_do_write(wd, adr, writelen); adr = (const char *)adr + writelen; len -= writelen; @@ -550,13 +550,13 @@ static void mywrite(WriteData *wd, const void *adr, size_t len) return; } - /* if data would overflow buffer, write out the buffer */ + /* If data would overflow buffer, write out the buffer. */ if (len + wd->buffer.used_len > wd->buffer.max_size - 1) { writedata_do_write(wd, wd->buffer.buf, wd->buffer.used_len); wd->buffer.used_len = 0; } - /* append data at end of buffer */ + /* Append data at end of buffer. */ memcpy(&wd->buffer.buf[wd->buffer.used_len], adr, len); wd->buffer.used_len += len; } @@ -669,7 +669,7 @@ static void writestruct_at_address_nr( return; } - /* init BHead */ + /* Initialize #BHead. */ bh.code = filecode; bh.old = adr; bh.nr = nr; @@ -693,7 +693,9 @@ static void writestruct_nr( writestruct_at_address_nr(wd, filecode, struct_nr, nr, adr, adr); } -/* do not use for structs */ +/** + * \warning Do not use for structs. + */ static void writedata(WriteData *wd, int filecode, size_t len, const void *adr) { BHead bh; @@ -707,10 +709,10 @@ static void writedata(WriteData *wd, int filecode, size_t len, const void *adr) return; } - /* align to 4 (writes uninitialized bytes in some cases) */ + /* Align to 4 (writes uninitialized bytes in some cases). */ len = (len + 3) & ~size_t(3); - /* init BHead */ + /* Initialize #BHead. */ bh.code = filecode; bh.old = adr; bh.nr = 1; @@ -721,7 +723,9 @@ static void writedata(WriteData *wd, int filecode, size_t len, const void *adr) mywrite(wd, adr, len); } -/* use this to force writing of lists in same order as reading (using link_list) */ +/** + * Use this to force writing of lists in same order as reading (using link_list). + */ static void writelist_nr(WriteData *wd, int filecode, const int struct_nr, const ListBase *lb) { const Link *link = static_cast(lb->first); @@ -782,20 +786,20 @@ static void current_screen_compat(Main *mainvar, wmWindowManager *wm; wmWindow *window = nullptr; - /* find a global current screen in the first open window, to have - * a reasonable default for reading in older versions */ + /* Find a global current screen in the first open window, to have + * a reasonable default for reading in older versions. */ wm = static_cast(mainvar->wm.first); if (wm) { if (use_active_win) { - /* write the active window into the file, needed for multi-window undo #43424 */ + /* Write the active window into the file, needed for multi-window undo #43424. */ for (window = static_cast(wm->windows.first); window; window = window->next) { if (window->active) { break; } } - /* fallback */ + /* Fallback. */ if (window == nullptr) { window = static_cast(wm->windows.first); } @@ -829,7 +833,7 @@ static void write_renderinfo(WriteData *wd, Main *mainvar) Scene *curscene = nullptr; ViewLayer *view_layer; - /* XXX in future, handle multiple windows with multiple screens? */ + /* XXX: in future, handle multiple windows with multiple screens? */ current_screen_compat(mainvar, false, &curscreen, &curscene, &view_layer); LISTBASE_FOREACH (Scene *, sce, &mainvar->scenes) { @@ -939,7 +943,7 @@ static void write_userdef(BlendWriter *writer, const UserDef *userdef) } } -/* Keep it last of write_foodata functions. */ +/** Keep it last of `write_*_data` functions. */ static void write_libraries(WriteData *wd, Main *main) { ListBase *lbarray[INDEX_ID_MAX]; @@ -950,7 +954,7 @@ static void write_libraries(WriteData *wd, Main *main) for (; main; main = main->next) { a = tot = set_listbasepointers(main, lbarray); - /* test: is lib being used */ + /* Test: is lib being used. */ if (main->curlib && main->curlib->packedfile) { found_one = true; } @@ -1024,9 +1028,11 @@ extern "C" ulong build_commit_timestamp; extern "C" char build_hash[]; #endif -/* context is usually defined by WM, two cases where no WM is available: - * - for forward compatibility, curscreen has to be saved - * - for undofile, curscene needs to be saved */ +/** + * Context is usually defined by WM, two cases where no WM is available: + * - for forward compatibility, `curscreen` has to be saved + * - for undo-file, `curscene` needs to be saved. + */ static void write_global(WriteData *wd, int fileflags, Main *mainvar) { const bool is_undo = wd->use_memfile; @@ -1036,7 +1042,7 @@ static void write_global(WriteData *wd, int fileflags, Main *mainvar) ViewLayer *view_layer; char subvstr[8]; - /* prevent mem checkers from complaining */ + /* Prevent memory checkers from complaining. */ memset(fg._pad, 0, sizeof(fg._pad)); memset(fg.filepath, 0, sizeof(fg.filepath)); memset(fg.build_hash, 0, sizeof(fg.build_hash)); @@ -1044,12 +1050,12 @@ static void write_global(WriteData *wd, int fileflags, Main *mainvar) current_screen_compat(mainvar, is_undo, &screen, &scene, &view_layer); - /* XXX still remap G */ + /* XXX: still remap `G`. */ fg.curscreen = screen; fg.curscene = scene; fg.cur_view_layer = view_layer; - /* prevent to save this, is not good convention, and feature with concerns... */ + /* Prevent to save this, is not good convention, and feature with concerns. */ fg.fileflags = (fileflags & ~G_FILE_FLAG_ALL_RUNTIME); fg.globalf = G.f; @@ -1192,7 +1198,12 @@ static int write_id_direct_linked_data_process_cb(LibraryIDLinkCallbackData *cb_ return IDWALK_RET_NOP; } -/* if MemFile * there's filesave to memory */ +/** + * When #MemFile arguments are non-null, this is a file-safe to memory. + * + * \param compare: Previous memory file (can be nullptr). + * \param current: The current memory file (can be nullptr). + */ static bool write_file_handle(Main *mainvar, WriteWrap *ww, MemFile *compare, @@ -1364,7 +1375,7 @@ static bool write_file_handle(Main *mainvar, * so writing each time uses the same address and doesn't cause unnecessary undo overhead. */ writedata(wd, BLO_CODE_DNA1, size_t(wd->sdna->data_len), wd->sdna->data); - /* end of file */ + /* End of file. */ memset(&bhead, 0, sizeof(BHead)); bhead.code = BLO_CODE_ENDB; mywrite(wd, &bhead, sizeof(BHead)); @@ -1475,14 +1486,14 @@ static bool BLO_write_file_impl(Main *mainvar, const BlendThumbnail *thumb = params->thumb; const bool relbase_valid = (mainvar->filepath[0] != '\0'); - /* path backup/restore */ + /* Path backup/restore. */ void *path_list_backup = nullptr; const eBPathForeachFlag path_list_flag = (BKE_BPATH_FOREACH_PATH_SKIP_LINKED | BKE_BPATH_FOREACH_PATH_SKIP_MULTIFILE); write_file_main_validate_pre(mainvar, reports); - /* open temporary file, so we preserve the original in case we crash */ + /* Open temporary file, so we preserve the original in case we crash. */ SNPRINTF(tempname, "%s@", filepath); if (ww.open(tempname) == false) { @@ -1574,7 +1585,7 @@ static bool BLO_write_file_impl(Main *mainvar, } } - /* actual file writing */ + /* Actual file writing. */ const bool err = write_file_handle( mainvar, &ww, nullptr, nullptr, write_flags, use_userdef, thumb); @@ -1592,8 +1603,8 @@ static bool BLO_write_file_impl(Main *mainvar, return false; } - /* file save to temporary file was successful */ - /* now do reverse file history (move .blend1 -> .blend2, .blend -> .blend1) */ + /* File save to temporary file was successful, now do reverse file history + * (move `.blend1` -> `.blend2`, `.blend` -> `.blend1` .. etc). */ if (use_save_versions) { if (!do_history(filepath, reports)) { BKE_report(reports, RPT_ERROR, "Version backup failed (file saved with @)"); @@ -1611,6 +1622,8 @@ static bool BLO_write_file_impl(Main *mainvar, return true; } +/** \} */ + /* -------------------------------------------------------------------- */ /** \name File Writing (Public) * \{ */ diff --git a/source/blender/bmesh/intern/bmesh_mesh_normals.cc b/source/blender/bmesh/intern/bmesh_mesh_normals.cc index bd7d8fc90e5..8824c6a820b 100644 --- a/source/blender/bmesh/intern/bmesh_mesh_normals.cc +++ b/source/blender/bmesh/intern/bmesh_mesh_normals.cc @@ -16,6 +16,7 @@ #include "BLI_bitmap.h" #include "BLI_linklist_stack.h" +#include "BLI_math_base.hh" #include "BLI_math_vector.h" #include "BLI_task.h" #include "BLI_utildefines.h" @@ -72,7 +73,7 @@ BLI_INLINE void bm_vert_calc_normals_accum_loop(const BMLoop *l_iter, if ((l_iter->prev->e->v1 == l_iter->prev->v) ^ (l_iter->e->v1 == l_iter->v)) { dotprod = -dotprod; } - const float fac = saacos(-dotprod); + const float fac = blender::math::safe_acos_approx(-dotprod); /* Shouldn't happen as normalizing edge-vectors cause degenerate values to be zeroed out. */ BLI_assert(!isnan(fac)); madd_v3_v3fl(v_no, f_no, fac); @@ -642,7 +643,7 @@ static int bm_mesh_loops_calc_normals_for_loop(BMesh *bm, /* Code similar to accumulate_vertex_normals_poly_v3. */ /* Calculate angle between the two face edges incident on this vertex. */ const BMFace *f = lfan_pivot->f; - const float fac = saacos(dot_v3v3(vec_next, vec_curr)); + const float fac = blender::math::safe_acos_approx(dot_v3v3(vec_next, vec_curr)); const float *no = fnos ? fnos[BM_elem_index_get(f)] : f->no; /* Accumulate */ madd_v3_v3fl(lnor, no, fac); diff --git a/source/blender/bmesh/intern/bmesh_polygon.cc b/source/blender/bmesh/intern/bmesh_polygon.cc index 1b5a95907c5..ca9ea78ecf7 100644 --- a/source/blender/bmesh/intern/bmesh_polygon.cc +++ b/source/blender/bmesh/intern/bmesh_polygon.cc @@ -18,6 +18,7 @@ #include "BLI_alloca.h" #include "BLI_heap.h" #include "BLI_linklist.h" +#include "BLI_math_base.hh" #include "BLI_math_geom.h" #include "BLI_math_matrix.h" #include "BLI_math_vector.h" @@ -615,7 +616,7 @@ static void bm_loop_normal_accum(const BMLoop *l, float no[3]) normalize_v3(vec1); normalize_v3(vec2); - fac = saacos(-dot_v3v3(vec1, vec2)); + fac = blender::math::safe_acos_approx(-dot_v3v3(vec1, vec2)); madd_v3_v3fl(no, l->f->no, fac); } @@ -944,7 +945,7 @@ bool BM_face_point_inside_test(const BMFace *f, const float co[3]) mul_v2_m3v3(projverts[i], axis_mat, l_iter->v->co); } - return isect_point_poly_v2(co_2d, projverts, f->len, false); + return isect_point_poly_v2(co_2d, projverts, f->len); } void BM_face_triangulate(BMesh *bm, diff --git a/source/blender/bmesh/intern/bmesh_query_uv.cc b/source/blender/bmesh/intern/bmesh_query_uv.cc index 9e872cbba32..0722fdf5228 100644 --- a/source/blender/bmesh/intern/bmesh_query_uv.cc +++ b/source/blender/bmesh/intern/bmesh_query_uv.cc @@ -208,6 +208,5 @@ bool BM_face_uv_point_inside_test(const BMFace *f, const float co[2], const int projverts[i] = BM_ELEM_CD_GET_FLOAT2_P(l_iter, cd_loop_uv_offset); } - return isect_point_poly_v2( - co, reinterpret_cast(projverts.data()), f->len, false); + return isect_point_poly_v2(co, reinterpret_cast(projverts.data()), f->len); } diff --git a/source/blender/bmesh/tools/bmesh_decimate_collapse.cc b/source/blender/bmesh/tools/bmesh_decimate_collapse.cc index 107a2e221fd..a2538b8f6a4 100644 --- a/source/blender/bmesh/tools/bmesh_decimate_collapse.cc +++ b/source/blender/bmesh/tools/bmesh_decimate_collapse.cc @@ -608,10 +608,10 @@ static void bm_decim_triangulate_end(BMesh *bm, const int edges_tri_tot) /* we need to collect before merging for ngons since the loops indices will be lost */ BMEdge **edges_tri = static_cast( - MEM_mallocN(MIN2(edges_tri_tot, bm->totedge) * sizeof(*edges_tri), __func__)); + MEM_mallocN(std::min(edges_tri_tot, bm->totedge) * sizeof(*edges_tri), __func__)); STACK_DECLARE(edges_tri); - STACK_INIT(edges_tri, MIN2(edges_tri_tot, bm->totedge)); + STACK_INIT(edges_tri, std::min(edges_tri_tot, bm->totedge)); /* boundary edges */ BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { diff --git a/source/blender/bmesh/tools/bmesh_region_match.cc b/source/blender/bmesh/tools/bmesh_region_match.cc index 9256d658bc1..dc71fc2f47e 100644 --- a/source/blender/bmesh/tools/bmesh_region_match.cc +++ b/source/blender/bmesh/tools/bmesh_region_match.cc @@ -382,8 +382,8 @@ static void bm_uuidwalk_rehash(UUIDWalk *uuidwalk) UUID_Int *uuid_store; uint i; - uint rehash_store_len_new = MAX2(BLI_ghash_len(uuidwalk->verts_uuid), - BLI_ghash_len(uuidwalk->faces_uuid)); + uint rehash_store_len_new = std::max(BLI_ghash_len(uuidwalk->verts_uuid), + BLI_ghash_len(uuidwalk->faces_uuid)); bm_uuidwalk_rehash_reserve(uuidwalk, rehash_store_len_new); uuid_store = uuidwalk->cache.rehash_store; @@ -740,8 +740,8 @@ static BMFace **bm_mesh_region_match_pair( goto finally; } - bm_uuidwalk_rehash_reserve(w_src, MAX2(faces_src_region_len, verts_src_region_len)); - bm_uuidwalk_rehash_reserve(w_dst, MAX2(faces_src_region_len, verts_src_region_len)); + bm_uuidwalk_rehash_reserve(w_src, std::max(faces_src_region_len, verts_src_region_len)); + bm_uuidwalk_rehash_reserve(w_dst, std::max(faces_src_region_len, verts_src_region_len)); while (true) { bool ok = false; diff --git a/source/blender/compositor/intern/COM_ExecutionGroup.cc b/source/blender/compositor/intern/COM_ExecutionGroup.cc index 955d6f25abb..484d78949bb 100644 --- a/source/blender/compositor/intern/COM_ExecutionGroup.cc +++ b/source/blender/compositor/intern/COM_ExecutionGroup.cc @@ -146,7 +146,7 @@ void ExecutionGroup::init_read_buffer_operations() if (operation->get_flags().is_read_buffer_operation) { ReadBufferOperation *read_operation = static_cast(operation); read_operations_.append(read_operation); - max_offset = MAX2(max_offset, read_operation->get_offset()); + max_offset = std::max(max_offset, read_operation->get_offset()); } } max_offset++; @@ -442,10 +442,10 @@ inline void ExecutionGroup::determine_chunk_rect(rcti *r_rect, const uint width = MIN2(uint(viewer_border_.xmax), width_); const uint height = MIN2(uint(viewer_border_.ymax), height_); BLI_rcti_init(r_rect, - MIN2(minx, width_), - MIN2(minx + chunk_size_, width), - MIN2(miny, height_), - MIN2(miny + chunk_size_, height)); + std::min(minx, width_), + std::min(minx + chunk_size_, width), + std::min(miny, height_), + std::min(miny + chunk_size_, height)); } } diff --git a/source/blender/compositor/intern/COM_ExecutionSystem.cc b/source/blender/compositor/intern/COM_ExecutionSystem.cc index e6fcb6f1a07..d2bd9b52a8a 100644 --- a/source/blender/compositor/intern/COM_ExecutionSystem.cc +++ b/source/blender/compositor/intern/COM_ExecutionSystem.cc @@ -109,7 +109,7 @@ void ExecutionSystem::execute_work(const rcti &work_rect, /* Split work vertically to maximize continuous memory. */ const int work_height = BLI_rcti_size_y(&work_rect); - const int num_sub_works = MIN2(num_work_threads_, work_height); + const int num_sub_works = std::min(num_work_threads_, work_height); const int split_height = num_sub_works == 0 ? 0 : work_height / num_sub_works; int remaining_height = work_height - split_height * num_sub_works; diff --git a/source/blender/compositor/intern/COM_MemoryBuffer.cc b/source/blender/compositor/intern/COM_MemoryBuffer.cc index e3daf21bc57..54cd893ebc9 100644 --- a/source/blender/compositor/intern/COM_MemoryBuffer.cc +++ b/source/blender/compositor/intern/COM_MemoryBuffer.cc @@ -312,9 +312,21 @@ static void colorspace_to_scene_linear(MemoryBuffer *buf, const rcti &area, Colo } } -void MemoryBuffer::copy_from(const ImBuf *src, const rcti &area, const bool ensure_linear_space) +static void premultiply_alpha(MemoryBuffer *buf, const rcti &area) { - copy_from(src, area, 0, this->get_num_channels(), 0, ensure_linear_space); + for (int y = area.ymin; y < area.ymax; y++) { + for (int x = area.xmin; x < area.xmax; x++) { + straight_to_premul_v4(buf->get_elem(x, y)); + } + } +} + +void MemoryBuffer::copy_from(const ImBuf *src, + const rcti &area, + const bool ensure_premultiplied, + const bool ensure_linear_space) +{ + copy_from(src, area, 0, this->get_num_channels(), 0, ensure_premultiplied, ensure_linear_space); } void MemoryBuffer::copy_from(const ImBuf *src, @@ -322,6 +334,7 @@ void MemoryBuffer::copy_from(const ImBuf *src, const int channel_offset, const int elem_size, const int to_channel_offset, + const bool ensure_premultiplied, const bool ensure_linear_space) { copy_from(src, @@ -331,6 +344,7 @@ void MemoryBuffer::copy_from(const ImBuf *src, area.xmin, area.ymin, to_channel_offset, + ensure_premultiplied, ensure_linear_space); } @@ -341,6 +355,7 @@ void MemoryBuffer::copy_from(const ImBuf *src, const int to_x, const int to_y, const int to_channel_offset, + const bool ensure_premultiplied, const bool ensure_linear_space) { if (src->float_buffer.data) { @@ -363,6 +378,9 @@ void MemoryBuffer::copy_from(const ImBuf *src, if (ensure_linear_space) { colorspace_to_scene_linear(this, area, src->byte_buffer.colorspace); } + if (ensure_premultiplied) { + premultiply_alpha(this, area); + } } else { /* Empty ImBuf source. Fill destination with empty values. */ @@ -391,8 +409,8 @@ void MemoryBuffer::fill_from(const MemoryBuffer &src) rcti overlap; overlap.xmin = MAX2(rect_.xmin, src.rect_.xmin); overlap.xmax = MIN2(rect_.xmax, src.rect_.xmax); - overlap.ymin = MAX2(rect_.ymin, src.rect_.ymin); - overlap.ymax = MIN2(rect_.ymax, src.rect_.ymax); + overlap.ymin = std::max(rect_.ymin, src.rect_.ymin); + overlap.ymax = std::min(rect_.ymax, src.rect_.ymax); copy_from(&src, overlap); } diff --git a/source/blender/compositor/intern/COM_MemoryBuffer.h b/source/blender/compositor/intern/COM_MemoryBuffer.h index 4738428a22c..d64c6609dc4 100644 --- a/source/blender/compositor/intern/COM_MemoryBuffer.h +++ b/source/blender/compositor/intern/COM_MemoryBuffer.h @@ -603,12 +603,16 @@ class MemoryBuffer { int to_x, int to_y, int to_channel_offset); - void copy_from(const struct ImBuf *src, const rcti &area, bool ensure_linear_space = false); + void copy_from(const struct ImBuf *src, + const rcti &area, + bool ensure_premultiplied = false, + bool ensure_linear_space = false); void copy_from(const struct ImBuf *src, const rcti &area, int channel_offset, int elem_size, int to_channel_offset, + bool ensure_premultiplied = false, bool ensure_linear_space = false); void copy_from(const struct ImBuf *src, const rcti &src_area, @@ -617,6 +621,7 @@ class MemoryBuffer { int to_x, int to_y, int to_channel_offset, + bool ensure_premultiplied = false, bool ensure_linear_space = false); void fill(const rcti &area, const float *value); diff --git a/source/blender/compositor/intern/COM_NodeOperation.cc b/source/blender/compositor/intern/COM_NodeOperation.cc index 0c0543d473a..2f10cd91236 100644 --- a/source/blender/compositor/intern/COM_NodeOperation.cc +++ b/source/blender/compositor/intern/COM_NodeOperation.cc @@ -237,10 +237,10 @@ bool NodeOperation::determine_depending_area_of_interest(rcti *input, first = false; } else { - output->xmin = MIN2(output->xmin, temp_output.xmin); - output->ymin = MIN2(output->ymin, temp_output.ymin); - output->xmax = MAX2(output->xmax, temp_output.xmax); - output->ymax = MAX2(output->ymax, temp_output.ymax); + output->xmin = std::min(output->xmin, temp_output.xmin); + output->ymin = std::min(output->ymin, temp_output.ymin); + output->xmax = std::max(output->xmax, temp_output.xmax); + output->ymax = std::max(output->ymax, temp_output.ymax); } } } diff --git a/source/blender/compositor/nodes/COM_SceneTimeNode.cc b/source/blender/compositor/nodes/COM_SceneTimeNode.cc index f4cd849f874..c1543874d35 100644 --- a/source/blender/compositor/nodes/COM_SceneTimeNode.cc +++ b/source/blender/compositor/nodes/COM_SceneTimeNode.cc @@ -21,7 +21,7 @@ void SceneTimeNode::convert_to_operations(NodeConverter &converter, const int frameNumber = context.get_framenumber(); const Scene *scene = context.get_scene(); - const double frameRate = (double(scene->r.frs_sec) / double(scene->r.frs_sec_base)); + const double frameRate = double(scene->r.frs_sec) / double(scene->r.frs_sec_base); SecondOperation->set_value(float(frameNumber / frameRate)); converter.add_operation(SecondOperation); diff --git a/source/blender/compositor/nodes/COM_SwitchViewNode.cc b/source/blender/compositor/nodes/COM_SwitchViewNode.cc index fe5be5ae15a..f953e76dce9 100644 --- a/source/blender/compositor/nodes/COM_SwitchViewNode.cc +++ b/source/blender/compositor/nodes/COM_SwitchViewNode.cc @@ -20,7 +20,7 @@ void SwitchViewNode::convert_to_operations(NodeConverter &converter, /* get the internal index of the socket with a matching name */ int nr = BLI_findstringindex(&bnode->inputs, view_name, offsetof(bNodeSocket, name)); - nr = MAX2(nr, 0); + nr = std::max(nr, 0); result = converter.add_input_proxy(get_input_socket(nr), false); converter.map_output_socket(get_output_socket(0), result); diff --git a/source/blender/compositor/operations/COM_BokehBlurOperation.cc b/source/blender/compositor/operations/COM_BokehBlurOperation.cc index 1df610689d9..81a960c7130 100644 --- a/source/blender/compositor/operations/COM_BokehBlurOperation.cc +++ b/source/blender/compositor/operations/COM_BokehBlurOperation.cc @@ -44,7 +44,7 @@ void BokehBlurOperation::init_data() const int width = bokeh->get_width(); const int height = bokeh->get_height(); - const float dimension = MIN2(width, height); + const float dimension = std::min(width, height); bokeh_mid_x_ = width / 2.0f; bokeh_mid_y_ = height / 2.0f; @@ -103,8 +103,8 @@ void BokehBlurOperation::execute_pixel(float output[4], int x, int y, void *data int maxy = y + pixel_size; int minx = x - pixel_size; int maxx = x + pixel_size; - miny = MAX2(miny, input_rect.ymin); - minx = MAX2(minx, input_rect.xmin); + miny = std::max(miny, input_rect.ymin); + minx = std::max(minx, input_rect.xmin); maxy = MIN2(maxy, input_rect.ymax); maxx = MIN2(maxx, input_rect.xmax); @@ -338,7 +338,7 @@ void BokehBlurOperation::update_memory_buffer_partial(MemoryBuffer *output, multiplier_accum[2] = 1.0f; multiplier_accum[3] = 1.0f; } - const int miny = MAX2(y - pixel_size, image_rect.ymin); + const int miny = std::max(y - pixel_size, image_rect.ymin); const int maxy = MIN2(y + pixel_size, image_rect.ymax); const int minx = MAX2(x - pixel_size, image_rect.xmin); const int maxx = MIN2(x + pixel_size, image_rect.xmax); diff --git a/source/blender/compositor/operations/COM_BoxMaskOperation.cc b/source/blender/compositor/operations/COM_BoxMaskOperation.cc index 5c7252c1239..d6f873bd7dc 100644 --- a/source/blender/compositor/operations/COM_BoxMaskOperation.cc +++ b/source/blender/compositor/operations/COM_BoxMaskOperation.cc @@ -53,7 +53,7 @@ void BoxMaskOperation::execute_pixel_sampled(float output[4], switch (mask_type_) { case CMP_NODE_MASKTYPE_ADD: if (inside) { - output[0] = MAX2(input_mask[0], input_value[0]); + output[0] = std::max(input_mask[0], input_value[0]); } else { output[0] = input_mask[0]; @@ -100,7 +100,7 @@ void BoxMaskOperation::update_memory_buffer_partial(MemoryBuffer *output, switch (mask_type_) { case CMP_NODE_MASKTYPE_ADD: mask_func = [](const bool is_inside, const float *mask, const float *value) { - return is_inside ? MAX2(mask[0], value[0]) : mask[0]; + return is_inside ? std::max(mask[0], value[0]) : mask[0]; }; break; case CMP_NODE_MASKTYPE_SUBTRACT: diff --git a/source/blender/compositor/operations/COM_ChannelMatteOperation.cc b/source/blender/compositor/operations/COM_ChannelMatteOperation.cc index e789cb58d9f..e6d100ffb56 100644 --- a/source/blender/compositor/operations/COM_ChannelMatteOperation.cc +++ b/source/blender/compositor/operations/COM_ChannelMatteOperation.cc @@ -83,7 +83,7 @@ void ChannelMatteOperation::execute_pixel_sampled(float output[4], input_image_program_->read_sampled(in_color, x, y, sampler); /* matte operation */ - alpha = in_color[ids_[0]] - MAX2(in_color[ids_[1]], in_color[ids_[2]]); + alpha = in_color[ids_[0]] - std::max(in_color[ids_[1]], in_color[ids_[2]]); /* flip because 0.0 is transparent, not 1.0 */ alpha = 1.0f - alpha; @@ -104,7 +104,7 @@ void ChannelMatteOperation::execute_pixel_sampled(float output[4], */ /* Don't make something that was more transparent less transparent. */ - output[0] = MIN2(alpha, in_color[3]); + output[0] = std::min(alpha, in_color[3]); } void ChannelMatteOperation::update_memory_buffer_partial(MemoryBuffer *output, diff --git a/source/blender/compositor/operations/COM_ColorBalanceLGGOperation.cc b/source/blender/compositor/operations/COM_ColorBalanceLGGOperation.cc index 1dbfb0e966e..29ffbff7195 100644 --- a/source/blender/compositor/operations/COM_ColorBalanceLGGOperation.cc +++ b/source/blender/compositor/operations/COM_ColorBalanceLGGOperation.cc @@ -54,7 +54,7 @@ void ColorBalanceLGGOperation::execute_pixel_sampled(float output[4], input_color_operation_->read_sampled(input_color, x, y, sampler); float fac = value[0]; - fac = MIN2(1.0f, fac); + fac = std::min(1.0f, fac); const float mfac = 1.0f - fac; output[0] = mfac * input_color[0] + diff --git a/source/blender/compositor/operations/COM_ColorSpillOperation.cc b/source/blender/compositor/operations/COM_ColorSpillOperation.cc index 50b5e00fbc9..d6b7fcba26e 100644 --- a/source/blender/compositor/operations/COM_ColorSpillOperation.cc +++ b/source/blender/compositor/operations/COM_ColorSpillOperation.cc @@ -78,7 +78,7 @@ void ColorSpillOperation::execute_pixel_sampled(float output[4], float input[4]; input_fac_reader_->read_sampled(fac, x, y, sampler); input_image_reader_->read_sampled(input, x, y, sampler); - float rfac = MIN2(1.0f, fac[0]); + float rfac = std::min(1.0f, fac[0]); float map; switch (spill_method_) { @@ -108,7 +108,7 @@ void ColorSpillOperation::update_memory_buffer_partial(MemoryBuffer *output, { for (BuffersIterator it = output->iterate_with(inputs, area); !it.is_end(); ++it) { const float *color = it.in(0); - const float factor = MIN2(1.0f, *it.in(1)); + const float factor = std::min(1.0f, *it.in(1)); float map; switch (spill_method_) { diff --git a/source/blender/compositor/operations/COM_ConvertDepthToRadiusOperation.cc b/source/blender/compositor/operations/COM_ConvertDepthToRadiusOperation.cc index fd95522db68..d6a8c4f50c6 100644 --- a/source/blender/compositor/operations/COM_ConvertDepthToRadiusOperation.cc +++ b/source/blender/compositor/operations/COM_ConvertDepthToRadiusOperation.cc @@ -55,7 +55,7 @@ void ConvertDepthToRadiusOperation::init_execution() dof_sp_ = minsz / ((cam_sensor / 2.0f) / cam_lens_); if (blur_post_operation_) { - blur_post_operation_->set_sigma(MIN2(aperture_ * 128.0f, max_radius_)); + blur_post_operation_->set_sigma(std::min(aperture_ * 128.0f, max_radius_)); } } diff --git a/source/blender/compositor/operations/COM_CropOperation.cc b/source/blender/compositor/operations/COM_CropOperation.cc index 18befcbb2fd..a3c7d784608 100644 --- a/source/blender/compositor/operations/COM_CropOperation.cc +++ b/source/blender/compositor/operations/COM_CropOperation.cc @@ -42,9 +42,9 @@ void CropBaseOperation::update_area() } xmax_ = MAX2(local_settings.x1, local_settings.x2); - xmin_ = MIN2(local_settings.x1, local_settings.x2); - ymax_ = MAX2(local_settings.y1, local_settings.y2); - ymin_ = MIN2(local_settings.y1, local_settings.y2); + xmin_ = std::min(local_settings.x1, local_settings.x2); + ymax_ = std::max(local_settings.y1, local_settings.y2); + ymin_ = std::min(local_settings.y1, local_settings.y2); } else { xmax_ = 0; diff --git a/source/blender/compositor/operations/COM_DespeckleOperation.cc b/source/blender/compositor/operations/COM_DespeckleOperation.cc index 13b9f8a6a6b..efe43306006 100644 --- a/source/blender/compositor/operations/COM_DespeckleOperation.cc +++ b/source/blender/compositor/operations/COM_DespeckleOperation.cc @@ -163,12 +163,12 @@ void DespeckleOperation::update_memory_buffer_partial(MemoryBuffer *output, const int last_x = get_width() - 1; const int last_y = get_height() - 1; for (BuffersIterator it = output->iterate_with(inputs, area); !it.is_end(); ++it) { - const int x1 = MAX2(it.x - 1, 0); + const int x1 = std::max(it.x - 1, 0); const int x2 = it.x; - const int x3 = MIN2(it.x + 1, last_x); - const int y1 = MAX2(it.y - 1, 0); + const int x3 = std::min(it.x + 1, last_x); + const int y1 = std::max(it.y - 1, 0); const int y2 = it.y; - const int y3 = MIN2(it.y + 1, last_y); + const int y3 = std::min(it.y + 1, last_y); float w = 0.0f; const float *color_org = it.in(IMAGE_INPUT_INDEX); diff --git a/source/blender/compositor/operations/COM_DilateErodeOperation.cc b/source/blender/compositor/operations/COM_DilateErodeOperation.cc index fe032628651..b8a341fe068 100644 --- a/source/blender/compositor/operations/COM_DilateErodeOperation.cc +++ b/source/blender/compositor/operations/COM_DilateErodeOperation.cc @@ -25,7 +25,7 @@ void DilateErodeThresholdOperation::init_data() } else { if (inset_ * 2 > distance_) { - scope_ = MAX2(inset_ * 2 - distance_, distance_); + scope_ = std::max(inset_ * 2 - distance_, distance_); } else { scope_ = distance_; @@ -60,10 +60,10 @@ void DilateErodeThresholdOperation::execute_pixel(float output[4], int x, int y, MemoryBuffer *input_buffer = (MemoryBuffer *)data; float *buffer = input_buffer->get_buffer(); const rcti &input_rect = input_buffer->get_rect(); - const int minx = MAX2(x - scope_, input_rect.xmin); - const int miny = MAX2(y - scope_, input_rect.ymin); - const int maxx = MIN2(x + scope_, input_rect.xmax); - const int maxy = MIN2(y + scope_, input_rect.ymax); + const int minx = std::max(x - scope_, input_rect.xmin); + const int miny = std::max(y - scope_, input_rect.ymin); + const int maxx = std::min(x + scope_, input_rect.xmax); + const int maxy = std::min(y + scope_, input_rect.ymax); const int buffer_width = input_buffer->get_width(); int offset; @@ -76,7 +76,7 @@ void DilateErodeThresholdOperation::execute_pixel(float output[4], int x, int y, if (buffer[offset] < sw) { const float dx = xi - x; const float dis = dx * dx + dy * dy; - mindist = MIN2(mindist, dis); + mindist = std::min(mindist, dis); } offset++; } @@ -91,7 +91,7 @@ void DilateErodeThresholdOperation::execute_pixel(float output[4], int x, int y, if (buffer[offset] > sw) { const float dx = xi - x; const float dis = dx * dx + dy * dy; - mindist = MIN2(mindist, dis); + mindist = std::min(mindist, dis); } offset++; } @@ -192,7 +192,7 @@ static float get_min_distance(DilateErodeThresholdOperation::PixelData &p) if (compare(*elem, p.sw)) { const float dx = xi - p.x; const float dist = dx * dx + dist_y; - min_dist = MIN2(min_dist, dist); + min_dist = std::min(min_dist, dist); } elem += p.elem_stride; } @@ -218,10 +218,10 @@ void DilateErodeThresholdOperation::update_memory_buffer_partial(MemoryBuffer *o for (BuffersIterator it = output->iterate_with(inputs, area); !it.is_end(); ++it) { p.x = it.x; p.y = it.y; - p.xmin = MAX2(p.x - scope_, input_rect.xmin); - p.ymin = MAX2(p.y - scope_, input_rect.ymin); - p.xmax = MIN2(p.x + scope_, input_rect.xmax); - p.ymax = MIN2(p.y + scope_, input_rect.ymax); + p.xmin = std::max(p.x - scope_, input_rect.xmin); + p.ymin = std::max(p.y - scope_, input_rect.ymin); + p.xmax = std::min(p.x + scope_, input_rect.xmax); + p.ymax = std::min(p.y + scope_, input_rect.ymax); p.elem = it.in(0); float pixel_value; @@ -290,10 +290,10 @@ void DilateDistanceOperation::execute_pixel(float output[4], int x, int y, void MemoryBuffer *input_buffer = (MemoryBuffer *)data; float *buffer = input_buffer->get_buffer(); const rcti &input_rect = input_buffer->get_rect(); - const int minx = MAX2(x - scope_, input_rect.xmin); - const int miny = MAX2(y - scope_, input_rect.ymin); - const int maxx = MIN2(x + scope_, input_rect.xmax); - const int maxy = MIN2(y + scope_, input_rect.ymax); + const int minx = std::max(x - scope_, input_rect.xmin); + const int miny = std::max(y - scope_, input_rect.ymin); + const int maxx = std::min(x + scope_, input_rect.xmax); + const int maxy = std::min(y + scope_, input_rect.ymax); const int buffer_width = input_buffer->get_width(); int offset; @@ -306,7 +306,7 @@ void DilateDistanceOperation::execute_pixel(float output[4], int x, int y, void const float dx = xi - x; const float dis = dx * dx + dy * dy; if (dis <= mindist) { - value = MAX2(buffer[offset], value); + value = std::max(buffer[offset], value); } offset++; } @@ -395,10 +395,10 @@ struct DilateDistanceOperation::PixelData { { x = it.x; y = it.y; - xmin = MAX2(x - scope, input_rect.xmin); - ymin = MAX2(y - scope, input_rect.ymin); - xmax = MIN2(x + scope, input_rect.xmax); - ymax = MIN2(y + scope, input_rect.ymax); + xmin = std::max(x - scope, input_rect.xmin); + ymin = std::max(y - scope, input_rect.ymin); + xmax = std::min(x + scope, input_rect.xmax); + ymax = std::min(y + scope, input_rect.ymax); elem = it.in(0); } }; @@ -455,10 +455,10 @@ void ErodeDistanceOperation::execute_pixel(float output[4], int x, int y, void * MemoryBuffer *input_buffer = (MemoryBuffer *)data; float *buffer = input_buffer->get_buffer(); const rcti &input_rect = input_buffer->get_rect(); - const int minx = MAX2(x - scope_, input_rect.xmin); - const int miny = MAX2(y - scope_, input_rect.ymin); - const int maxx = MIN2(x + scope_, input_rect.xmax); - const int maxy = MIN2(y + scope_, input_rect.ymax); + const int minx = std::max(x - scope_, input_rect.xmin); + const int miny = std::max(y - scope_, input_rect.ymin); + const int maxx = std::min(x + scope_, input_rect.xmax); + const int maxy = std::min(y + scope_, input_rect.ymax); const int buffer_width = input_buffer->get_width(); int offset; @@ -471,7 +471,7 @@ void ErodeDistanceOperation::execute_pixel(float output[4], int x, int y, void * const float dx = xi - x; const float dis = dx * dx + dy * dy; if (dis <= mindist) { - value = MIN2(buffer[offset], value); + value = std::min(buffer[offset], value); } offset++; } @@ -557,10 +557,10 @@ void *DilateStepOperation::initialize_tile_data(rcti *rect) int half_window = iterations_; int window = half_window * 2 + 1; - int xmin = MAX2(0, rect->xmin - half_window); - int ymin = MAX2(0, rect->ymin - half_window); - int xmax = MIN2(width, rect->xmax + half_window); - int ymax = MIN2(height, rect->ymax + half_window); + int xmin = std::max(0, rect->xmin - half_window); + int ymin = std::max(0, rect->ymin - half_window); + int xmax = std::min(width, rect->xmax + half_window); + int ymax = std::min(height, rect->ymax + half_window); int bwidth = rect->xmax - rect->xmin; int bheight = rect->ymax - rect->ymin; @@ -575,7 +575,7 @@ void *DilateStepOperation::initialize_tile_data(rcti *rect) * single row or column of input values, padded with FLT_MAX's to * simplify the logic. */ float *temp = (float *)MEM_mallocN(sizeof(float) * (2 * window - 1), "dilate erode temp"); - float *buf = (float *)MEM_mallocN(sizeof(float) * (MAX2(bwidth, bheight) + 5 * half_window), + float *buf = (float *)MEM_mallocN(sizeof(float) * (std::max(bwidth, bheight) + 5 * half_window), "dilate erode buf"); /* The following is based on the van Herk/Gil-Werman algorithm for morphology operations. @@ -593,13 +593,13 @@ void *DilateStepOperation::initialize_tile_data(rcti *rect) temp[window - 1] = buf[start]; for (x = 1; x < window; x++) { - temp[window - 1 - x] = MAX2(temp[window - x], buf[start - x]); - temp[window - 1 + x] = MAX2(temp[window + x - 2], buf[start + x]); + temp[window - 1 - x] = std::max(temp[window - x], buf[start - x]); + temp[window - 1 + x] = std::max(temp[window + x - 2], buf[start + x]); } start = half_window + (i - 1) * window + 1; - for (x = -MIN2(0, start); x < window - MAX2(0, start + window - bwidth); x++) { - rectf[bwidth * (y - ymin) + (start + x)] = MAX2(temp[x], temp[x + window - 1]); + for (x = -std::min(0, start); x < window - std::max(0, start + window - bwidth); x++) { + rectf[bwidth * (y - ymin) + (start + x)] = std::max(temp[x], temp[x + window - 1]); } } } @@ -618,14 +618,14 @@ void *DilateStepOperation::initialize_tile_data(rcti *rect) temp[window - 1] = buf[start]; for (y = 1; y < window; y++) { - temp[window - 1 - y] = MAX2(temp[window - y], buf[start - y]); - temp[window - 1 + y] = MAX2(temp[window + y - 2], buf[start + y]); + temp[window - 1 - y] = std::max(temp[window - y], buf[start - y]); + temp[window - 1 + y] = std::max(temp[window + y - 2], buf[start + y]); } start = half_window + (i - 1) * window + 1; - for (y = -MIN2(0, start); y < window - MAX2(0, start + window - bheight); y++) { - rectf[bwidth * (y + start + (rect->ymin - ymin)) + x] = MAX2(temp[y], - temp[y + window - 1]); + for (y = -std::min(0, start); y < window - std::max(0, start + window - bheight); y++) { + rectf[bwidth * (y + start + (rect->ymin - ymin)) + x] = std::max(temp[y], + temp[y + window - 1]); } } } @@ -697,10 +697,10 @@ static void step_update_memory_buffer(MemoryBuffer *output, const int half_window = num_iterations; const int window = half_window * 2 + 1; - const int xmin = MAX2(0, area.xmin - half_window); - const int ymin = MAX2(0, area.ymin - half_window); - const int xmax = MIN2(width, area.xmax + half_window); - const int ymax = MIN2(height, area.ymax + half_window); + const int xmin = std::max(0, area.xmin - half_window); + const int ymin = std::max(0, area.ymin - half_window); + const int xmax = std::min(width, area.xmax + half_window); + const int ymax = std::min(height, area.ymax + half_window); const int bwidth = area.xmax - area.xmin; const int bheight = area.ymax - area.ymin; @@ -716,7 +716,7 @@ static void step_update_memory_buffer(MemoryBuffer *output, * single row or column of input values, padded with #limit values to * simplify the logic. */ float *temp = (float *)MEM_mallocN(sizeof(float) * (2 * window - 1), "dilate erode temp"); - float *buf = (float *)MEM_mallocN(sizeof(float) * (MAX2(bwidth, bheight) + 5 * half_window), + float *buf = (float *)MEM_mallocN(sizeof(float) * (std::max(bwidth, bheight) + 5 * half_window), "dilate erode buf"); /* The following is based on the van Herk/Gil-Werman algorithm for morphology operations. */ @@ -739,7 +739,7 @@ static void step_update_memory_buffer(MemoryBuffer *output, } start = half_window + (i - 1) * window + 1; - for (int x = -MIN2(0, start); x < window - MAX2(0, start + window - bwidth); x++) { + for (int x = -std::min(0, start); x < window - std::max(0, start + window - bwidth); x++) { result.get_value(start + x + area.xmin, y, 0) = selector(temp[x], temp[x + window - 1]); } } @@ -764,7 +764,7 @@ static void step_update_memory_buffer(MemoryBuffer *output, } start = half_window + (i - 1) * window + 1; - for (int y = -MIN2(0, start); y < window - MAX2(0, start + window - bheight); y++) { + for (int y = -std::min(0, start); y < window - std::max(0, start + window - bheight); y++) { result.get_value(x + area.xmin, y + start + area.ymin, 0) = selector(temp[y], temp[y + window - 1]); } @@ -780,7 +780,7 @@ static void step_update_memory_buffer(MemoryBuffer *output, struct Max2Selector { float operator()(float f1, float f2) const { - return MAX2(f1, f2); + return std::max(f1, f2); } }; @@ -807,10 +807,10 @@ void *ErodeStepOperation::initialize_tile_data(rcti *rect) int half_window = iterations_; int window = half_window * 2 + 1; - int xmin = MAX2(0, rect->xmin - half_window); - int ymin = MAX2(0, rect->ymin - half_window); - int xmax = MIN2(width, rect->xmax + half_window); - int ymax = MIN2(height, rect->ymax + half_window); + int xmin = std::max(0, rect->xmin - half_window); + int ymin = std::max(0, rect->ymin - half_window); + int xmax = std::min(width, rect->xmax + half_window); + int ymax = std::min(height, rect->ymax + half_window); int bwidth = rect->xmax - rect->xmin; int bheight = rect->ymax - rect->ymin; @@ -825,7 +825,7 @@ void *ErodeStepOperation::initialize_tile_data(rcti *rect) * single row or column of input values, padded with FLT_MAX's to * simplify the logic. */ float *temp = (float *)MEM_mallocN(sizeof(float) * (2 * window - 1), "dilate erode temp"); - float *buf = (float *)MEM_mallocN(sizeof(float) * (MAX2(bwidth, bheight) + 5 * half_window), + float *buf = (float *)MEM_mallocN(sizeof(float) * (std::max(bwidth, bheight) + 5 * half_window), "dilate erode buf"); /* The following is based on the van Herk/Gil-Werman algorithm for morphology operations. @@ -843,13 +843,13 @@ void *ErodeStepOperation::initialize_tile_data(rcti *rect) temp[window - 1] = buf[start]; for (x = 1; x < window; x++) { - temp[window - 1 - x] = MIN2(temp[window - x], buf[start - x]); - temp[window - 1 + x] = MIN2(temp[window + x - 2], buf[start + x]); + temp[window - 1 - x] = std::min(temp[window - x], buf[start - x]); + temp[window - 1 + x] = std::min(temp[window + x - 2], buf[start + x]); } start = half_window + (i - 1) * window + 1; - for (x = -MIN2(0, start); x < window - MAX2(0, start + window - bwidth); x++) { - rectf[bwidth * (y - ymin) + (start + x)] = MIN2(temp[x], temp[x + window - 1]); + for (x = -std::min(0, start); x < window - std::max(0, start + window - bwidth); x++) { + rectf[bwidth * (y - ymin) + (start + x)] = std::min(temp[x], temp[x + window - 1]); } } } @@ -868,14 +868,14 @@ void *ErodeStepOperation::initialize_tile_data(rcti *rect) temp[window - 1] = buf[start]; for (y = 1; y < window; y++) { - temp[window - 1 - y] = MIN2(temp[window - y], buf[start - y]); - temp[window - 1 + y] = MIN2(temp[window + y - 2], buf[start + y]); + temp[window - 1 - y] = std::min(temp[window - y], buf[start - y]); + temp[window - 1 + y] = std::min(temp[window + y - 2], buf[start + y]); } start = half_window + (i - 1) * window + 1; - for (y = -MIN2(0, start); y < window - MAX2(0, start + window - bheight); y++) { - rectf[bwidth * (y + start + (rect->ymin - ymin)) + x] = MIN2(temp[y], - temp[y + window - 1]); + for (y = -std::min(0, start); y < window - std::max(0, start + window - bheight); y++) { + rectf[bwidth * (y + start + (rect->ymin - ymin)) + x] = std::min(temp[y], + temp[y + window - 1]); } } } @@ -889,7 +889,7 @@ void *ErodeStepOperation::initialize_tile_data(rcti *rect) struct Min2Selector { float operator()(float f1, float f2) const { - return MIN2(f1, f2); + return std::min(f1, f2); } }; diff --git a/source/blender/compositor/operations/COM_EllipseMaskOperation.cc b/source/blender/compositor/operations/COM_EllipseMaskOperation.cc index 252efc50909..f11c9a69386 100644 --- a/source/blender/compositor/operations/COM_EllipseMaskOperation.cc +++ b/source/blender/compositor/operations/COM_EllipseMaskOperation.cc @@ -59,7 +59,7 @@ void EllipseMaskOperation::execute_pixel_sampled(float output[4], switch (mask_type_) { case CMP_NODE_MASKTYPE_ADD: if (inside) { - output[0] = MAX2(input_mask[0], input_value[0]); + output[0] = std::max(input_mask[0], input_value[0]); } else { output[0] = input_mask[0]; @@ -106,7 +106,7 @@ void EllipseMaskOperation::update_memory_buffer_partial(MemoryBuffer *output, switch (mask_type_) { case CMP_NODE_MASKTYPE_ADD: mask_func = [](const bool is_inside, const float *mask, const float *value) { - return is_inside ? MAX2(mask[0], value[0]) : mask[0]; + return is_inside ? std::max(mask[0], value[0]) : mask[0]; }; break; case CMP_NODE_MASKTYPE_SUBTRACT: diff --git a/source/blender/compositor/operations/COM_FastGaussianBlurOperation.cc b/source/blender/compositor/operations/COM_FastGaussianBlurOperation.cc index ed9ba75f8dc..ec87e31d5d2 100644 --- a/source/blender/compositor/operations/COM_FastGaussianBlurOperation.cc +++ b/source/blender/compositor/operations/COM_FastGaussianBlurOperation.cc @@ -210,7 +210,7 @@ void FastGaussianBlurOperation::IIR_gauss(MemoryBuffer *src, float sigma, uint c (void)0 /* Intermediate buffers. */ - src_dim_max = MAX2(src_width, src_height); + src_dim_max = std::max(src_width, src_height); X = (double *)MEM_callocN(src_dim_max * sizeof(double), "IIR_gauss X buf"); Y = (double *)MEM_callocN(src_dim_max * sizeof(double), "IIR_gauss Y buf"); W = (double *)MEM_callocN(src_dim_max * sizeof(double), "IIR_gauss W buf"); @@ -424,12 +424,12 @@ void FastGaussianBlurValueOperation::update_memory_buffer_partial(MemoryBuffer * BuffersIterator it = output->iterate_with({image, iirgaus_}, area); if (overlay_ == FAST_GAUSS_OVERLAY_MIN) { for (; !it.is_end(); ++it) { - *it.out = MIN2(*it.in(0), *it.in(1)); + *it.out = std::min(*it.in(0), *it.in(1)); } } else if (overlay_ == FAST_GAUSS_OVERLAY_MAX) { for (; !it.is_end(); ++it) { - *it.out = MAX2(*it.in(0), *it.in(1)); + *it.out = std::max(*it.in(0), *it.in(1)); } } } diff --git a/source/blender/compositor/operations/COM_GaussianBokehBlurOperation.cc b/source/blender/compositor/operations/COM_GaussianBokehBlurOperation.cc index 995e624a2e9..3f514f69d11 100644 --- a/source/blender/compositor/operations/COM_GaussianBokehBlurOperation.cc +++ b/source/blender/compositor/operations/COM_GaussianBokehBlurOperation.cc @@ -319,7 +319,7 @@ void GaussianBlurReferenceOperation::init_execution() void GaussianBlurReferenceOperation::update_gauss() { int i; - int x = MAX2(filtersizex_, filtersizey_); + int x = std::max(filtersizex_, filtersizey_); maintabs_ = (float **)MEM_mallocN(x * sizeof(float *), "gauss array"); for (i = 0; i < x; i++) { maintabs_[i] = make_gausstab(i + 1, i + 1); @@ -396,7 +396,7 @@ void GaussianBlurReferenceOperation::execute_pixel(float output[4], int x, int y void GaussianBlurReferenceOperation::deinit_execution() { int x, i; - x = MAX2(filtersizex_, filtersizey_); + x = std::max(filtersizex_, filtersizey_); for (i = 0; i < x; i++) { MEM_freeN(maintabs_[i]); } diff --git a/source/blender/compositor/operations/COM_ImageOperation.cc b/source/blender/compositor/operations/COM_ImageOperation.cc index b246fdff916..7eb0a4ed238 100644 --- a/source/blender/compositor/operations/COM_ImageOperation.cc +++ b/source/blender/compositor/operations/COM_ImageOperation.cc @@ -91,8 +91,13 @@ void BaseImageOperation::determine_canvas(const rcti & /*preferred_area*/, rcti BKE_image_release_ibuf(image_, stackbuf, nullptr); } -static void sample_image_at_location( - ImBuf *ibuf, float x, float y, PixelSampler sampler, bool make_linear_rgb, float color[4]) +static void sample_image_at_location(ImBuf *ibuf, + float x, + float y, + PixelSampler sampler, + bool make_linear_rgb, + bool ensure_premultiplied, + float color[4]) { if (ibuf->float_buffer.data) { switch (sampler) { @@ -125,6 +130,9 @@ static void sample_image_at_location( IMB_colormanagement_colorspace_to_scene_linear_v4( color, false, ibuf->byte_buffer.colorspace); } + if (ensure_premultiplied) { + straight_to_premul_v4(color); + } } } @@ -138,7 +146,9 @@ void ImageOperation::execute_pixel_sampled(float output[4], float x, float y, Pi zero_v4(output); } else { - sample_image_at_location(buffer_, x, y, sampler, true, output); + const bool ensure_premultiplied = !ELEM( + image_->alpha_mode, IMA_ALPHA_CHANNEL_PACKED, IMA_ALPHA_IGNORE); + sample_image_at_location(buffer_, x, y, sampler, true, ensure_premultiplied, output); } } @@ -146,7 +156,9 @@ void ImageOperation::update_memory_buffer_partial(MemoryBuffer *output, const rcti &area, Span /*inputs*/) { - output->copy_from(buffer_, area, true); + const bool ensure_premultiplied = !ELEM( + image_->alpha_mode, IMA_ALPHA_CHANNEL_PACKED, IMA_ALPHA_IGNORE); + output->copy_from(buffer_, area, ensure_premultiplied, true); } void ImageAlphaOperation::execute_pixel_sampled(float output[4], @@ -161,7 +173,7 @@ void ImageAlphaOperation::execute_pixel_sampled(float output[4], } else { tempcolor[3] = 1.0f; - sample_image_at_location(buffer_, x, y, sampler, false, tempcolor); + sample_image_at_location(buffer_, x, y, sampler, false, false, tempcolor); output[0] = tempcolor[3]; } } diff --git a/source/blender/compositor/operations/COM_KeyingBlurOperation.cc b/source/blender/compositor/operations/COM_KeyingBlurOperation.cc index 0314d766f6c..4f95176d3f6 100644 --- a/source/blender/compositor/operations/COM_KeyingBlurOperation.cc +++ b/source/blender/compositor/operations/COM_KeyingBlurOperation.cc @@ -33,7 +33,8 @@ void KeyingBlurOperation::execute_pixel(float output[4], int x, int y, void *dat float average = 0.0f; if (axis_ == 0) { - const int start = MAX2(0, x - size_ + 1), end = MIN2(buffer_width, x + size_); + const int start = MAX2(0, x - size_ + 1); + const int end = std::min(buffer_width, x + size_); for (int cx = start; cx < end; cx++) { int buffer_index = (y * buffer_width + cx); average += buffer[buffer_index]; @@ -41,7 +42,8 @@ void KeyingBlurOperation::execute_pixel(float output[4], int x, int y, void *dat } } else { - const int start = MAX2(0, y - size_ + 1), end = MIN2(input_buffer->get_height(), y + size_); + const int start = std::max(0, y - size_ + 1); + const int end = std::min(input_buffer->get_height(), y + size_); for (int cy = start; cy < end; cy++) { int buffer_index = (cy * buffer_width + x); average += buffer[buffer_index]; @@ -124,8 +126,8 @@ void KeyingBlurOperation::update_memory_buffer_partial(MemoryBuffer *output, for (; !it.is_end(); ++it) { const int coord = get_current_coord(); - const int start_coord = MAX2(0, coord - size_ + 1); - const int end_coord = MIN2(coord_max, coord + size_); + const int start_coord = std::max(0, coord - size_ + 1); + const int end_coord = std::min(coord_max, coord + size_); const int count = end_coord - start_coord; float sum = 0.0f; diff --git a/source/blender/compositor/operations/COM_KeyingClipOperation.cc b/source/blender/compositor/operations/COM_KeyingClipOperation.cc index b70c1b03d56..4a1b2835936 100644 --- a/source/blender/compositor/operations/COM_KeyingClipOperation.cc +++ b/source/blender/compositor/operations/COM_KeyingClipOperation.cc @@ -140,10 +140,10 @@ void KeyingClipOperation::update_memory_buffer_partial(MemoryBuffer *output, const int x = it.x; const int y = it.y; - const int start_x = MAX2(0, x - delta + 1); - const int start_y = MAX2(0, y - delta + 1); - const int end_x = MIN2(x + delta, width); - const int end_y = MIN2(y + delta, height); + const int start_x = std::max(0, x - delta + 1); + const int start_y = std::max(0, y - delta + 1); + const int end_x = std::min(x + delta, width); + const int end_y = std::min(y + delta, height); const int x_len = end_x - start_x; const int y_len = end_y - start_y; diff --git a/source/blender/compositor/operations/COM_KeyingDespillOperation.cc b/source/blender/compositor/operations/COM_KeyingDespillOperation.cc index 2e44f5d50a4..a3bc7726212 100644 --- a/source/blender/compositor/operations/COM_KeyingDespillOperation.cc +++ b/source/blender/compositor/operations/COM_KeyingDespillOperation.cc @@ -49,8 +49,8 @@ void KeyingDespillOperation::execute_pixel_sampled(float output[4], const int other_1 = (screen_primary_channel + 1) % 3; const int other_2 = (screen_primary_channel + 2) % 3; - const int min_channel = MIN2(other_1, other_2); - const int max_channel = MAX2(other_1, other_2); + const int min_channel = std::min(other_1, other_2); + const int max_channel = std::max(other_1, other_2); float average_value, amount; @@ -78,8 +78,8 @@ void KeyingDespillOperation::update_memory_buffer_partial(MemoryBuffer *output, const int other_1 = (screen_primary_channel + 1) % 3; const int other_2 = (screen_primary_channel + 2) % 3; - const int min_channel = MIN2(other_1, other_2); - const int max_channel = MAX2(other_1, other_2); + const int min_channel = std::min(other_1, other_2); + const int max_channel = std::max(other_1, other_2); const float average_value = color_balance_ * pixel_color[min_channel] + (1.0f - color_balance_) * pixel_color[max_channel]; diff --git a/source/blender/compositor/operations/COM_KeyingOperation.cc b/source/blender/compositor/operations/COM_KeyingOperation.cc index 19d099fc32c..e9eedf0cb13 100644 --- a/source/blender/compositor/operations/COM_KeyingOperation.cc +++ b/source/blender/compositor/operations/COM_KeyingOperation.cc @@ -15,8 +15,8 @@ static float get_pixel_saturation(const float pixel_color[4], const int other_1 = (primary_channel + 1) % 3; const int other_2 = (primary_channel + 2) % 3; - const int min_channel = MIN2(other_1, other_2); - const int max_channel = MAX2(other_1, other_2); + const int min_channel = std::min(other_1, other_2); + const int max_channel = std::max(other_1, other_2); const float val = screen_balance * pixel_color[min_channel] + (1.0f - screen_balance) * pixel_color[max_channel]; diff --git a/source/blender/compositor/operations/COM_KuwaharaAnisotropicStructureTensorOperation.cc b/source/blender/compositor/operations/COM_KuwaharaAnisotropicStructureTensorOperation.cc index bd54a2b062d..66be7a256b3 100644 --- a/source/blender/compositor/operations/COM_KuwaharaAnisotropicStructureTensorOperation.cc +++ b/source/blender/compositor/operations/COM_KuwaharaAnisotropicStructureTensorOperation.cc @@ -1,4 +1,4 @@ -/* SPDX-FileCopyrightText: 2023 Blender Foundation +/* SPDX-FileCopyrightText: 2023 Blender Authors * * SPDX-License-Identifier: GPL-2.0-or-later */ diff --git a/source/blender/compositor/operations/COM_KuwaharaAnisotropicStructureTensorOperation.h b/source/blender/compositor/operations/COM_KuwaharaAnisotropicStructureTensorOperation.h index 5e35c06b8ac..2a76cfd3e7e 100644 --- a/source/blender/compositor/operations/COM_KuwaharaAnisotropicStructureTensorOperation.h +++ b/source/blender/compositor/operations/COM_KuwaharaAnisotropicStructureTensorOperation.h @@ -1,4 +1,4 @@ -/* SPDX-FileCopyrightText: 2023 Blender Foundation +/* SPDX-FileCopyrightText: 2023 Blender Authors * * SPDX-License-Identifier: GPL-2.0-or-later */ diff --git a/source/blender/compositor/operations/COM_MathBaseOperation.cc b/source/blender/compositor/operations/COM_MathBaseOperation.cc index 46f989dc323..5d65014f888 100644 --- a/source/blender/compositor/operations/COM_MathBaseOperation.cc +++ b/source/blender/compositor/operations/COM_MathBaseOperation.cc @@ -997,8 +997,9 @@ void MathCompareOperation::execute_pixel_sampled(float output[4], input_value2_operation_->read_sampled(input_value2, x, y, sampler); input_value3_operation_->read_sampled(input_value3, x, y, sampler); - output[0] = (fabsf(input_value1[0] - input_value2[0]) <= MAX2(input_value3[0], 1e-5f)) ? 1.0f : - 0.0f; + output[0] = (fabsf(input_value1[0] - input_value2[0]) <= std::max(input_value3[0], 1e-5f)) ? + 1.0f : + 0.0f; clamp_if_needed(output); } diff --git a/source/blender/compositor/operations/COM_RotateOperation.cc b/source/blender/compositor/operations/COM_RotateOperation.cc index 2b189fea492..aea2198da57 100644 --- a/source/blender/compositor/operations/COM_RotateOperation.cc +++ b/source/blender/compositor/operations/COM_RotateOperation.cc @@ -57,9 +57,9 @@ void RotateOperation::get_area_rotation_bounds(const rcti &area, const float y3 = center_y + (sine * dxmin + cosine * dymax); const float y4 = center_y + (sine * dxmax + cosine * dymax); const float minx = MIN2(x1, MIN2(x2, MIN2(x3, x4))); - const float maxx = MAX2(x1, MAX2(x2, MAX2(x3, x4))); - const float miny = MIN2(y1, MIN2(y2, MIN2(y3, y4))); - const float maxy = MAX2(y1, MAX2(y2, MAX2(y3, y4))); + const float maxx = std::max(x1, MAX2(x2, std::max(x3, x4))); + const float miny = MIN2(y1, std::min(y2, MIN2(y3, y4))); + const float maxy = std::max(y1, MAX2(y2, std::max(y3, y4))); r_bounds.xmin = floor(minx); r_bounds.xmax = ceil(maxx); @@ -191,10 +191,10 @@ bool RotateOperation::determine_depending_area_of_interest(rcti *input, const float y2 = center_y_ + (-sine_ * dxmax + cosine_ * dymin); const float y3 = center_y_ + (-sine_ * dxmin + cosine_ * dymax); const float y4 = center_y_ + (-sine_ * dxmax + cosine_ * dymax); - const float minx = MIN2(x1, MIN2(x2, MIN2(x3, x4))); - const float maxx = MAX2(x1, MAX2(x2, MAX2(x3, x4))); - const float miny = MIN2(y1, MIN2(y2, MIN2(y3, y4))); - const float maxy = MAX2(y1, MAX2(y2, MAX2(y3, y4))); + const float minx = std::min(x1, std::min(x2, std::min(x3, x4))); + const float maxx = std::max(x1, std::max(x2, std::max(x3, x4))); + const float miny = std::min(y1, std::min(y2, std::min(y3, y4))); + const float maxy = std::max(y1, std::max(y2, std::max(y3, y4))); new_input.xmax = ceil(maxx) + 1; new_input.xmin = floor(minx) - 1; diff --git a/source/blender/compositor/operations/COM_ScaleOperation.cc b/source/blender/compositor/operations/COM_ScaleOperation.cc index 4b24e1b4f5c..a8a5421b3ba 100644 --- a/source/blender/compositor/operations/COM_ScaleOperation.cc +++ b/source/blender/compositor/operations/COM_ScaleOperation.cc @@ -223,8 +223,8 @@ void ScaleOperation::determine_canvas(const rcti &preferred_area, rcti &r_area) const float scale_x = get_constant_scale_x(input_width); const float scale_y = get_constant_scale_y(input_height); scale_area(r_area, scale_x, scale_y); - const Size2f max_scale_size = {MAX2(input_width, max_scale_canvas_size_.x), - MAX2(input_height, max_scale_canvas_size_.y)}; + const Size2f max_scale_size = {std::max(input_width, max_scale_canvas_size_.x), + std::max(input_height, max_scale_canvas_size_.y)}; clamp_area_size_max(r_area, max_scale_size); /* Re-determine canvases of x and y constant inputs with scaled canvas as preferred. */ diff --git a/source/blender/compositor/operations/COM_SummedAreaTableOperation.cc b/source/blender/compositor/operations/COM_SummedAreaTableOperation.cc index 258f0e12e1e..4b7b03cbe84 100644 --- a/source/blender/compositor/operations/COM_SummedAreaTableOperation.cc +++ b/source/blender/compositor/operations/COM_SummedAreaTableOperation.cc @@ -1,4 +1,4 @@ -/* SPDX-FileCopyrightText: 2023 Blender Foundation +/* SPDX-FileCopyrightText: 2023 Blender Authors * * SPDX-License-Identifier: GPL-2.0-or-later */ @@ -155,8 +155,8 @@ float4 summed_area_table_sum_tiled(SocketReader *buffer, const rcti &area) int2 corrected_lower_bound = lower_bound - int2(1, 1); int2 corrected_upper_bound; - corrected_upper_bound[0] = math::min((int)buffer->get_width() - 1, upper_bound[0]); - corrected_upper_bound[1] = math::min((int)buffer->get_height() - 1, upper_bound[1]); + corrected_upper_bound[0] = math::min(int(buffer->get_width()) - 1, upper_bound[0]); + corrected_upper_bound[1] = math::min(int(buffer->get_height()) - 1, upper_bound[1]); float4 a, b, c, d, addend, substrahend; buffer->read_sampled( diff --git a/source/blender/compositor/operations/COM_SummedAreaTableOperation.h b/source/blender/compositor/operations/COM_SummedAreaTableOperation.h index 05d1bba0461..e4766a56740 100644 --- a/source/blender/compositor/operations/COM_SummedAreaTableOperation.h +++ b/source/blender/compositor/operations/COM_SummedAreaTableOperation.h @@ -1,4 +1,4 @@ -/* SPDX-FileCopyrightText: 2023 Blender Foundation +/* SPDX-FileCopyrightText: 2023 Blender Authors * * SPDX-License-Identifier: GPL-2.0-or-later */ diff --git a/source/blender/compositor/operations/COM_TonemapOperation.cc b/source/blender/compositor/operations/COM_TonemapOperation.cc index cfeb88ab1ac..51dce9cc4d1 100644 --- a/source/blender/compositor/operations/COM_TonemapOperation.cc +++ b/source/blender/compositor/operations/COM_TonemapOperation.cc @@ -39,9 +39,9 @@ void TonemapOperation::execute_pixel(float output[4], int x, int y, void *data) output[2] /= ((db == 0.0f) ? 1.0f : db); const float igm = avg->igm; if (igm != 0.0f) { - output[0] = powf(MAX2(output[0], 0.0f), igm); + output[0] = powf(std::max(output[0], 0.0f), igm); output[1] = powf(MAX2(output[1], 0.0f), igm); - output[2] = powf(MAX2(output[2], 0.0f), igm); + output[2] = powf(std::max(output[2], 0.0f), igm); } } void PhotoreceptorTonemapOperation::execute_pixel(float output[4], int x, int y, void *data) @@ -186,8 +186,8 @@ void TonemapOperation::update_memory_buffer_started(MemoryBuffer * /*output*/, join.sum += chunk.sum; add_v3_v3(join.color_sum, chunk.color_sum); join.log_sum += chunk.log_sum; - join.max = MAX2(join.max, chunk.max); - join.min = MIN2(join.min, chunk.min); + join.max = std::max(join.max, chunk.max); + join.min = std::min(join.min, chunk.min); join.num_pixels += chunk.num_pixels; }); @@ -224,7 +224,7 @@ void TonemapOperation::update_memory_buffer_partial(MemoryBuffer *output, if (igm != 0.0f) { it.out[0] = powf(MAX2(it.out[0], 0.0f), igm); it.out[1] = powf(MAX2(it.out[1], 0.0f), igm); - it.out[2] = powf(MAX2(it.out[2], 0.0f), igm); + it.out[2] = powf(std::max(it.out[2], 0.0f), igm); } } } diff --git a/source/blender/compositor/operations/COM_VariableSizeBokehBlurOperation.cc b/source/blender/compositor/operations/COM_VariableSizeBokehBlurOperation.cc index 7f93f529833..fbc0def4109 100644 --- a/source/blender/compositor/operations/COM_VariableSizeBokehBlurOperation.cc +++ b/source/blender/compositor/operations/COM_VariableSizeBokehBlurOperation.cc @@ -59,7 +59,7 @@ void *VariableSizeBokehBlurOperation::initialize_tile_data(rcti *rect) this->determine_depending_area_of_interest( rect, (ReadBufferOperation *)input_size_program_, &rect2); - const float max_dim = MAX2(this->get_width(), this->get_height()); + const float max_dim = std::max(this->get_width(), this->get_height()); const float scalar = do_size_scale_ ? (max_dim / 100.0f) : 1.0f; data->max_blur_scalar = int(data->size->get_max_value(rect2) * scalar); @@ -87,7 +87,7 @@ void VariableSizeBokehBlurOperation::execute_pixel(float output[4], int x, int y float multiplier_accum[4]; float color_accum[4]; - const float max_dim = MAX2(get_width(), get_height()); + const float max_dim = std::max(get_width(), get_height()); const float scalar = do_size_scale_ ? (max_dim / 100.0f) : 1.0f; int max_blur_scalar = tile_data->max_blur_scalar; @@ -105,10 +105,10 @@ void VariableSizeBokehBlurOperation::execute_pixel(float output[4], int x, int y int maxx = search[2]; int maxy = search[3]; #else - int minx = MAX2(x - max_blur_scalar, 0); - int miny = MAX2(y - max_blur_scalar, 0); - int maxx = MIN2(x + max_blur_scalar, int(get_width())); - int maxy = MIN2(y + max_blur_scalar, int(get_height())); + int minx = std::max(x - max_blur_scalar, 0); + int miny = std::max(y - max_blur_scalar, 0); + int maxx = std::min(x + max_blur_scalar, int(get_width())); + int maxy = std::min(y + max_blur_scalar, int(get_height())); #endif { input_size_buffer->read_no_check(temp_size, x, y); @@ -130,7 +130,8 @@ void VariableSizeBokehBlurOperation::execute_pixel(float output[4], int x, int y int offset_color_nx_ny = offset_value_nx_ny * COM_DATA_TYPE_COLOR_CHANNELS; for (int nx = minx; nx < maxx; nx += add_xstep_value) { if (nx != x || ny != y) { - float size = MIN2(input_size_float_buffer[offset_value_nx_ny] * scalar, size_center); + float size = std::min(input_size_float_buffer[offset_value_nx_ny] * scalar, + size_center); if (size > threshold_) { float dx = nx - x; if (size > fabsf(dx) && size > fabsf(dy)) { @@ -183,7 +184,7 @@ void VariableSizeBokehBlurOperation::execute_opencl( MemoryBuffer *size_memory_buffer = input_size_program_->get_input_memory_buffer( input_memory_buffers); - const float max_dim = MAX2(get_width(), get_height()); + const float max_dim = std::max(get_width(), get_height()); cl_float scalar = do_size_scale_ ? (max_dim / 100.0f) : 1.0f; max_blur = (cl_int)min_ff(size_memory_buffer->get_max_value() * scalar, float(max_blur_)); @@ -223,7 +224,7 @@ bool VariableSizeBokehBlurOperation::determine_depending_area_of_interest( rcti new_input; rcti bokeh_input; - const float max_dim = MAX2(get_width(), get_height()); + const float max_dim = std::max(get_width(), get_height()); const float scalar = do_size_scale_ ? (max_dim / 100.0f) : 1.0f; int max_blur_scalar = max_blur_ * scalar; @@ -269,7 +270,7 @@ void VariableSizeBokehBlurOperation::get_area_of_interest(const int input_idx, switch (input_idx) { case IMAGE_INPUT_INDEX: case SIZE_INPUT_INDEX: { - const float max_dim = MAX2(get_width(), get_height()); + const float max_dim = std::max(get_width(), get_height()); const float scalar = do_size_scale_ ? (max_dim / 100.0f) : 1.0f; const int max_blur_scalar = max_blur_ * scalar; r_input_area.xmax = output_area.xmax + max_blur_scalar + 2; @@ -326,10 +327,10 @@ static void blur_pixel(int x, int y, PixelData &p) const int maxx = search[2]; const int maxy = search[3]; #else - const int minx = MAX2(x - p.max_blur_scalar, 0); - const int miny = MAX2(y - p.max_blur_scalar, 0); - const int maxx = MIN2(x + p.max_blur_scalar, p.image_width); - const int maxy = MIN2(y + p.max_blur_scalar, p.image_height); + const int minx = std::max(x - p.max_blur_scalar, 0); + const int miny = std::max(y - p.max_blur_scalar, 0); + const int maxx = std::min(x + p.max_blur_scalar, p.image_width); + const int maxy = std::min(y + p.max_blur_scalar, p.image_height); #endif const int color_row_stride = p.image_input->row_stride * p.step; @@ -350,7 +351,7 @@ static void blur_pixel(int x, int y, PixelData &p) if (nx == x && ny == y) { continue; } - const float size = MIN2(size_elem[0] * p.scalar, p.size_center); + const float size = std::min(size_elem[0] * p.scalar, p.size_center); if (size <= p.threshold) { continue; } @@ -391,7 +392,7 @@ void VariableSizeBokehBlurOperation::update_memory_buffer_partial(MemoryBuffer * BLI_rcti_isect(&scalar_area, &p.size_input->get_rect(), &scalar_area); const float max_size = p.size_input->get_max_value(scalar_area); - const float max_dim = MAX2(this->get_width(), this->get_height()); + const float max_dim = std::max(this->get_width(), this->get_height()); p.scalar = do_size_scale_ ? (max_dim / 100.0f) : 1.0f; p.max_blur_scalar = int(max_size * p.scalar); CLAMP(p.max_blur_scalar, 1, max_blur_); @@ -452,10 +453,10 @@ void *InverseSearchRadiusOperation::initialize_tile_data(rcti *rect) for (x = rect->xmin; x < rect->xmax; x++) { int rx = x * DIVIDER; int ry = y * DIVIDER; - buffer[offset] = MAX2(rx - max_blur_, 0); - buffer[offset + 1] = MAX2(ry - max_blur_, 0); - buffer[offset + 2] = MIN2(rx + DIVIDER + max_blur_, width); - buffer[offset + 3] = MIN2(ry + DIVIDER + max_blur_, height); + buffer[offset] = std::max(rx - max_blur_, 0); + buffer[offset + 1] = std::max(ry - max_blur_, 0); + buffer[offset + 2] = std::min(rx + DIVIDER + max_blur_, width); + buffer[offset + 3] = std::min(ry + DIVIDER + max_blur_, height); offset += 4; } } @@ -482,10 +483,10 @@ void *InverseSearchRadiusOperation::initialize_tile_data(rcti *rect) for (int x2 = x - impact_radius; x2 < x + impact_radius; x2++) { for (int y2 = y - impact_radius; y2 < y + impact_radius; y2++) { data->read(temp, x2, y2); - temp[0] = MIN2(temp[0], maxx); - temp[1] = MIN2(temp[1], maxy); - temp[2] = MAX2(temp[2], maxx); - temp[3] = MAX2(temp[3], maxy); + temp[0] = std::min(temp[0], maxx); + temp[1] = std::min(temp[1], maxy); + temp[2] = std::max(temp[2], maxx); + temp[3] = std::max(temp[3], maxy); data->write_pixel(x2, y2, temp); } } diff --git a/source/blender/compositor/operations/COM_ZCombineOperation.cc b/source/blender/compositor/operations/COM_ZCombineOperation.cc index d926d919a75..4ccd178407a 100644 --- a/source/blender/compositor/operations/COM_ZCombineOperation.cc +++ b/source/blender/compositor/operations/COM_ZCombineOperation.cc @@ -84,7 +84,7 @@ void ZCombineAlphaOperation::execute_pixel_sampled(float output[4], output[0] = fac * color1[0] + ifac * color2[0]; output[1] = fac * color1[1] + ifac * color2[1]; output[2] = fac * color1[2] + ifac * color2[2]; - output[3] = MAX2(color1[3], color2[3]); + output[3] = std::max(color1[3], color2[3]); } void ZCombineAlphaOperation::update_memory_buffer_partial(MemoryBuffer *output, @@ -109,7 +109,7 @@ void ZCombineAlphaOperation::update_memory_buffer_partial(MemoryBuffer *output, it.out[0] = fac * color1[0] + ifac * color2[0]; it.out[1] = fac * color1[1] + ifac * color2[1]; it.out[2] = fac * color1[2] + ifac * color2[2]; - it.out[3] = MAX2(color1[3], color2[3]); + it.out[3] = std::max(color1[3], color2[3]); } } @@ -188,7 +188,7 @@ void ZCombineMaskAlphaOperation::execute_pixel_sampled(float output[4], output[0] = color1[0] * mfac + color2[0] * fac; output[1] = color1[1] * mfac + color2[1] * fac; output[2] = color1[2] * mfac + color2[2] * fac; - output[3] = MAX2(color1[3], color2[3]); + output[3] = std::max(color1[3], color2[3]); } void ZCombineMaskAlphaOperation::update_memory_buffer_partial(MemoryBuffer *output, @@ -205,7 +205,7 @@ void ZCombineMaskAlphaOperation::update_memory_buffer_partial(MemoryBuffer *outp it.out[0] = color1[0] * mfac + color2[0] * fac; it.out[1] = color1[1] * mfac + color2[1] * fac; it.out[2] = color1[2] * mfac + color2[2] * fac; - it.out[3] = MAX2(color1[3], color2[3]); + it.out[3] = std::max(color1[3], color2[3]); } } diff --git a/source/blender/compositor/realtime_compositor/intern/scheduler.cc b/source/blender/compositor/realtime_compositor/intern/scheduler.cc index 1138f47c9a5..759a9f5c023 100644 --- a/source/blender/compositor/realtime_compositor/intern/scheduler.cc +++ b/source/blender/compositor/realtime_compositor/intern/scheduler.cc @@ -263,8 +263,8 @@ static NeededBuffers compute_number_of_needed_buffers(Stack &output_nodes /* Compute the heuristic estimation of the number of needed intermediate buffers to compute * this node and all of its dependencies. This is computing the aforementioned equation * "max(n + m, d)". */ - const int total_buffers = MAX2(number_of_input_buffers + number_of_output_buffers, - buffers_needed_by_dependencies); + const int total_buffers = std::max(number_of_input_buffers + number_of_output_buffers, + buffers_needed_by_dependencies); needed_buffers.add(node, total_buffers); } diff --git a/source/blender/compositor/realtime_compositor/shaders/infos/compositor_read_input_info.hh b/source/blender/compositor/realtime_compositor/shaders/infos/compositor_read_input_info.hh index a8e80ebb948..d1dee6b8a56 100644 --- a/source/blender/compositor/realtime_compositor/shaders/infos/compositor_read_input_info.hh +++ b/source/blender/compositor/realtime_compositor/shaders/infos/compositor_read_input_info.hh @@ -24,8 +24,10 @@ GPU_SHADER_CREATE_INFO(compositor_read_input_vector) GPU_SHADER_CREATE_INFO(compositor_read_input_color) .additional_info("compositor_read_input_shared") + .push_constant(Type::BOOL, "premultiply_alpha") .image(0, GPU_RGBA16F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img") - .define("READ_EXPRESSION(input_color)", "input_color") + .define("READ_EXPRESSION(input_color)", + "input_color * vec4(vec3(premultiply_alpha ? input_color.a : 1.0), 1.0)") .do_static_compilation(true); GPU_SHADER_CREATE_INFO(compositor_read_input_alpha) diff --git a/source/blender/compositor/tests/COM_ComputeSummedAreaTableOperation_test.cc b/source/blender/compositor/tests/COM_ComputeSummedAreaTableOperation_test.cc index 415fb908fb4..986a340e240 100644 --- a/source/blender/compositor/tests/COM_ComputeSummedAreaTableOperation_test.cc +++ b/source/blender/compositor/tests/COM_ComputeSummedAreaTableOperation_test.cc @@ -1,4 +1,4 @@ -/* SPDX-FileCopyrightText: 2023 Blender Foundation +/* SPDX-FileCopyrightText: 2023 Blender Authors * * SPDX-License-Identifier: GPL-2.0-or-later */ diff --git a/source/blender/depsgraph/intern/depsgraph_query_iter.cc b/source/blender/depsgraph/intern/depsgraph_query_iter.cc index 5b26381babc..86f42dfb379 100644 --- a/source/blender/depsgraph/intern/depsgraph_query_iter.cc +++ b/source/blender/depsgraph/intern/depsgraph_query_iter.cc @@ -171,7 +171,7 @@ bool deg_iterator_duplis_step(DEGObjectIterData *data) temp_dupli_object->base_local_view_bits = dupli_parent->base_local_view_bits; temp_dupli_object->runtime.local_collections_bits = dupli_parent->runtime.local_collections_bits; - temp_dupli_object->dt = MIN2(temp_dupli_object->dt, dupli_parent->dt); + temp_dupli_object->dt = std::min(temp_dupli_object->dt, dupli_parent->dt); copy_v4_v4(temp_dupli_object->color, dupli_parent->color); temp_dupli_object->runtime.select_id = dupli_parent->runtime.select_id; if (dob->ob->data != dob->ob_data) { diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt index ab76ae31337..c3343d1de50 100644 --- a/source/blender/draw/CMakeLists.txt +++ b/source/blender/draw/CMakeLists.txt @@ -35,6 +35,7 @@ set(INC_SYS ) set(SRC + intern/attribute_convert.cc intern/draw_cache.cc intern/draw_cache_extract_mesh.cc intern/draw_cache_extract_mesh_render_data.cc @@ -229,6 +230,7 @@ set(SRC DRW_engine.h DRW_pbvh.hh DRW_select_buffer.hh + intern/attribute_convert.hh intern/DRW_gpu_wrapper.hh intern/DRW_render.h intern/draw_attributes.hh diff --git a/source/blender/draw/engines/eevee/eevee_bloom.cc b/source/blender/draw/engines/eevee/eevee_bloom.cc index 8e3026de8c7..6c50879f2ad 100644 --- a/source/blender/draw/engines/eevee/eevee_bloom.cc +++ b/source/blender/draw/engines/eevee/eevee_bloom.cc @@ -59,7 +59,7 @@ int EEVEE_bloom_init(EEVEE_ViewLayerData * /*sldata*/, EEVEE_Data *vedata) effects->bloom_clamp = scene_eval->eevee.bloom_clamp; /* determine the iteration count */ - const float minDim = float(MIN2(blitsize[0], blitsize[1])); + const float minDim = float(std::min(blitsize[0], blitsize[1])); const float maxIter = (radius - 8.0f) + log(minDim) / log(2); const int maxIterInt = effects->bloom_iteration_len = int(maxIter); @@ -79,8 +79,8 @@ int EEVEE_bloom_init(EEVEE_ViewLayerData * /*sldata*/, EEVEE_Data *vedata) texsize[0] /= 2; texsize[1] /= 2; - texsize[0] = MAX2(texsize[0], 2); - texsize[1] = MAX2(texsize[1], 2); + texsize[0] = std::max(texsize[0], 2); + texsize[1] = std::max(texsize[1], 2); effects->downsamp_texel_size[i][0] = 1.0f / float(texsize[0]); effects->downsamp_texel_size[i][1] = 1.0f / float(texsize[1]); @@ -101,8 +101,8 @@ int EEVEE_bloom_init(EEVEE_ViewLayerData * /*sldata*/, EEVEE_Data *vedata) texsize[0] /= 2; texsize[1] /= 2; - texsize[0] = MAX2(texsize[0], 2); - texsize[1] = MAX2(texsize[1], 2); + texsize[0] = std::max(texsize[0], 2); + texsize[1] = std::max(texsize[1], 2); eGPUTextureUsage upsample_usage = GPU_TEXTURE_USAGE_SHADER_READ | GPU_TEXTURE_USAGE_ATTACHMENT | diff --git a/source/blender/draw/engines/eevee/eevee_engine.cc b/source/blender/draw/engines/eevee/eevee_engine.cc index 3e19ccdc928..35de9d74b78 100644 --- a/source/blender/draw/engines/eevee/eevee_engine.cc +++ b/source/blender/draw/engines/eevee/eevee_engine.cc @@ -223,7 +223,7 @@ static void eevee_draw_scene(void *vedata) if (DRW_state_is_image_render()) { const DRWContextState *draw_ctx = DRW_context_state_get(); const Scene *scene = draw_ctx->scene; - loop_len = MAX2(1, scene->eevee.taa_samples); + loop_len = std::max(1, scene->eevee.taa_samples); } if (stl->effects->bypass_drawing) { diff --git a/source/blender/draw/engines/eevee/eevee_lightcache.cc b/source/blender/draw/engines/eevee/eevee_lightcache.cc index 94942f165fa..1ff2ef4a686 100644 --- a/source/blender/draw/engines/eevee/eevee_lightcache.cc +++ b/source/blender/draw/engines/eevee/eevee_lightcache.cc @@ -276,7 +276,7 @@ static void irradiance_pool_size_get(int visibility_size, int total_samples, int (visibility_size / IRRADIANCE_SAMPLE_SIZE_Y); /* The irradiance itself take one layer, hence the +1 */ - int layer_count = MIN2(irr_per_vis + 1, IRRADIANCE_MAX_POOL_LAYER); + int layer_count = std::min(irr_per_vis + 1, IRRADIANCE_MAX_POOL_LAYER); int texel_count = int(ceilf(float(total_samples) / float(layer_count - 1))); r_size[0] = visibility_size * diff --git a/source/blender/draw/engines/eevee_next/eevee_instance.cc b/source/blender/draw/engines/eevee_next/eevee_instance.cc index df7a057be55..8dae3eb3ac5 100644 --- a/source/blender/draw/engines/eevee_next/eevee_instance.cc +++ b/source/blender/draw/engines/eevee_next/eevee_instance.cc @@ -196,6 +196,7 @@ void Instance::object_sync(Object *ob) OB_VOLUME, OB_LAMP, OB_LIGHTPROBE); + const bool is_drawable_type = is_renderable_type && !ELEM(ob->type, OB_LAMP, OB_LIGHTPROBE); const int ob_visibility = DRW_object_visibility_in_active_context(ob); const bool partsys_is_visible = (ob_visibility & OB_VISIBLE_PARTICLES) != 0 && (ob->type == OB_MESH); @@ -208,15 +209,17 @@ void Instance::object_sync(Object *ob) /* TODO cleanup. */ ObjectRef ob_ref = DRW_object_ref_get(ob); - ResourceHandle res_handle = manager->resource_handle(ob_ref); - ObjectHandle &ob_handle = sync.sync_object(ob); + ResourceHandle res_handle = {0}; + if (is_drawable_type) { + res_handle = manager->resource_handle(ob_ref); + } if (partsys_is_visible && ob != DRW_context_state_get()->object_edit) { auto sync_hair = [&](ObjectHandle hair_handle, ModifierData &md, ParticleSystem &particle_sys) { ResourceHandle _res_handle = manager->resource_handle(float4x4(ob->object_to_world)); - sync.sync_curves(ob, hair_handle, _res_handle, &md, &particle_sys); + sync.sync_curves(ob, hair_handle, _res_handle, ob_ref, &md, &particle_sys); }; foreach_hair_particle_handle(ob, ob_handle, sync_hair); } @@ -238,7 +241,7 @@ void Instance::object_sync(Object *ob) sync.sync_volume(ob, ob_handle, res_handle); break; case OB_CURVES: - sync.sync_curves(ob, ob_handle, res_handle); + sync.sync_curves(ob, ob_handle, res_handle, ob_ref); break; case OB_GPENCIL_LEGACY: sync.sync_gpencil(ob, ob_handle, res_handle); diff --git a/source/blender/draw/engines/eevee_next/eevee_material.hh b/source/blender/draw/engines/eevee_next/eevee_material.hh index 439d8cb31a8..27c0c189fc9 100644 --- a/source/blender/draw/engines/eevee_next/eevee_material.hh +++ b/source/blender/draw/engines/eevee_next/eevee_material.hh @@ -69,19 +69,24 @@ enum eMaterialProbe { static inline void material_type_from_shader_uuid(uint64_t shader_uuid, eMaterialPipeline &pipeline_type, - eMaterialGeometry &geometry_type) + eMaterialGeometry &geometry_type, + bool &transparent_shadows) { const uint64_t geometry_mask = ((1u << 4u) - 1u); const uint64_t pipeline_mask = ((1u << 4u) - 1u); geometry_type = static_cast(shader_uuid & geometry_mask); pipeline_type = static_cast((shader_uuid >> 4u) & pipeline_mask); + transparent_shadows = (shader_uuid >> 8u) & 1u; } static inline uint64_t shader_uuid_from_material_type(eMaterialPipeline pipeline_type, - eMaterialGeometry geometry_type) + eMaterialGeometry geometry_type, + char blend_flags) { BLI_assert(geometry_type < (1 << 4)); - return geometry_type | (pipeline_type << 4); + BLI_assert(pipeline_type < (1 << 4)); + uchar transparent_shadows = blend_flags & MA_BL_TRANSPARENT_SHADOW ? 1 : 0; + return geometry_type | (pipeline_type << 4) | (transparent_shadows << 8); } ENUM_OPERATORS(eClosureBits, CLOSURE_AMBIENT_OCCLUSION) @@ -142,7 +147,7 @@ struct MaterialKey { MaterialKey(::Material *mat_, eMaterialGeometry geometry, eMaterialPipeline pipeline) : mat(mat_) { - options = shader_uuid_from_material_type(pipeline, geometry); + options = shader_uuid_from_material_type(pipeline, geometry, mat_->blend_flag); } uint64_t hash() const diff --git a/source/blender/draw/engines/eevee_next/eevee_shader.cc b/source/blender/draw/engines/eevee_next/eevee_shader.cc index d44e97fd485..4f8d9c3dca4 100644 --- a/source/blender/draw/engines/eevee_next/eevee_shader.cc +++ b/source/blender/draw/engines/eevee_next/eevee_shader.cc @@ -311,7 +311,8 @@ void ShaderModule::material_create_info_ammend(GPUMaterial *gpumat, GPUCodegenOu eMaterialPipeline pipeline_type; eMaterialGeometry geometry_type; - material_type_from_shader_uuid(shader_uuid, pipeline_type, geometry_type); + bool transparent_shadows; + material_type_from_shader_uuid(shader_uuid, pipeline_type, geometry_type, transparent_shadows); GPUCodegenOutput &codegen = *codegen_; ShaderCreateInfo &info = *reinterpret_cast(codegen.create_info); @@ -356,7 +357,9 @@ void ShaderModule::material_create_info_ammend(GPUMaterial *gpumat, GPUCodegenOu } if (GPU_material_flag_get(gpumat, GPU_MATFLAG_TRANSPARENT)) { - info.define("MAT_TRANSPARENT"); + if (pipeline_type != MAT_PIPE_SHADOW || transparent_shadows) { + info.define("MAT_TRANSPARENT"); + } /* Transparent material do not have any velocity specific pipeline. */ if (pipeline_type == MAT_PIPE_PREPASS_FORWARD_VELOCITY) { pipeline_type = MAT_PIPE_PREPASS_FORWARD; @@ -641,7 +644,8 @@ GPUMaterial *ShaderModule::material_shader_get(::Material *blender_mat, { bool is_volume = ELEM(pipeline_type, MAT_PIPE_VOLUME_MATERIAL, MAT_PIPE_VOLUME_OCCUPANCY); - uint64_t shader_uuid = shader_uuid_from_material_type(pipeline_type, geometry_type); + uint64_t shader_uuid = shader_uuid_from_material_type( + pipeline_type, geometry_type, blender_mat->blend_flag); return DRW_shader_from_material( blender_mat, nodetree, shader_uuid, is_volume, deferred_compilation, codegen_callback, this); @@ -656,7 +660,7 @@ GPUMaterial *ShaderModule::world_shader_get(::World *blender_world, eMaterialGeometry geometry_type = is_volume ? MAT_GEOM_VOLUME_WORLD : MAT_GEOM_WORLD; - uint64_t shader_uuid = shader_uuid_from_material_type(pipeline_type, geometry_type); + uint64_t shader_uuid = shader_uuid_from_material_type(pipeline_type, geometry_type, 0); return DRW_shader_from_world( blender_world, nodetree, shader_uuid, is_volume, defer_compilation, codegen_callback, this); @@ -671,7 +675,7 @@ GPUMaterial *ShaderModule::material_shader_get(const char *name, eMaterialGeometry geometry_type, bool is_lookdev) { - uint64_t shader_uuid = shader_uuid_from_material_type(pipeline_type, geometry_type); + uint64_t shader_uuid = shader_uuid_from_material_type(pipeline_type, geometry_type, 0); bool is_volume = ELEM(pipeline_type, MAT_PIPE_VOLUME_MATERIAL, MAT_PIPE_VOLUME_OCCUPANCY); diff --git a/source/blender/draw/engines/eevee_next/eevee_shadow.cc b/source/blender/draw/engines/eevee_next/eevee_shadow.cc index 66df398a22b..1244b091656 100644 --- a/source/blender/draw/engines/eevee_next/eevee_shadow.cc +++ b/source/blender/draw/engines/eevee_next/eevee_shadow.cc @@ -321,7 +321,7 @@ void ShadowPunctual::compute_projection_boundaries(float light_radius, * TODO(fclem): Explain derivation. */ float cos_alpha = shadow_radius / max_lit_distance; - float sin_alpha = sqrt((1.0f - math::square(cos_alpha))); + float sin_alpha = sqrt(1.0f - math::square(cos_alpha)); float near_shift = M_SQRT2 * shadow_radius * 0.5f * (sin_alpha - cos_alpha); float side_shift = M_SQRT2 * shadow_radius * 0.5f * (sin_alpha + cos_alpha); float origin_shift = M_SQRT2 * shadow_radius / (sin_alpha - cos_alpha); @@ -345,7 +345,7 @@ void ShadowPunctual::end_sync(Light &light, float lod_bias) light_radius_, light_radius_ * softness_factor_, max_distance_, near, far, side); /* Shift shadow map origin for area light to avoid clipping nearby geometry. */ - float shift = (is_area_light(light.type)) ? near : 0.0f; + float shift = is_area_light(light.type) ? near : 0.0f; float4x4 obmat_tmp = light.object_mat; @@ -893,11 +893,12 @@ void ShadowModule::begin_sync() } } -void ShadowModule::sync_object(const ObjectHandle &handle, +void ShadowModule::sync_object(const Object *ob, + const ObjectHandle &handle, const ResourceHandle &resource_handle, - bool is_shadow_caster, bool is_alpha_blend) { + bool is_shadow_caster = !(ob->visibility_flag & OB_HIDE_SHADOW); if (!is_shadow_caster && !is_alpha_blend) { return; } diff --git a/source/blender/draw/engines/eevee_next/eevee_shadow.hh b/source/blender/draw/engines/eevee_next/eevee_shadow.hh index 81a88e54975..4808df6d01e 100644 --- a/source/blender/draw/engines/eevee_next/eevee_shadow.hh +++ b/source/blender/draw/engines/eevee_next/eevee_shadow.hh @@ -328,9 +328,9 @@ class ShadowModule { void begin_sync(); /** Register a shadow caster or receiver. */ - void sync_object(const ObjectHandle &handle, + void sync_object(const Object *ob, + const ObjectHandle &handle, const ResourceHandle &resource_handle, - bool is_shadow_caster, bool is_alpha_blend); void end_sync(); diff --git a/source/blender/draw/engines/eevee_next/eevee_sync.cc b/source/blender/draw/engines/eevee_next/eevee_sync.cc index 5b179c963c4..a633a729b04 100644 --- a/source/blender/draw/engines/eevee_next/eevee_sync.cc +++ b/source/blender/draw/engines/eevee_next/eevee_sync.cc @@ -140,8 +140,8 @@ void SyncModule::sync_mesh(Object *ob, return; } - bool is_shadow_caster = false; bool is_alpha_blend = false; + float inflate_bounds = 0.0f; for (auto i : material_array.gpu_materials.index_range()) { GPUBatch *geom = mat_geom[i]; if (geom == nullptr) { @@ -173,16 +173,23 @@ void SyncModule::sync_mesh(Object *ob, geometry_call(material.reflection_probe_prepass.sub_pass, geom, res_handle); geometry_call(material.reflection_probe_shading.sub_pass, geom, res_handle); - is_shadow_caster = is_shadow_caster || material.shadow.sub_pass != nullptr; is_alpha_blend = is_alpha_blend || material.is_alpha_blend_transparent; ::Material *mat = GPU_material_get_material(gpu_material); inst_.cryptomatte.sync_material(mat); + + if (GPU_material_has_displacement_output(gpu_material)) { + inflate_bounds = math::max(inflate_bounds, mat->inflate_bounds); + } + } + + if (inflate_bounds != 0.0f) { + inst_.manager->update_handle_bounds(res_handle, ob_ref, inflate_bounds); } inst_.manager->extract_object_attributes(res_handle, ob_ref, material_array.gpu_materials); - inst_.shadows.sync_object(ob_handle, res_handle, is_shadow_caster, is_alpha_blend); + inst_.shadows.sync_object(ob, ob_handle, res_handle, is_alpha_blend); inst_.cryptomatte.sync_object(ob, res_handle); } @@ -204,19 +211,11 @@ bool SyncModule::sync_sculpt(Object *ob, return false; } - /* Use a valid bounding box. The PBVH module already does its own culling, but a valid */ - /* bounding box is still needed for directional shadow tile-map bounds computation. */ - float3 min, max; - BKE_pbvh_bounding_box(ob_ref.object->sculpt->pbvh, min, max); - float3 center = (min + max) * 0.5; - float3 half_extent = max - center; - res_handle = inst_.manager->resource_handle(ob_ref, nullptr, ¢er, &half_extent); - bool has_motion = false; MaterialArray &material_array = inst_.materials.material_array_get(ob, has_motion); - bool is_shadow_caster = false; bool is_alpha_blend = false; + float inflate_bounds = 0.0f; for (SculptBatch &batch : sculpt_batches_per_material_get(ob_ref.object, material_array.gpu_materials)) { @@ -249,17 +248,29 @@ bool SyncModule::sync_sculpt(Object *ob, geometry_call(material.reflection_probe_prepass.sub_pass, geom, res_handle); geometry_call(material.reflection_probe_shading.sub_pass, geom, res_handle); - is_shadow_caster = is_shadow_caster || material.shadow.sub_pass != nullptr; is_alpha_blend = is_alpha_blend || material.is_alpha_blend_transparent; GPUMaterial *gpu_material = material_array.gpu_materials[batch.material_slot]; ::Material *mat = GPU_material_get_material(gpu_material); inst_.cryptomatte.sync_material(mat); + + if (GPU_material_has_displacement_output(gpu_material)) { + inflate_bounds = math::max(inflate_bounds, mat->inflate_bounds); + } } + /* Use a valid bounding box. The PBVH module already does its own culling, but a valid */ + /* bounding box is still needed for directional shadow tile-map bounds computation. */ + float3 min, max; + BKE_pbvh_bounding_box(ob_ref.object->sculpt->pbvh, min, max); + float3 center = (min + max) * 0.5; + float3 half_extent = max - center; + half_extent += inflate_bounds; + inst_.manager->update_handle_bounds(res_handle, center, half_extent); + inst_.manager->extract_object_attributes(res_handle, ob_ref, material_array.gpu_materials); - inst_.shadows.sync_object(ob_handle, res_handle, is_shadow_caster, is_alpha_blend); + inst_.shadows.sync_object(ob, ob_handle, res_handle, is_alpha_blend); inst_.cryptomatte.sync_object(ob, res_handle); return true; @@ -274,7 +285,7 @@ bool SyncModule::sync_sculpt(Object *ob, void SyncModule::sync_point_cloud(Object *ob, ObjectHandle &ob_handle, ResourceHandle res_handle, - const ObjectRef & /*ob_ref*/) + const ObjectRef &ob_ref) { const int material_slot = POINTCLOUD_MATERIAL_NR; @@ -322,9 +333,13 @@ void SyncModule::sync_point_cloud(Object *ob, ::Material *mat = GPU_material_get_material(gpu_material); inst_.cryptomatte.sync_material(mat); - bool is_caster = material.shadow.sub_pass != nullptr; bool is_alpha_blend = material.is_alpha_blend_transparent; - inst_.shadows.sync_object(ob_handle, res_handle, is_caster, is_alpha_blend); + + if (GPU_material_has_displacement_output(gpu_material) && mat->inflate_bounds != 0.0f) { + inst_.manager->update_handle_bounds(res_handle, ob_ref, mat->inflate_bounds); + } + + inst_.shadows.sync_object(ob, ob_handle, res_handle, is_alpha_blend); } /** \} */ @@ -486,9 +501,8 @@ void SyncModule::sync_gpencil(Object *ob, ObjectHandle &ob_handle, ResourceHandl gpencil_drawcall_flush(iter); - bool is_caster = true; /* TODO material.shadow.sub_pass. */ bool is_alpha_blend = true; /* TODO material.is_alpha_blend. */ - inst_.shadows.sync_object(ob_handle, res_handle, is_caster, is_alpha_blend); + inst_.shadows.sync_object(ob, ob_handle, res_handle, is_alpha_blend); } /** \} */ @@ -500,6 +514,7 @@ void SyncModule::sync_gpencil(Object *ob, ObjectHandle &ob_handle, ResourceHandl void SyncModule::sync_curves(Object *ob, ObjectHandle &ob_handle, ResourceHandle res_handle, + const ObjectRef &ob_ref, ModifierData *modifier_data, ParticleSystem *particle_sys) { @@ -557,9 +572,13 @@ void SyncModule::sync_curves(Object *ob, ::Material *mat = GPU_material_get_material(gpu_material); inst_.cryptomatte.sync_material(mat); - bool is_caster = material.shadow.sub_pass != nullptr; bool is_alpha_blend = material.is_alpha_blend_transparent; - inst_.shadows.sync_object(ob_handle, res_handle, is_caster, is_alpha_blend); + + if (GPU_material_has_displacement_output(gpu_material) && mat->inflate_bounds != 0.0f) { + inst_.manager->update_handle_bounds(res_handle, ob_ref, mat->inflate_bounds); + } + + inst_.shadows.sync_object(ob, ob_handle, res_handle, is_alpha_blend); } /** \} */ diff --git a/source/blender/draw/engines/eevee_next/eevee_sync.hh b/source/blender/draw/engines/eevee_next/eevee_sync.hh index e455b6b50fc..cdaf46777ab 100644 --- a/source/blender/draw/engines/eevee_next/eevee_sync.hh +++ b/source/blender/draw/engines/eevee_next/eevee_sync.hh @@ -161,6 +161,7 @@ class SyncModule { void sync_curves(Object *ob, ObjectHandle &ob_handle, ResourceHandle res_handle, + const ObjectRef &ob_ref, ModifierData *modifier_data = nullptr, ParticleSystem *particle_sys = nullptr); void sync_light_probe(Object *ob, ObjectHandle &ob_handle); diff --git a/source/blender/draw/engines/eevee_next/shaders/eevee_shadow_page_defrag_comp.glsl b/source/blender/draw/engines/eevee_next/shaders/eevee_shadow_page_defrag_comp.glsl index 4e8e448e596..3a1d292bfc2 100644 --- a/source/blender/draw/engines/eevee_next/shaders/eevee_shadow_page_defrag_comp.glsl +++ b/source/blender/draw/engines/eevee_next/shaders/eevee_shadow_page_defrag_comp.glsl @@ -24,11 +24,14 @@ const uint max_page = SHADOW_MAX_PAGE; void find_first_valid(inout uint src, uint dst) { - for (; src < dst; src++) { - if (pages_cached_buf[src % max_page].x != uint(-1)) { + for (uint i = src; i < dst; i++) { + if (pages_cached_buf[i % max_page].x != uint(-1)) { + src = i; return; } } + + src = dst; } void page_cached_free(uint page_index) diff --git a/source/blender/draw/engines/workbench/workbench_mesh_passes.cc b/source/blender/draw/engines/workbench/workbench_mesh_passes.cc index 1271a28707e..18b0e5bdadb 100644 --- a/source/blender/draw/engines/workbench/workbench_mesh_passes.cc +++ b/source/blender/draw/engines/workbench/workbench_mesh_passes.cc @@ -91,7 +91,11 @@ PassMain::Sub &MeshPass::get_subpass( /* TODO(@pragma37): This setting should be exposed on the user side, * either as a global parameter (and set it here) * or by reading the Material Clipping Threshold (and set it per material) */ - sub_pass->push_constant("imageTransparencyCutoff", 0.1f); + float alpha_cutoff = 0.1f; + if (ELEM(image->alpha_mode, IMA_ALPHA_IGNORE, IMA_ALPHA_CHANNEL_PACKED)) { + alpha_cutoff = -FLT_MAX; + } + sub_pass->push_constant("imageTransparencyCutoff", alpha_cutoff); return sub_pass; }; diff --git a/source/blender/draw/engines/workbench/workbench_volume.cc b/source/blender/draw/engines/workbench/workbench_volume.cc index 0376c006682..e3f09c66bc3 100644 --- a/source/blender/draw/engines/workbench/workbench_volume.cc +++ b/source/blender/draw/engines/workbench/workbench_volume.cc @@ -15,7 +15,7 @@ namespace blender::workbench { VolumePass::~VolumePass() { GPUShader **sh_p = &shaders_[0][0][0][0]; - const int n = sizeof(shaders_) / sizeof(*shaders_); + const int n = ARRAY_SIZE(shaders_); for (int i = 0; i < n; i++, sh_p++) { GPUShader *sh = *sh_p; if (sh) { diff --git a/source/blender/draw/intern/attribute_convert.cc b/source/blender/draw/intern/attribute_convert.cc new file mode 100644 index 00000000000..45e4e2cf4af --- /dev/null +++ b/source/blender/draw/intern/attribute_convert.cc @@ -0,0 +1,57 @@ +/* SPDX-FileCopyrightText: 2005 Blender Authors + * + * SPDX-License-Identifier: GPL-2.0-or-later */ + +/** \file + * \ingroup gpu + */ + +#include "BLI_array_utils.hh" + +#include "BKE_attribute_math.hh" + +#include "GPU_vertex_buffer.h" + +#include "attribute_convert.hh" + +namespace blender::draw { + +GPUVertFormat init_format_for_attribute(const eCustomDataType data_type, + const StringRefNull vbo_name) +{ + GPUVertFormat format{}; + bke::attribute_math::convert_to_static_type(data_type, [&](auto dummy) { + using T = decltype(dummy); + using Converter = AttributeConverter; + GPU_vertformat_attr_add(&format, + vbo_name.c_str(), + Converter::gpu_component_type, + Converter::gpu_component_len, + Converter::gpu_fetch_mode); + }); + return format; +} + +void vertbuf_data_extract_direct(const GSpan attribute, GPUVertBuf &vbo) +{ + bke::attribute_math::convert_to_static_type(attribute.type(), [&](auto dummy) { + using T = decltype(dummy); + using Converter = AttributeConverter; + using VBOType = typename Converter::VBOType; + const Span src = attribute.typed(); + MutableSpan data(static_cast(GPU_vertbuf_get_data(&vbo)), + attribute.size()); + if constexpr (std::is_same_v) { + array_utils::copy(src, data); + } + else { + threading::parallel_for(src.index_range(), 8192, [&](const IndexRange range) { + for (const int i : range) { + data[i] = Converter::convert(src[i]); + } + }); + } + }); +} + +} // namespace blender::draw diff --git a/source/blender/draw/intern/attribute_convert.hh b/source/blender/draw/intern/attribute_convert.hh new file mode 100644 index 00000000000..8beb3fb6171 --- /dev/null +++ b/source/blender/draw/intern/attribute_convert.hh @@ -0,0 +1,144 @@ +/* SPDX-FileCopyrightText: 2005 Blender Authors + * + * SPDX-License-Identifier: GPL-2.0-or-later */ + +/** \file + * \ingroup gpu + */ + +#include "BLI_color.hh" +#include "BLI_generic_span.hh" +#include "BLI_math_quaternion_types.hh" +#include "BLI_math_vector_types.hh" +#include "BLI_string_ref.hh" + +#include "DNA_customdata_types.h" /* #eCustomDataType. */ + +#include "GPU_vertex_format.h" + +/** + * Component length of 3 is used for scalars because implicit conversion is done by OpenGL from a + * scalar `s` will produce `vec4(s, 0, 0, 1)`. However, following the Blender convention, it should + * be `vec4(s, s, s, 1)`. + */ +constexpr int COMPONENT_LEN_SCALAR = 3; + +namespace blender::draw { + +/** + * Utility to convert from the type used in the attributes to the types for GPU vertex buffers. + */ +template struct AttributeConverter { + using VBOType = void; +}; + +template<> struct AttributeConverter { + using VBOType = VecBase; + static constexpr GPUVertCompType gpu_component_type = GPU_COMP_I32; + static constexpr int gpu_component_len = COMPONENT_LEN_SCALAR; + static constexpr GPUVertFetchMode gpu_fetch_mode = GPU_FETCH_INT_TO_FLOAT; + static VBOType convert(const bool &value) + { + return VBOType(value); + } +}; +template<> struct AttributeConverter { + using VBOType = VecBase; + static constexpr GPUVertCompType gpu_component_type = GPU_COMP_I32; + static constexpr int gpu_component_len = COMPONENT_LEN_SCALAR; + static constexpr GPUVertFetchMode gpu_fetch_mode = GPU_FETCH_INT_TO_FLOAT; + static VBOType convert(const int8_t &value) + { + return VecBase(value); + } +}; +template<> struct AttributeConverter { + using VBOType = VecBase; + static constexpr GPUVertCompType gpu_component_type = GPU_COMP_I32; + static constexpr int gpu_component_len = COMPONENT_LEN_SCALAR; + static constexpr GPUVertFetchMode gpu_fetch_mode = GPU_FETCH_INT_TO_FLOAT; + static VBOType convert(const int &value) + { + return int3(value); + } +}; +template<> struct AttributeConverter { + using VBOType = int2; + static constexpr GPUVertCompType gpu_component_type = GPU_COMP_I32; + static constexpr int gpu_component_len = 2; + static constexpr GPUVertFetchMode gpu_fetch_mode = GPU_FETCH_INT_TO_FLOAT; + static VBOType convert(const int2 &value) + { + return int2(value.x, value.y); + } +}; +template<> struct AttributeConverter { + using VBOType = VecBase; + static constexpr GPUVertCompType gpu_component_type = GPU_COMP_F32; + static constexpr int gpu_component_len = COMPONENT_LEN_SCALAR; + static constexpr GPUVertFetchMode gpu_fetch_mode = GPU_FETCH_FLOAT; + static VBOType convert(const float &value) + { + return VBOType(value); + } +}; +template<> struct AttributeConverter { + using VBOType = float2; + static constexpr GPUVertCompType gpu_component_type = GPU_COMP_F32; + static constexpr int gpu_component_len = 2; + static constexpr GPUVertFetchMode gpu_fetch_mode = GPU_FETCH_FLOAT; + static VBOType convert(const float2 &value) + { + return value; + } +}; +template<> struct AttributeConverter { + using VBOType = float3; + static constexpr GPUVertCompType gpu_component_type = GPU_COMP_F32; + static constexpr int gpu_component_len = 3; + static constexpr GPUVertFetchMode gpu_fetch_mode = GPU_FETCH_FLOAT; + static VBOType convert(const float3 &value) + { + return value; + } +}; +template<> struct AttributeConverter { + /* 16 bits are required to store the color in linear space without precision loss. */ + using VBOType = ushort4; + static constexpr GPUVertCompType gpu_component_type = GPU_COMP_U16; + static constexpr int gpu_component_len = 4; + static constexpr GPUVertFetchMode gpu_fetch_mode = GPU_FETCH_INT_TO_FLOAT_UNIT; + static VBOType convert(const ColorGeometry4b &value) + { + return {unit_float_to_ushort_clamp(BLI_color_from_srgb_table[value.r]), + unit_float_to_ushort_clamp(BLI_color_from_srgb_table[value.g]), + unit_float_to_ushort_clamp(BLI_color_from_srgb_table[value.b]), + ushort(value.a * 257)}; + } +}; +template<> struct AttributeConverter { + using VBOType = ColorGeometry4f; + static constexpr GPUVertCompType gpu_component_type = GPU_COMP_F32; + static constexpr int gpu_component_len = 4; + static constexpr GPUVertFetchMode gpu_fetch_mode = GPU_FETCH_FLOAT; + static VBOType convert(const ColorGeometry4f &value) + { + return value; + } +}; +template<> struct AttributeConverter { + using VBOType = float4; + static constexpr GPUVertCompType gpu_component_type = GPU_COMP_F32; + static constexpr int gpu_component_len = 4; + static constexpr GPUVertFetchMode gpu_fetch_mode = GPU_FETCH_FLOAT; + static VBOType convert(const math::Quaternion &value) + { + return float4(value.w, value.x, value.y, value.z); + } +}; + +GPUVertFormat init_format_for_attribute(eCustomDataType data_type, StringRefNull vbo_name); + +void vertbuf_data_extract_direct(GSpan attribute, GPUVertBuf &vbo); + +} // namespace blender::draw diff --git a/source/blender/draw/intern/draw_curves.cc b/source/blender/draw/intern/draw_curves.cc index 507254a0624..3af02fb3982 100644 --- a/source/blender/draw/intern/draw_curves.cc +++ b/source/blender/draw/intern/draw_curves.cc @@ -158,7 +158,7 @@ static void drw_curves_cache_update_compute(CurvesEvalCache *cache, const int max_strands_per_call = GPU_max_work_group_count(0); int strands_start = 0; while (strands_start < strands_len) { - int batch_strands_len = MIN2(strands_len - strands_start, max_strands_per_call); + int batch_strands_len = std::min(strands_len - strands_start, max_strands_per_call); DRWShadingGroup *subgroup = DRW_shgroup_create_sub(shgrp); DRW_shgroup_uniform_int_copy(subgroup, "hairStrandOffset", strands_start); DRW_shgroup_call_compute(subgroup, batch_strands_len, cache->final[subdiv].strands_res, 1); @@ -509,7 +509,7 @@ void DRW_curves_update() GPUFrameBuffer *temp_fb = nullptr; GPUFrameBuffer *prev_fb = nullptr; if (GPU_type_matches_ex(GPU_DEVICE_ANY, GPU_OS_MAC, GPU_DRIVER_ANY, GPU_BACKEND_METAL)) { - if (!(GPU_compute_shader_support())) { + if (!GPU_compute_shader_support()) { prev_fb = GPU_framebuffer_active_get(); char errorOut[256]; /* if the frame-buffer is invalid we need a dummy frame-buffer to be bound. */ diff --git a/source/blender/draw/intern/draw_hair.cc b/source/blender/draw/intern/draw_hair.cc index 729dfb97931..1c4c6ff0e90 100644 --- a/source/blender/draw/intern/draw_hair.cc +++ b/source/blender/draw/intern/draw_hair.cc @@ -130,7 +130,7 @@ static void drw_hair_particle_cache_update_compute(ParticleHairCache *cache, con const int max_strands_per_call = GPU_max_work_group_count(0); int strands_start = 0; while (strands_start < strands_len) { - int batch_strands_len = MIN2(strands_len - strands_start, max_strands_per_call); + int batch_strands_len = std::min(strands_len - strands_start, max_strands_per_call); DRWShadingGroup *subgroup = DRW_shgroup_create_sub(shgrp); DRW_shgroup_uniform_int_copy(subgroup, "hairStrandOffset", strands_start); DRW_shgroup_call_compute(subgroup, batch_strands_len, cache->final[subdiv].strands_res, 1); diff --git a/source/blender/draw/intern/draw_manager.hh b/source/blender/draw/intern/draw_manager.hh index efb8732023e..30e871554b8 100644 --- a/source/blender/draw/intern/draw_manager.hh +++ b/source/blender/draw/intern/draw_manager.hh @@ -119,7 +119,7 @@ class Manager { /** * Create a new resource handle for the given object. */ - ResourceHandle resource_handle(const ObjectRef ref); + ResourceHandle resource_handle(const ObjectRef ref, float inflate_bounds = 0.0f); /** * Create a new resource handle for the given object, but optionally override model matrix and * bounds. @@ -142,6 +142,15 @@ class Manager { const float3 &bounds_center, const float3 &bounds_half_extent); + /** Update the bounds of an already created handle. */ + void update_handle_bounds(ResourceHandle handle, + const ObjectRef ref, + float inflate_bounds = 0.0f); + /** Update the bounds of an already created handle. */ + void update_handle_bounds(ResourceHandle handle, + const float3 &bounds_center, + const float3 &bounds_half_extent); + /** * Populate additional per resource data on demand. */ @@ -206,11 +215,11 @@ class Manager { void sync_layer_attributes(); }; -inline ResourceHandle Manager::resource_handle(const ObjectRef ref) +inline ResourceHandle Manager::resource_handle(const ObjectRef ref, float inflate_bounds) { bool is_active_object = (ref.dupli_object ? ref.dupli_parent : ref.object) == object_active; matrix_buf.current().get_or_resize(resource_len_).sync(*ref.object); - bounds_buf.current().get_or_resize(resource_len_).sync(*ref.object); + bounds_buf.current().get_or_resize(resource_len_).sync(*ref.object, inflate_bounds); infos_buf.current().get_or_resize(resource_len_).sync(ref, is_active_object); return ResourceHandle(resource_len_++, (ref.object->transflag & OB_NEG_SCALE) != 0); } @@ -255,6 +264,20 @@ inline ResourceHandle Manager::resource_handle(const float4x4 &model_matrix, return ResourceHandle(resource_len_++, false); } +inline void Manager::update_handle_bounds(ResourceHandle handle, + const ObjectRef ref, + float inflate_bounds) +{ + bounds_buf.current()[handle.resource_index()].sync(*ref.object, inflate_bounds); +} + +inline void Manager::update_handle_bounds(ResourceHandle handle, + const float3 &bounds_center, + const float3 &bounds_half_extent) +{ + bounds_buf.current()[handle.resource_index()].sync(bounds_center, bounds_half_extent); +} + inline void Manager::extract_object_attributes(ResourceHandle handle, const ObjectRef &ref, Span materials) diff --git a/source/blender/draw/intern/draw_manager_profiling.cc b/source/blender/draw/intern/draw_manager_profiling.cc index fbed558e0e1..cb4cc3bdce9 100644 --- a/source/blender/draw/intern/draw_manager_profiling.cc +++ b/source/blender/draw/intern/draw_manager_profiling.cc @@ -337,8 +337,8 @@ void DRW_stats_draw(const rcti *rect) } /* avoid very long number */ - time_ms = MIN2(time_ms, 999.0); - time_percent = MIN2(time_percent, 100.0); + time_ms = std::min(time_ms, 999.0); + time_percent = std::min(time_percent, 100.0); SNPRINTF(stat_string, "%s", timer->name); draw_stat(rect, 0 + timer->lvl, v, stat_string, sizeof(stat_string)); diff --git a/source/blender/draw/intern/draw_pbvh.cc b/source/blender/draw/intern/draw_pbvh.cc index f96d5151277..fab5fa31b52 100644 --- a/source/blender/draw/intern/draw_pbvh.cc +++ b/source/blender/draw/intern/draw_pbvh.cc @@ -50,6 +50,7 @@ #include "DRW_engine.h" #include "DRW_pbvh.hh" +#include "attribute_convert.hh" #include "bmesh.h" #include "draw_pbvh.h" #include "gpu_private.h" @@ -57,10 +58,7 @@ #define MAX_PBVH_BATCH_KEY 512 #define MAX_PBVH_VBOS 16 -using blender::char3; -using blender::float2; using blender::float3; -using blender::float4; using blender::FunctionRef; using blender::IndexRange; using blender::Map; @@ -72,131 +70,8 @@ using blender::StringRef; using blender::StringRefNull; using blender::uchar3; using blender::uchar4; -using blender::ushort3; -using blender::ushort4; using blender::Vector; -/** - * Component length of 3 is used for scalars because implicit conversion is done by OpenGL from a - * scalar `s` will produce `vec4(s, 0, 0, 1)`. However, following the Blender convention, it should - * be `vec4(s, s, s, 1)`. - */ -constexpr int COMPONENT_LEN_SCALAR = 3; - -namespace blender::draw { - -/** Similar to #AttributeTypeConverter. */ -template struct AttributeConverter { - using VBOT = void; -}; - -template<> struct AttributeConverter { - using VBOT = VecBase; - static constexpr GPUVertCompType gpu_component_type = GPU_COMP_I32; - static constexpr int gpu_component_len = COMPONENT_LEN_SCALAR; - static constexpr GPUVertFetchMode gpu_fetch_mode = GPU_FETCH_INT_TO_FLOAT; - static VBOT convert(const bool &value) - { - return VBOT(value); - } -}; -template<> struct AttributeConverter { - using VBOT = VecBase; - static constexpr GPUVertCompType gpu_component_type = GPU_COMP_I32; - static constexpr int gpu_component_len = COMPONENT_LEN_SCALAR; - static constexpr GPUVertFetchMode gpu_fetch_mode = GPU_FETCH_INT_TO_FLOAT; - static VBOT convert(const int8_t &value) - { - return VecBase(value); - } -}; -template<> struct AttributeConverter { - using VBOT = VecBase; - static constexpr GPUVertCompType gpu_component_type = GPU_COMP_I32; - static constexpr int gpu_component_len = COMPONENT_LEN_SCALAR; - static constexpr GPUVertFetchMode gpu_fetch_mode = GPU_FETCH_INT_TO_FLOAT; - static VBOT convert(const int &value) - { - return int3(value); - } -}; -template<> struct AttributeConverter { - using VBOT = int2; - static constexpr GPUVertCompType gpu_component_type = GPU_COMP_I32; - static constexpr int gpu_component_len = 2; - static constexpr GPUVertFetchMode gpu_fetch_mode = GPU_FETCH_INT_TO_FLOAT; - static VBOT convert(const int2 &value) - { - return int2(value.x, value.y); - } -}; -template<> struct AttributeConverter { - using VBOT = VecBase; - static constexpr GPUVertCompType gpu_component_type = GPU_COMP_F32; - static constexpr int gpu_component_len = COMPONENT_LEN_SCALAR; - static constexpr GPUVertFetchMode gpu_fetch_mode = GPU_FETCH_FLOAT; - static VBOT convert(const float &value) - { - return VBOT(value); - } -}; -template<> struct AttributeConverter { - using VBOT = float2; - static constexpr GPUVertCompType gpu_component_type = GPU_COMP_F32; - static constexpr int gpu_component_len = 2; - static constexpr GPUVertFetchMode gpu_fetch_mode = GPU_FETCH_FLOAT; - static VBOT convert(const float2 &value) - { - return value; - } -}; -template<> struct AttributeConverter { - using VBOT = float3; - static constexpr GPUVertCompType gpu_component_type = GPU_COMP_F32; - static constexpr int gpu_component_len = 3; - static constexpr GPUVertFetchMode gpu_fetch_mode = GPU_FETCH_FLOAT; - static VBOT convert(const float3 &value) - { - return value; - } -}; -template<> struct AttributeConverter { - /* 16 bits are required to store the color in linear space without precision loss. */ - using VBOT = ushort4; - static constexpr GPUVertCompType gpu_component_type = GPU_COMP_U16; - static constexpr int gpu_component_len = 4; - static constexpr GPUVertFetchMode gpu_fetch_mode = GPU_FETCH_INT_TO_FLOAT_UNIT; - static VBOT convert(const ColorGeometry4b &value) - { - return {unit_float_to_ushort_clamp(BLI_color_from_srgb_table[value.r]), - unit_float_to_ushort_clamp(BLI_color_from_srgb_table[value.g]), - unit_float_to_ushort_clamp(BLI_color_from_srgb_table[value.b]), - ushort(value.a * 257)}; - } -}; -template<> struct AttributeConverter { - using VBOT = ColorGeometry4f; - static constexpr GPUVertCompType gpu_component_type = GPU_COMP_F32; - static constexpr int gpu_component_len = 4; - static constexpr GPUVertFetchMode gpu_fetch_mode = GPU_FETCH_FLOAT; - static VBOT convert(const ColorGeometry4f &value) - { - return value; - } -}; -template<> struct AttributeConverter { - using VBOT = float4; - static constexpr GPUVertCompType gpu_component_type = GPU_COMP_F32; - static constexpr int gpu_component_len = 4; - static constexpr GPUVertFetchMode gpu_fetch_mode = GPU_FETCH_FLOAT; - static VBOT convert(const blender::math::Quaternion &value) - { - return float4(value.w, value.x, value.y, value.z); - } -}; - -} // namespace blender::draw - static bool pbvh_attr_supported(int type, const eAttrDomain domain) { using namespace blender; @@ -211,8 +86,8 @@ static bool pbvh_attr_supported(int type, const eAttrDomain domain) bke::attribute_math::convert_to_static_type(eCustomDataType(type), [&](auto dummy) { using T = decltype(dummy); using Converter = draw::AttributeConverter; - using VBOT = typename Converter::VBOT; - if constexpr (!std::is_void_v) { + using VBOType = typename Converter::VBOType; + if constexpr (!std::is_void_v) { type_supported = true; } }); @@ -257,13 +132,13 @@ template void extract_data_vert_faces(const PBVH_GPU_Args &args, const Span attribute, GPUVertBuf &vbo) { using Converter = blender::draw::AttributeConverter; - using VBOT = typename Converter::VBOT; + using VBOType = typename Converter::VBOType; const Span corner_verts = args.corner_verts; const Span looptris = args.mlooptri; const Span looptri_faces = args.looptri_faces; const bool *hide_poly = args.hide_poly; - VBOT *data = static_cast(GPU_vertbuf_get_data(&vbo)); + VBOType *data = static_cast(GPU_vertbuf_get_data(&vbo)); for (const int looptri_i : args.prim_indices) { if (hide_poly && hide_poly[looptri_faces[looptri_i]]) { continue; @@ -280,12 +155,12 @@ template void extract_data_face_faces(const PBVH_GPU_Args &args, const Span attribute, GPUVertBuf &vbo) { using Converter = blender::draw::AttributeConverter; - using VBOT = typename Converter::VBOT; + using VBOType = typename Converter::VBOType; const Span looptri_faces = args.looptri_faces; const bool *hide_poly = args.hide_poly; - VBOT *data = static_cast(GPU_vertbuf_get_data(&vbo)); + VBOType *data = static_cast(GPU_vertbuf_get_data(&vbo)); for (const int looptri_i : args.prim_indices) { const int face = looptri_faces[looptri_i]; if (hide_poly && hide_poly[face]) { @@ -300,13 +175,13 @@ template void extract_data_corner_faces(const PBVH_GPU_Args &args, const Span attribute, GPUVertBuf &vbo) { using Converter = blender::draw::AttributeConverter; - using VBOT = typename Converter::VBOT; + using VBOType = typename Converter::VBOType; const Span looptris = args.mlooptri; const Span looptri_faces = args.looptri_faces; const bool *hide_poly = args.hide_poly; - VBOT *data = static_cast(GPU_vertbuf_get_data(&vbo)); + VBOType *data = static_cast(GPU_vertbuf_get_data(&vbo)); for (const int looptri_i : args.prim_indices) { if (hide_poly && hide_poly[looptri_faces[looptri_i]]) { continue; @@ -338,8 +213,8 @@ template void extract_data_vert_bmesh(const PBVH_GPU_Args &args, const int cd_offset, GPUVertBuf &vbo) { using Converter = blender::draw::AttributeConverter; - using VBOT = typename Converter::VBOT; - VBOT *data = static_cast(GPU_vertbuf_get_data(&vbo)); + using VBOType = typename Converter::VBOType; + VBOType *data = static_cast(GPU_vertbuf_get_data(&vbo)); for (const BMFace *f : *args.bm_faces) { if (BM_elem_flag_test(f, BM_ELEM_HIDDEN)) { @@ -359,8 +234,8 @@ template void extract_data_face_bmesh(const PBVH_GPU_Args &args, const int cd_offset, GPUVertBuf &vbo) { using Converter = blender::draw::AttributeConverter; - using VBOT = typename Converter::VBOT; - VBOT *data = static_cast(GPU_vertbuf_get_data(&vbo)); + using VBOType = typename Converter::VBOType; + VBOType *data = static_cast(GPU_vertbuf_get_data(&vbo)); for (const BMFace *f : *args.bm_faces) { if (BM_elem_flag_test(f, BM_ELEM_HIDDEN)) { @@ -375,8 +250,8 @@ template void extract_data_corner_bmesh(const PBVH_GPU_Args &args, const int cd_offset, GPUVertBuf &vbo) { using Converter = blender::draw::AttributeConverter; - using VBOT = typename Converter::VBOT; - VBOT *data = static_cast(GPU_vertbuf_get_data(&vbo)); + using VBOType = typename Converter::VBOType; + VBOType *data = static_cast(GPU_vertbuf_get_data(&vbo)); for (const BMFace *f : *args.bm_faces) { if (BM_elem_flag_test(f, BM_ELEM_HIDDEN)) { @@ -736,10 +611,10 @@ struct PBVHBatches { bke::attribute_math::convert_to_static_type(eCustomDataType(vbo.type), [&](auto dummy) { using T = decltype(dummy); using Converter = draw::AttributeConverter; - using VBOT = typename Converter::VBOT; - std::fill_n(static_cast(GPU_vertbuf_get_data(vbo.vert_buf)), + using VBOType = typename Converter::VBOType; + std::fill_n(static_cast(GPU_vertbuf_get_data(vbo.vert_buf)), GPU_vertbuf_get_vertex_len(vbo.vert_buf), - VBOT()); + VBOType()); }); } } @@ -1094,8 +969,7 @@ struct PBVHBatches { PBVHVbo vbo(domain, type, name); GPUVertFormat format; - bool need_aliases = !ELEM( - type, CD_PBVH_CO_TYPE, CD_PBVH_NO_TYPE, CD_PBVH_FSET_TYPE, CD_PBVH_MASK_TYPE); + bool need_aliases = false; GPU_vertformat_clear(&format); @@ -1112,15 +986,7 @@ struct PBVHBatches { GPU_vertformat_attr_add(&format, "msk", GPU_COMP_F32, 1, GPU_FETCH_FLOAT); } else { - bke::attribute_math::convert_to_static_type(eCustomDataType(type), [&](auto dummy) { - using T = decltype(dummy); - using Converter = draw::AttributeConverter; - GPU_vertformat_attr_add(&format, - "data", - Converter::gpu_component_type, - Converter::gpu_component_len, - Converter::gpu_fetch_mode); - }); + format = draw::init_format_for_attribute(eCustomDataType(type), "data"); need_aliases = true; } diff --git a/source/blender/draw/intern/draw_resource.hh b/source/blender/draw/intern/draw_resource.hh index b8c5471d92c..5821ef65d6b 100644 --- a/source/blender/draw/intern/draw_resource.hh +++ b/source/blender/draw/intern/draw_resource.hh @@ -159,7 +159,7 @@ inline void ObjectBounds::sync() bounding_sphere.w = -1.0f; /* Disable test. */ } -inline void ObjectBounds::sync(Object &ob) +inline void ObjectBounds::sync(Object &ob, float inflate_bounds) { const std::optional bbox = BKE_object_boundbox_get(&ob); if (!bbox) { @@ -171,6 +171,16 @@ inline void ObjectBounds::sync(Object &ob) *reinterpret_cast(&bounding_corners[2]) = bbox->vec[3]; *reinterpret_cast(&bounding_corners[3]) = bbox->vec[1]; bounding_sphere.w = 0.0f; /* Enable test. */ + + if (inflate_bounds != 0.0f) { + BLI_assert(inflate_bounds >= 0.0f); + float p = inflate_bounds; + float n = -inflate_bounds; + bounding_corners[0] += float4(n, n, n, 0.0f); + bounding_corners[1] += float4(p, n, n, 0.0f); + bounding_corners[2] += float4(n, p, n, 0.0f); + bounding_corners[3] += float4(n, n, p, 0.0f); + } } inline void ObjectBounds::sync(const float3 ¢er, const float3 &size) diff --git a/source/blender/draw/intern/draw_shader_shared.h b/source/blender/draw/intern/draw_shader_shared.h index a4ff34091fc..887d4727212 100644 --- a/source/blender/draw/intern/draw_shader_shared.h +++ b/source/blender/draw/intern/draw_shader_shared.h @@ -204,7 +204,7 @@ struct ObjectBounds { #if !defined(GPU_SHADER) && defined(__cplusplus) void sync(); - void sync(Object &ob); + void sync(Object &ob, float inflate_bounds = 0.0f); void sync(const float3 ¢er, const float3 &size); #endif }; diff --git a/source/blender/draw/intern/draw_view_c.cc b/source/blender/draw/intern/draw_view_c.cc index 05862ccf64f..8200dca4e63 100644 --- a/source/blender/draw/intern/draw_view_c.cc +++ b/source/blender/draw/intern/draw_view_c.cc @@ -17,6 +17,7 @@ #include "ED_util.hh" #include "ED_view3d.hh" +#include "GPU_debug.h" #include "GPU_immediate.h" #include "GPU_matrix.h" #include "GPU_shader.h" @@ -40,12 +41,14 @@ void DRW_draw_region_info() { + GPU_debug_group_begin("RegionInfo"); const DRWContextState *draw_ctx = DRW_context_state_get(); ARegion *region = draw_ctx->region; DRW_draw_cursor(); view3d_draw_region_info(draw_ctx->evil_C, region); + GPU_debug_group_end(); } /* **************************** 3D Cursor ******************************** */ diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_attributes.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_attributes.cc index 3414636eb7a..9cf503b8e68 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_attributes.cc +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_attributes.cc @@ -8,16 +8,15 @@ #include "MEM_guardedalloc.h" -#include - -#include "BLI_color.hh" +#include "BLI_array_utils.hh" #include "BLI_math_vector_types.hh" #include "BLI_string.h" -#include "BKE_attribute.h" #include "BKE_attribute.hh" +#include "BKE_attribute_math.hh" #include "BKE_mesh.hh" +#include "attribute_convert.hh" #include "draw_attributes.hh" #include "draw_subdivision.h" #include "extract_mesh.hh" @@ -28,142 +27,19 @@ namespace blender::draw { /** \name Extract Attributes * \{ */ -static CustomData *get_custom_data_for_domain(const MeshRenderData &mr, eAttrDomain domain) -{ - switch (domain) { - case ATTR_DOMAIN_POINT: - return (mr.extract_type == MR_EXTRACT_BMESH) ? &mr.bm->vdata : &mr.me->vert_data; - case ATTR_DOMAIN_CORNER: - return (mr.extract_type == MR_EXTRACT_BMESH) ? &mr.bm->ldata : &mr.me->loop_data; - case ATTR_DOMAIN_FACE: - return (mr.extract_type == MR_EXTRACT_BMESH) ? &mr.bm->pdata : &mr.me->face_data; - case ATTR_DOMAIN_EDGE: - return (mr.extract_type == MR_EXTRACT_BMESH) ? &mr.bm->edata : &mr.me->edge_data; - default: - return nullptr; - } -} - -/* Utility to convert from the type used in the attributes to the types for the VBO. - * This is mostly used to promote integers and booleans to floats, as other types (float, float2, - * etc.) directly map to available GPU types. Booleans are still converted as attributes are vec4 - * in the shader. - */ -template struct AttributeTypeConverter { - static VBOType convert_value(AttributeType value) - { - if constexpr (std::is_same_v) { - return value; - } - - /* This should only concern bools which are converted to floats. */ - return static_cast(value); - } -}; - -struct gpuMeshCol { - ushort r, g, b, a; -}; - -template<> struct AttributeTypeConverter { - static gpuMeshCol convert_value(MPropCol value) - { - gpuMeshCol result; - result.r = unit_float_to_ushort_clamp(value.color[0]); - result.g = unit_float_to_ushort_clamp(value.color[1]); - result.b = unit_float_to_ushort_clamp(value.color[2]); - result.a = unit_float_to_ushort_clamp(value.color[3]); - return result; - } -}; - -template<> struct AttributeTypeConverter { - static gpuMeshCol convert_value(ColorGeometry4b value) - { - gpuMeshCol result; - result.r = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[value.r]); - result.g = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[value.g]); - result.b = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[value.b]); - result.a = unit_float_to_ushort_clamp(value.a * (1.0f / 255.0f)); - return result; - } -}; - -/* Return the number of component for the attribute's value type, or 0 if is it unsupported. */ -static uint gpu_component_size_for_attribute_type(eCustomDataType type) -{ - switch (type) { - case CD_PROP_BOOL: - case CD_PROP_INT8: - case CD_PROP_INT32: - case CD_PROP_FLOAT: - /* TODO(@kevindietrich): should be 1 when scalar attributes conversion is handled by us. See - * comment #extract_attr_init. */ - return 3; - case CD_PROP_FLOAT2: - case CD_PROP_INT32_2D: - return 2; - case CD_PROP_FLOAT3: - return 3; - case CD_PROP_COLOR: - case CD_PROP_BYTE_COLOR: - case CD_PROP_QUATERNION: - return 4; - default: - return 0; - } -} - -static GPUVertFetchMode get_fetch_mode_for_type(eCustomDataType type) -{ - switch (type) { - case CD_PROP_INT8: - case CD_PROP_INT32: - case CD_PROP_INT32_2D: - return GPU_FETCH_INT_TO_FLOAT; - case CD_PROP_BYTE_COLOR: - return GPU_FETCH_INT_TO_FLOAT_UNIT; - default: - return GPU_FETCH_FLOAT; - } -} - -static GPUVertCompType get_comp_type_for_type(eCustomDataType type) -{ - switch (type) { - case CD_PROP_INT8: - case CD_PROP_INT32_2D: - case CD_PROP_INT32: - return GPU_COMP_I32; - case CD_PROP_BYTE_COLOR: - /* This should be u8, - * but u16 is required to store the color in linear space without precision loss */ - return GPU_COMP_U16; - default: - return GPU_COMP_F32; - } -} - static void init_vbo_for_attribute(const MeshRenderData &mr, GPUVertBuf *vbo, const DRW_AttributeRequest &request, bool build_on_device, uint32_t len) { - GPUVertCompType comp_type = get_comp_type_for_type(request.cd_type); - GPUVertFetchMode fetch_mode = get_fetch_mode_for_type(request.cd_type); - const uint comp_size = gpu_component_size_for_attribute_type(request.cd_type); - /* We should not be here if the attribute type is not supported. */ - BLI_assert(comp_size != 0); - char attr_name[32], attr_safe_name[GPU_MAX_SAFE_ATTR_NAME]; GPU_vertformat_safe_attr_name(request.attribute_name, attr_safe_name, GPU_MAX_SAFE_ATTR_NAME); /* Attributes use auto-name. */ SNPRINTF(attr_name, "a%s", attr_safe_name); - GPUVertFormat format = {0}; + GPUVertFormat format = init_format_for_attribute(request.cd_type, attr_name); GPU_vertformat_deinterleave(&format); - GPU_vertformat_attr_add(&format, attr_name, comp_type, comp_size, fetch_mode); if (mr.active_color_name && STREQ(request.attribute_name, mr.active_color_name)) { GPU_vertformat_alias_add(&format, "ac"); @@ -181,164 +57,214 @@ static void init_vbo_for_attribute(const MeshRenderData &mr, } } -template -static void fill_vertbuf_with_attribute(const MeshRenderData &mr, - VBOType *vbo_data, - const DRW_AttributeRequest &request) +template +static void extract_data_mesh_mapped_corner(const Span attribute, + const Span indices, + GPUVertBuf &vbo) { - const CustomData *custom_data = get_custom_data_for_domain(mr, request.domain); - BLI_assert(custom_data); - const int layer_index = request.layer_index; + using Converter = AttributeConverter; + using VBOType = typename Converter::VBOType; + MutableSpan data(static_cast(GPU_vertbuf_get_data(&vbo)), indices.size()); - const Span corner_verts = mr.corner_verts; - const Span corner_edges = mr.corner_edges; - - const AttributeType *attr_data = static_cast( - CustomData_get_layer_n(custom_data, request.cd_type, layer_index)); - - using Converter = AttributeTypeConverter; - - switch (request.domain) { - case ATTR_DOMAIN_POINT: - for (int ml_index = 0; ml_index < mr.loop_len; ml_index++, vbo_data++) { - *vbo_data = Converter::convert_value(attr_data[corner_verts[ml_index]]); - } - break; - case ATTR_DOMAIN_CORNER: - for (int ml_index = 0; ml_index < mr.loop_len; ml_index++, vbo_data++) { - *vbo_data = Converter::convert_value(attr_data[ml_index]); - } - break; - case ATTR_DOMAIN_EDGE: - for (int ml_index = 0; ml_index < mr.loop_len; ml_index++, vbo_data++) { - *vbo_data = Converter::convert_value(attr_data[corner_edges[ml_index]]); - } - break; - case ATTR_DOMAIN_FACE: - for (int face_index = 0; face_index < mr.face_len; face_index++) { - const IndexRange face = mr.faces[face_index]; - const VBOType value = Converter::convert_value(attr_data[face_index]); - for (int l = 0; l < face.size(); l++) { - *vbo_data++ = value; - } - } - break; - default: - BLI_assert_unreachable(); - break; - } -} - -template -static void fill_vertbuf_with_attribute_bm(const MeshRenderData &mr, - VBOType *&vbo_data, - const DRW_AttributeRequest &request) -{ - const CustomData *custom_data = get_custom_data_for_domain(mr, request.domain); - BLI_assert(custom_data); - const int layer_index = request.layer_index; - - const int cd_ofs = CustomData_get_n_offset(custom_data, request.cd_type, layer_index); - - using Converter = AttributeTypeConverter; - - BMIter f_iter; - BMFace *efa; - BM_ITER_MESH (efa, &f_iter, mr.bm, BM_FACES_OF_MESH) { - BMLoop *l_iter, *l_first; - l_iter = l_first = BM_FACE_FIRST_LOOP(efa); - do { - const AttributeType *attr_data = nullptr; - if (request.domain == ATTR_DOMAIN_POINT) { - attr_data = static_cast(BM_ELEM_CD_GET_VOID_P(l_iter->v, cd_ofs)); - } - else if (request.domain == ATTR_DOMAIN_CORNER) { - attr_data = static_cast(BM_ELEM_CD_GET_VOID_P(l_iter, cd_ofs)); - } - else if (request.domain == ATTR_DOMAIN_FACE) { - attr_data = static_cast(BM_ELEM_CD_GET_VOID_P(efa, cd_ofs)); - } - else if (request.domain == ATTR_DOMAIN_EDGE) { - attr_data = static_cast(BM_ELEM_CD_GET_VOID_P(l_iter->e, cd_ofs)); - } - else { - BLI_assert_unreachable(); - continue; - } - *vbo_data = Converter::convert_value(*attr_data); - vbo_data++; - } while ((l_iter = l_iter->next) != l_first); - } -} - -template -static void extract_attr_generic(const MeshRenderData &mr, - GPUVertBuf *vbo, - const DRW_AttributeRequest &request) -{ - VBOType *vbo_data = static_cast(GPU_vertbuf_get_data(vbo)); - - if (mr.extract_type == MR_EXTRACT_BMESH) { - fill_vertbuf_with_attribute_bm(mr, vbo_data, request); + if constexpr (std::is_same_v) { + array_utils::gather(attribute, indices, data); } else { - fill_vertbuf_with_attribute(mr, vbo_data, request); + threading::parallel_for(indices.index_range(), 8192, [&](const IndexRange range) { + for (const int i : range) { + data[i] = Converter::convert(attribute[indices[i]]); + } + }); + } +} + +template +static void extract_data_mesh_vert(const MeshRenderData &mr, + const Span attribute, + GPUVertBuf &vbo) +{ +} + +template +static void extract_data_mesh_edge(const MeshRenderData &mr, + const Span attribute, + GPUVertBuf &vbo) +{ + extract_data_mapped_corner(attribute, mr.corner_edges, vbo); +} + +template +static void extract_data_mesh_face(const OffsetIndices faces, + const Span attribute, + GPUVertBuf &vbo) +{ + using Converter = AttributeConverter; + using VBOType = typename Converter::VBOType; + MutableSpan data(static_cast(GPU_vertbuf_get_data(&vbo)), faces.total_size()); + + threading::parallel_for(faces.index_range(), 2048, [&](const IndexRange range) { + for (const int i : range) { + data.slice(faces[i]).fill(Converter::convert(attribute[i])); + } + }); +} + +template +static void extract_data_bmesh_vert(const BMesh &bm, const int cd_offset, GPUVertBuf &vbo) +{ + using Converter = AttributeConverter; + using VBOType = typename Converter::VBOType; + VBOType *data = static_cast(GPU_vertbuf_get_data(&vbo)); + + const BMFace *face; + BMIter f_iter; + BM_ITER_MESH (face, &f_iter, &const_cast(bm), BM_FACES_OF_MESH) { + const BMLoop *loop = BM_FACE_FIRST_LOOP(face); + for ([[maybe_unused]] const int i : IndexRange(face->len)) { + const T *src = static_cast(POINTER_OFFSET(loop->v->head.data, cd_offset)); + *data = Converter::convert(*src); + loop = loop->next; + data++; + } + } +} + +template +static void extract_data_bmesh_edge(const BMesh &bm, const int cd_offset, GPUVertBuf &vbo) +{ + using Converter = AttributeConverter; + using VBOType = typename Converter::VBOType; + VBOType *data = static_cast(GPU_vertbuf_get_data(&vbo)); + + const BMFace *face; + BMIter f_iter; + BM_ITER_MESH (face, &f_iter, &const_cast(bm), BM_FACES_OF_MESH) { + const BMLoop *loop = BM_FACE_FIRST_LOOP(face); + for ([[maybe_unused]] const int i : IndexRange(face->len)) { + const T &src = *static_cast(POINTER_OFFSET(loop->e->head.data, cd_offset)); + *data = Converter::convert(src); + loop = loop->next; + data++; + } + } +} + +template +static void extract_data_bmesh_face(const BMesh &bm, const int cd_offset, GPUVertBuf &vbo) +{ + using Converter = AttributeConverter; + using VBOType = typename Converter::VBOType; + VBOType *data = static_cast(GPU_vertbuf_get_data(&vbo)); + + const BMFace *face; + BMIter f_iter; + BM_ITER_MESH (face, &f_iter, &const_cast(bm), BM_FACES_OF_MESH) { + const T &src = *static_cast(POINTER_OFFSET(face->head.data, cd_offset)); + std::fill_n(data, face->len, Converter::convert(src)); + data += face->len; + } +} + +template +static void extract_data_bmesh_loop(const BMesh &bm, const int cd_offset, GPUVertBuf &vbo) +{ + using Converter = AttributeConverter; + using VBOType = typename Converter::VBOType; + VBOType *data = static_cast(GPU_vertbuf_get_data(&vbo)); + + const BMFace *face; + BMIter f_iter; + BM_ITER_MESH (face, &f_iter, &const_cast(bm), BM_FACES_OF_MESH) { + const BMLoop *loop = BM_FACE_FIRST_LOOP(face); + for ([[maybe_unused]] const int i : IndexRange(face->len)) { + const T &src = *static_cast(POINTER_OFFSET(loop->head.data, cd_offset)); + *data = Converter::convert(src); + loop = loop->next; + data++; + } + } +} + +static const CustomData *get_custom_data_for_domain(const BMesh &bm, eAttrDomain domain) +{ + switch (domain) { + case ATTR_DOMAIN_POINT: + return &bm.vdata; + case ATTR_DOMAIN_CORNER: + return &bm.ldata; + case ATTR_DOMAIN_FACE: + return &bm.pdata; + case ATTR_DOMAIN_EDGE: + return &bm.edata; + default: + return nullptr; } } static void extract_attr(const MeshRenderData &mr, - GPUVertBuf *vbo, - const DRW_AttributeRequest &request) + const DRW_AttributeRequest &request, + GPUVertBuf &vbo) { - /* TODO(@kevindietrich): float3 is used for scalar attributes as the implicit conversion done by - * OpenGL to vec4 for a scalar `s` will produce a `vec4(s, 0, 0, 1)`. However, following the - * Blender convention, it should be `vec4(s, s, s, 1)`. This could be resolved using a similar - * texture as for volume attribute, so we can control the conversion ourselves. */ - switch (request.cd_type) { - case CD_PROP_BOOL: - extract_attr_generic(mr, vbo, request); - break; - case CD_PROP_INT8: - extract_attr_generic(mr, vbo, request); - break; - case CD_PROP_INT32: - extract_attr_generic(mr, vbo, request); - break; - case CD_PROP_INT32_2D: - extract_attr_generic(mr, vbo, request); - break; - case CD_PROP_FLOAT: - extract_attr_generic(mr, vbo, request); - break; - case CD_PROP_FLOAT2: - extract_attr_generic(mr, vbo, request); - break; - case CD_PROP_FLOAT3: - extract_attr_generic(mr, vbo, request); - break; - case CD_PROP_QUATERNION: - case CD_PROP_COLOR: - extract_attr_generic(mr, vbo, request); - break; - case CD_PROP_BYTE_COLOR: - extract_attr_generic(mr, vbo, request); - break; - default: - BLI_assert_unreachable(); + if (mr.extract_type == MR_EXTRACT_BMESH) { + const CustomData &custom_data = *get_custom_data_for_domain(*mr.bm, request.domain); + const char *name = request.attribute_name; + const int cd_offset = CustomData_get_offset_named(&custom_data, request.cd_type, name); + + bke::attribute_math::convert_to_static_type(request.cd_type, [&](auto dummy) { + using T = decltype(dummy); + switch (request.domain) { + case ATTR_DOMAIN_POINT: + extract_data_bmesh_vert(*mr.bm, cd_offset, vbo); + break; + case ATTR_DOMAIN_EDGE: + extract_data_bmesh_edge(*mr.bm, cd_offset, vbo); + break; + case ATTR_DOMAIN_FACE: + extract_data_bmesh_face(*mr.bm, cd_offset, vbo); + break; + case ATTR_DOMAIN_CORNER: + extract_data_bmesh_loop(*mr.bm, cd_offset, vbo); + break; + default: + BLI_assert_unreachable(); + } + }); + } + else { + const bke::AttributeAccessor attributes = mr.me->attributes(); + const StringRef name = request.attribute_name; + const eCustomDataType data_type = request.cd_type; + const GVArraySpan attribute = *attributes.lookup_or_default(name, request.domain, data_type); + + bke::attribute_math::convert_to_static_type(request.cd_type, [&](auto dummy) { + using T = decltype(dummy); + switch (request.domain) { + case ATTR_DOMAIN_POINT: + extract_data_mesh_mapped_corner(attribute.typed(), mr.corner_verts, vbo); + break; + case ATTR_DOMAIN_EDGE: + extract_data_mesh_mapped_corner(attribute.typed(), mr.corner_edges, vbo); + break; + case ATTR_DOMAIN_FACE: + extract_data_mesh_face(mr.faces, attribute.typed(), vbo); + break; + case ATTR_DOMAIN_CORNER: + vertbuf_data_extract_direct(attribute.typed(), vbo); + break; + default: + BLI_assert_unreachable(); + } + }); } } static void extract_attr_init( const MeshRenderData &mr, MeshBatchCache &cache, void *buf, void * /*tls_data*/, int index) { - const DRW_Attributes *attrs_used = &cache.attr_used; - const DRW_AttributeRequest &request = attrs_used->requests[index]; - + const DRW_AttributeRequest &request = cache.attr_used.requests[index]; GPUVertBuf *vbo = static_cast(buf); - init_vbo_for_attribute(mr, vbo, request, false, uint32_t(mr.loop_len)); - - extract_attr(mr, vbo, request); + extract_attr(mr, request, *vbo); } static void extract_attr_init_subdiv(const DRWSubdivCache &subdiv_cache, @@ -353,26 +279,29 @@ static void extract_attr_init_subdiv(const DRWSubdivCache &subdiv_cache, Mesh *coarse_mesh = subdiv_cache.mesh; - GPUVertCompType comp_type = get_comp_type_for_type(request.cd_type); - GPUVertFetchMode fetch_mode = get_fetch_mode_for_type(request.cd_type); - const uint32_t dimensions = gpu_component_size_for_attribute_type(request.cd_type); - /* Prepare VBO for coarse data. The compute shader only expects floats. */ GPUVertBuf *src_data = GPU_vertbuf_calloc(); - GPUVertFormat coarse_format = {0}; - GPU_vertformat_attr_add(&coarse_format, "data", comp_type, dimensions, fetch_mode); + GPUVertFormat coarse_format = draw::init_format_for_attribute(request.cd_type, "data"); GPU_vertbuf_init_with_format_ex(src_data, &coarse_format, GPU_USAGE_STATIC); GPU_vertbuf_data_alloc(src_data, uint32_t(coarse_mesh->totloop)); - extract_attr(mr, src_data, request); + extract_attr(mr, request, *src_data); GPUVertBuf *dst_buffer = static_cast(buffer); init_vbo_for_attribute(mr, dst_buffer, request, true, subdiv_cache.num_subdiv_loops); /* Ensure data is uploaded properly. */ GPU_vertbuf_tag_dirty(src_data); - draw_subdiv_interp_custom_data( - subdiv_cache, src_data, dst_buffer, comp_type, int(dimensions), 0); + bke::attribute_math::convert_to_static_type(request.cd_type, [&](auto dummy) { + using T = decltype(dummy); + using Converter = AttributeConverter; + draw_subdiv_interp_custom_data(subdiv_cache, + src_data, + dst_buffer, + Converter::gpu_component_type, + Converter::gpu_component_len, + 0); + }); GPU_vertbuf_discard(src_data); } diff --git a/source/blender/draw/tests/eevee_test.cc b/source/blender/draw/tests/eevee_test.cc index ecfb94740c1..40f7584fd84 100644 --- a/source/blender/draw/tests/eevee_test.cc +++ b/source/blender/draw/tests/eevee_test.cc @@ -648,6 +648,10 @@ class TestAlloc { GPU_render_begin(); int tiles_index = 1; + for (int i : IndexRange(SHADOW_MAX_TILE)) { + tiles_data[i] = 0; + } + for (uint i : IndexRange(0, page_free_count)) { uint2 page = {i % SHADOW_PAGE_PER_ROW, i / SHADOW_PAGE_PER_ROW}; pages_free_data[i] = page.x | (page.y << 16u); diff --git a/source/blender/editors/animation/anim_channels_defines.cc b/source/blender/editors/animation/anim_channels_defines.cc index 632551e9158..23455350acd 100644 --- a/source/blender/editors/animation/anim_channels_defines.cc +++ b/source/blender/editors/animation/anim_channels_defines.cc @@ -8,7 +8,7 @@ #include -#include "ANIM_fcurve.hh" +#include "ANIM_action.hh" #include "ANIM_keyframing.hh" #include "MEM_guardedalloc.h" @@ -5593,7 +5593,7 @@ void ANIM_channel_draw_widgets(const bContext *C, "", offset + margin_x, rect->ymin, - MAX2(width, RENAME_TEXT_MIN_WIDTH), + std::max(width, RENAME_TEXT_MIN_WIDTH), channel_height, &ptr, RNA_property_identifier(prop), diff --git a/source/blender/editors/animation/anim_channels_edit.cc b/source/blender/editors/animation/anim_channels_edit.cc index 355b698f5cc..60bc6ddf025 100644 --- a/source/blender/editors/animation/anim_channels_edit.cc +++ b/source/blender/editors/animation/anim_channels_edit.cc @@ -46,7 +46,6 @@ #include "UI_interface.hh" #include "UI_view2d.hh" -#include "ED_anim_api.hh" #include "ED_armature.hh" #include "ED_keyframes_edit.hh" /* XXX move the select modes out of there! */ #include "ED_markers.hh" @@ -54,6 +53,8 @@ #include "ED_screen.hh" #include "ED_select_utils.hh" +#include "ANIM_animdata.hh" + #include "WM_api.hh" #include "WM_types.hh" @@ -857,82 +858,6 @@ void ANIM_frame_channel_y_extents(bContext *C, bAnimContext *ac) } /** \} */ -/* -------------------------------------------------------------------- */ -/** \name Public F-Curves API - * \{ */ - -void ANIM_fcurve_delete_from_animdata(bAnimContext *ac, AnimData *adt, FCurve *fcu) -{ - /* - if no AnimData, we've got nowhere to remove the F-Curve from - * (this doesn't guarantee that the F-Curve is in there, but at least we tried - * - if no F-Curve, there is nothing to remove - */ - if (ELEM(nullptr, adt, fcu)) { - return; - } - - /* remove from whatever list it came from - * - Action Group - * - Action - * - Drivers - * - TODO... some others? - */ - if ((ac) && (ac->datatype == ANIMCONT_DRIVERS)) { - /* driver F-Curve */ - BLI_remlink(&adt->drivers, fcu); - } - else if (adt->action) { - bAction *act = adt->action; - - /* remove from group or action, whichever one "owns" the F-Curve */ - if (fcu->grp) { - bActionGroup *agrp = fcu->grp; - - /* remove F-Curve from group+action */ - action_groups_remove_channel(act, fcu); - - /* if group has no more channels, remove it too, - * otherwise can have many dangling groups #33541. - */ - if (BLI_listbase_is_empty(&agrp->channels)) { - BLI_freelinkN(&act->groups, agrp); - } - } - else { - BLI_remlink(&act->curves, fcu); - } - - /* if action has no more F-Curves as a result of this, unlink it from - * AnimData if it did not come from a NLA Strip being tweaked. - * - * This is done so that we don't have dangling Object+Action entries in - * channel list that are empty, and linger around long after the data they - * are for has disappeared (and probably won't come back). - */ - ANIM_remove_empty_action_from_animdata(adt); - } - - /* free the F-Curve itself */ - BKE_fcurve_free(fcu); -} - -bool ANIM_remove_empty_action_from_animdata(AnimData *adt) -{ - if (adt->action != nullptr) { - bAction *act = adt->action; - - if (BLI_listbase_is_empty(&act->curves) && (adt->flag & ADT_NLA_EDIT_ON) == 0) { - id_us_min(&act->id); - adt->action = nullptr; - return true; - } - } - - return false; -} - -/** \} */ - /* -------------------------------------------------------------------- */ /** \name Operator Utilities * \{ */ @@ -2211,7 +2136,7 @@ static int animchannels_delete_exec(bContext *C, wmOperator * /*op*/) FCurve *fcu = (FCurve *)ale->data; /* try to free F-Curve */ - ANIM_fcurve_delete_from_animdata(&ac, adt, fcu); + blender::animrig::animdata_fcurve_delete(&ac, adt, fcu); tag_update_animation_element(ale); break; } diff --git a/source/blender/editors/animation/anim_filter.cc b/source/blender/editors/animation/anim_filter.cc index 2657932b4f3..60379903719 100644 --- a/source/blender/editors/animation/anim_filter.cc +++ b/source/blender/editors/animation/anim_filter.cc @@ -1822,7 +1822,7 @@ static size_t animdata_filter_grease_pencil_layer_node_recursive( size_t tmp_items = 0; /* Add grease pencil layer channels. */ - BEGIN_ANIMFILTER_SUBCHANNELS ((layer_group.base.flag & GP_LAYER_TREE_NODE_EXPANDED)) { + BEGIN_ANIMFILTER_SUBCHANNELS (layer_group.base.flag &GP_LAYER_TREE_NODE_EXPANDED) { LISTBASE_FOREACH_BACKWARD (GreasePencilLayerTreeNode *, node_, &layer_group.children) { tmp_items += animdata_filter_grease_pencil_layer_node_recursive( &tmp_data, ads, grease_pencil, node_->wrap(), filter_mode); diff --git a/source/blender/editors/animation/drivers.cc b/source/blender/editors/animation/drivers.cc index 5712c7ebaaf..4ece9a66933 100644 --- a/source/blender/editors/animation/drivers.cc +++ b/source/blender/editors/animation/drivers.cc @@ -43,6 +43,8 @@ #include "RNA_path.hh" #include "RNA_prototypes.h" +#include "ANIM_fcurve.hh" + #include "anim_intern.h" /* ************************************************** */ @@ -122,9 +124,9 @@ FCurve *alloc_driver_fcurve(const char rna_path[], * - These are configured to 0,0 and 1,1 to give a 1-1 mapping * which can be easily tweaked from there. */ - insert_vert_fcurve( + blender::animrig::insert_vert_fcurve( fcu, 0.0f, 0.0f, BEZT_KEYTYPE_KEYFRAME, INSERTKEY_FAST | INSERTKEY_NO_USERPREF); - insert_vert_fcurve( + blender::animrig::insert_vert_fcurve( fcu, 1.0f, 1.0f, BEZT_KEYTYPE_KEYFRAME, INSERTKEY_FAST | INSERTKEY_NO_USERPREF); fcu->extend = FCURVE_EXTRAPOLATE_LINEAR; BKE_fcurve_handles_recalc(fcu); @@ -330,7 +332,7 @@ int ANIM_add_driver_with_target(ReportList *reports, int dst_len = RNA_property_array_check(prop) ? RNA_property_array_length(&ptr, prop) : 1; int src_len = RNA_property_array_check(prop) ? RNA_property_array_length(&ptr2, prop2) : 1; - int len = MIN2(dst_len, src_len); + int len = std::min(dst_len, src_len); for (int i = 0; i < len; i++) { done_tot += add_driver_with_target(reports, diff --git a/source/blender/editors/animation/keyframes_general.cc b/source/blender/editors/animation/keyframes_general.cc index 9b550859b49..05a55412f69 100644 --- a/source/blender/editors/animation/keyframes_general.cc +++ b/source/blender/editors/animation/keyframes_general.cc @@ -34,9 +34,10 @@ #include "RNA_enum_types.hh" #include "RNA_path.hh" -#include "ED_anim_api.hh" #include "ED_keyframes_edit.hh" -#include "ED_keyframing.hh" + +#include "ANIM_animdata.hh" +#include "ANIM_fcurve.hh" /* This file contains code for various keyframe-editing tools which are 'destructive' * (i.e. they will modify the order of the keyframes, and change the size of the array). @@ -117,7 +118,7 @@ void clean_fcurve(bAnimContext *ac, /* now insert first keyframe, as it should be ok */ bezt = old_bezts; - insert_bezt_fcurve(fcu, bezt, eInsertKeyFlags(0)); + blender::animrig::insert_bezt_fcurve(fcu, bezt, eInsertKeyFlags(0)); if (!(bezt->f2 & SELECT)) { lastb = fcu->bezt; lastb->f1 = lastb->f2 = lastb->f3 = 0; @@ -149,7 +150,7 @@ void clean_fcurve(bAnimContext *ac, cur[1] = bezt->vec[1][1]; if (only_selected_keys && !(bezt->f2 & SELECT)) { - insert_bezt_fcurve(fcu, bezt, eInsertKeyFlags(0)); + blender::animrig::insert_bezt_fcurve(fcu, bezt, eInsertKeyFlags(0)); lastb = (fcu->bezt + (fcu->totvert - 1)); lastb->f1 = lastb->f2 = lastb->f3 = 0; continue; @@ -166,7 +167,7 @@ void clean_fcurve(bAnimContext *ac, if (cur[1] > next[1]) { if (IS_EQT(cur[1], prev[1], thresh) == 0) { /* add new keyframe */ - insert_bezt_fcurve(fcu, bezt, eInsertKeyFlags(0)); + blender::animrig::insert_bezt_fcurve(fcu, bezt, eInsertKeyFlags(0)); } } } @@ -174,7 +175,7 @@ void clean_fcurve(bAnimContext *ac, /* only add if values are a considerable distance apart */ if (IS_EQT(cur[1], prev[1], thresh) == 0) { /* add new keyframe */ - insert_bezt_fcurve(fcu, bezt, eInsertKeyFlags(0)); + blender::animrig::insert_bezt_fcurve(fcu, bezt, eInsertKeyFlags(0)); } } } @@ -184,18 +185,18 @@ void clean_fcurve(bAnimContext *ac, /* does current have same value as previous and next? */ if (IS_EQT(cur[1], prev[1], thresh) == 0) { /* add new keyframe */ - insert_bezt_fcurve(fcu, bezt, eInsertKeyFlags(0)); + blender::animrig::insert_bezt_fcurve(fcu, bezt, eInsertKeyFlags(0)); } else if (IS_EQT(cur[1], next[1], thresh) == 0) { /* add new keyframe */ - insert_bezt_fcurve(fcu, bezt, eInsertKeyFlags(0)); + blender::animrig::insert_bezt_fcurve(fcu, bezt, eInsertKeyFlags(0)); } } else { /* add if value doesn't equal that of previous */ if (IS_EQT(cur[1], prev[1], thresh) == 0) { /* add new keyframe */ - insert_bezt_fcurve(fcu, bezt, eInsertKeyFlags(0)); + blender::animrig::insert_bezt_fcurve(fcu, bezt, eInsertKeyFlags(0)); } } } @@ -227,7 +228,7 @@ void clean_fcurve(bAnimContext *ac, /* check if curve is really unused and if it is, return signal for deletion */ if (BKE_fcurve_is_empty(fcu)) { AnimData *adt = ale->adt; - ANIM_fcurve_delete_from_animdata(ac, adt, fcu); + blender::animrig::animdata_fcurve_delete(ac, adt, fcu); ale->key_data = nullptr; } } @@ -1077,7 +1078,7 @@ bool decimate_fcurve(bAnimListElem *ale, float remove_ratio, float error_sq_max) BezTriple *bezt = (old_bezts + i); bezt->f2 &= ~BEZT_FLAG_IGNORE_TAG; if ((bezt->f2 & BEZT_FLAG_TEMP_TAG) == 0) { - insert_bezt_fcurve(fcu, bezt, eInsertKeyFlags(0)); + blender::animrig::insert_bezt_fcurve(fcu, bezt, eInsertKeyFlags(0)); } } /* now free the memory used by the old BezTriples */ @@ -1270,7 +1271,7 @@ void bake_fcurve_segments(FCurve *fcu) /* add keyframes with these, tagging as 'breakdowns' */ for (n = 1, fp = value_cache; n < range && fp; n++, fp++) { - insert_vert_fcurve( + blender::animrig::insert_vert_fcurve( fcu, fp->frame, fp->val, BEZT_KEYTYPE_BREAKDOWN, eInsertKeyFlags(1)); } @@ -1712,7 +1713,7 @@ static void paste_animedit_keys_fcurve( * NOTE: we do not want to inherit handles from existing keyframes in this case! */ - insert_bezt_fcurve(fcu, bezt, INSERTKEY_OVERWRITE_FULL); + blender::animrig::insert_bezt_fcurve(fcu, bezt, INSERTKEY_OVERWRITE_FULL); /* un-apply offset from src beztriple after copying */ sub_v2_v2(bezt->vec[0], offset); diff --git a/source/blender/editors/animation/keyframes_keylist.cc b/source/blender/editors/animation/keyframes_keylist.cc index 001b2ad2cd7..4d2d13cd159 100644 --- a/source/blender/editors/animation/keyframes_keylist.cc +++ b/source/blender/editors/animation/keyframes_keylist.cc @@ -493,7 +493,7 @@ static void nupdate_ak_bezt(ActKeyColumn *ak, void *data) } /* For interpolation type, select the highest value (enum is sorted). */ - ak->handle_type = MAX2((eKeyframeHandleDrawOpts)ak->handle_type, bezt_handle_type(bezt)); + ak->handle_type = std::max((eKeyframeHandleDrawOpts)ak->handle_type, bezt_handle_type(bezt)); /* For extremes, detect when combining different states. */ const char new_extreme = bezt_extreme_type(chain); diff --git a/source/blender/editors/animation/keyframing.cc b/source/blender/editors/animation/keyframing.cc index 17e06fc825d..e427625e5eb 100644 --- a/source/blender/editors/animation/keyframing.cc +++ b/source/blender/editors/animation/keyframing.cc @@ -39,11 +39,11 @@ #include "DEG_depsgraph.hh" #include "DEG_depsgraph_build.hh" -#include "ED_keyframes_edit.hh" #include "ED_keyframing.hh" #include "ED_object.hh" #include "ED_screen.hh" +#include "ANIM_animdata.hh" #include "ANIM_bone_collections.h" #include "ANIM_fcurve.hh" #include "ANIM_keyframing.hh" @@ -212,271 +212,6 @@ void update_autoflags_fcurve(FCurve *fcu, bContext *C, ReportList *reports, Poin } } -/* ************************************************** */ -/* KEYFRAME INSERTION */ - -/* -------------- BezTriple Insertion -------------------- */ - -/* Change the Y position of a keyframe to match the input, adjusting handles. */ -static void replace_bezt_keyframe_ypos(BezTriple *dst, const BezTriple *bezt) -{ - /* just change the values when replacing, so as to not overwrite handles */ - float dy = bezt->vec[1][1] - dst->vec[1][1]; - - /* just apply delta value change to the handle values */ - dst->vec[0][1] += dy; - dst->vec[1][1] += dy; - dst->vec[2][1] += dy; - - dst->f1 = bezt->f1; - dst->f2 = bezt->f2; - dst->f3 = bezt->f3; - - /* TODO: perform some other operations? */ -} - -int insert_bezt_fcurve(FCurve *fcu, const BezTriple *bezt, eInsertKeyFlags flag) -{ - int i = 0; - - /* are there already keyframes? */ - if (fcu->bezt) { - bool replace; - i = BKE_fcurve_bezt_binarysearch_index(fcu->bezt, bezt->vec[1][0], fcu->totvert, &replace); - - /* replace an existing keyframe? */ - if (replace) { - /* sanity check: 'i' may in rare cases exceed arraylen */ - if ((i >= 0) && (i < fcu->totvert)) { - if (flag & INSERTKEY_OVERWRITE_FULL) { - fcu->bezt[i] = *bezt; - } - else { - replace_bezt_keyframe_ypos(&fcu->bezt[i], bezt); - } - - if (flag & INSERTKEY_CYCLE_AWARE) { - /* If replacing an end point of a cyclic curve without offset, - * modify the other end too. */ - if (ELEM(i, 0, fcu->totvert - 1) && BKE_fcurve_get_cycle_type(fcu) == FCU_CYCLE_PERFECT) - { - replace_bezt_keyframe_ypos(&fcu->bezt[i == 0 ? fcu->totvert - 1 : 0], bezt); - } - } - } - } - /* Keyframing modes allow not replacing the keyframe. */ - else if ((flag & INSERTKEY_REPLACE) == 0) { - /* insert new - if we're not restricted to replacing keyframes only */ - BezTriple *newb = static_cast( - MEM_callocN((fcu->totvert + 1) * sizeof(BezTriple), "beztriple")); - - /* Add the beztriples that should occur before the beztriple to be pasted - * (originally in fcu). */ - if (i > 0) { - memcpy(newb, fcu->bezt, i * sizeof(BezTriple)); - } - - /* add beztriple to paste at index i */ - *(newb + i) = *bezt; - - /* add the beztriples that occur after the beztriple to be pasted (originally in fcu) */ - if (i < fcu->totvert) { - memcpy(newb + i + 1, fcu->bezt + i, (fcu->totvert - i) * sizeof(BezTriple)); - } - - /* replace (+ free) old with new, only if necessary to do so */ - MEM_freeN(fcu->bezt); - fcu->bezt = newb; - - fcu->totvert++; - } - else { - return -1; - } - } - /* no keyframes already, but can only add if... - * 1) keyframing modes say that keyframes can only be replaced, so adding new ones won't know - * 2) there are no samples on the curve - * NOTE: maybe we may want to allow this later when doing samples -> bezt conversions, - * but for now, having both is asking for trouble - */ - else if ((flag & INSERTKEY_REPLACE) == 0 && (fcu->fpt == nullptr)) { - /* create new keyframes array */ - fcu->bezt = static_cast(MEM_callocN(sizeof(BezTriple), "beztriple")); - *(fcu->bezt) = *bezt; - fcu->totvert = 1; - } - /* cannot add anything */ - else { - /* return error code -1 to prevent any misunderstandings */ - return -1; - } - - /* we need to return the index, so that some tools which do post-processing can - * detect where we added the BezTriple in the array - */ - return i; -} - -/** - * Update the FCurve to allow insertion of `bezt` without modifying the curve shape. - * - * Checks whether it is necessary to apply Bezier subdivision due to involvement of non-auto - * handles. If necessary, changes `bezt` handles from Auto to Aligned. - * - * \param bezt: key being inserted - * \param prev: keyframe before that key - * \param next: keyframe after that key - */ -static void subdivide_nonauto_handles(const FCurve *fcu, - BezTriple *bezt, - BezTriple *prev, - BezTriple *next) -{ - if (prev->ipo != BEZT_IPO_BEZ || bezt->ipo != BEZT_IPO_BEZ) { - return; - } - - /* Don't change Vector handles, or completely auto regions. */ - const bool bezt_auto = BEZT_IS_AUTOH(bezt) || (bezt->h1 == HD_VECT && bezt->h2 == HD_VECT); - const bool prev_auto = BEZT_IS_AUTOH(prev) || (prev->h2 == HD_VECT); - const bool next_auto = BEZT_IS_AUTOH(next) || (next->h1 == HD_VECT); - if (bezt_auto && prev_auto && next_auto) { - return; - } - - /* Subdivide the curve. */ - float delta; - if (!BKE_fcurve_bezt_subdivide_handles(bezt, prev, next, &delta)) { - return; - } - - /* Decide when to force auto to manual. */ - if (!BEZT_IS_AUTOH(bezt)) { - return; - } - if ((prev_auto || next_auto) && fcu->auto_smoothing == FCURVE_SMOOTH_CONT_ACCEL) { - const float hx = bezt->vec[1][0] - bezt->vec[0][0]; - const float dx = bezt->vec[1][0] - prev->vec[1][0]; - - /* This mode always uses 1/3 of key distance for handle x size. */ - const bool auto_works_well = fabsf(hx - dx / 3.0f) < 0.001f; - if (auto_works_well) { - return; - } - } - - /* Turn off auto mode. */ - bezt->h1 = bezt->h2 = HD_ALIGN; -} - -int insert_vert_fcurve( - FCurve *fcu, float x, float y, eBezTriple_KeyframeType keyframe_type, eInsertKeyFlags flag) -{ - BezTriple beztr = {{{0}}}; - uint oldTot = fcu->totvert; - int a; - - /* set all three points, for nicer start position - * NOTE: +/- 1 on vec.x for left and right handles is so that 'free' handles work ok... - */ - beztr.vec[0][0] = x - 1.0f; - beztr.vec[0][1] = y; - beztr.vec[1][0] = x; - beztr.vec[1][1] = y; - beztr.vec[2][0] = x + 1.0f; - beztr.vec[2][1] = y; - beztr.f1 = beztr.f2 = beztr.f3 = SELECT; - - /* set default handle types and interpolation mode */ - if (flag & INSERTKEY_NO_USERPREF) { - /* for Py-API, we want scripts to have predictable behavior, - * hence the option to not depend on the userpref defaults - */ - beztr.h1 = beztr.h2 = HD_AUTO_ANIM; - beztr.ipo = BEZT_IPO_BEZ; - } - else { - /* For UI usage - defaults should come from the user-preferences and/or tool-settings. */ - beztr.h1 = beztr.h2 = U.keyhandles_new; /* use default handle type here */ - - /* use default interpolation mode, with exceptions for int/discrete values */ - beztr.ipo = U.ipo_new; - } - - /* interpolation type used is constrained by the type of values the curve can take */ - if (fcu->flag & FCURVE_DISCRETE_VALUES) { - beztr.ipo = BEZT_IPO_CONST; - } - else if ((beztr.ipo == BEZT_IPO_BEZ) && (fcu->flag & FCURVE_INT_VALUES)) { - beztr.ipo = BEZT_IPO_LIN; - } - - /* set keyframe type value (supplied), which should come from the scene settings in most cases */ - BEZKEYTYPE(&beztr) = keyframe_type; - - /* set default values for "easing" interpolation mode settings - * NOTE: Even if these modes aren't currently used, if users switch - * to these later, we want these to work in a sane way out of - * the box. - */ - - /* "back" easing - this value used to be used when overshoot=0, but that - * introduced discontinuities in how the param worked. */ - beztr.back = 1.70158f; - - /* "elastic" easing - values here were hand-optimized for a default duration of - * ~10 frames (typical mograph motion length) */ - beztr.amplitude = 0.8f; - beztr.period = 4.1f; - - /* add temp beztriple to keyframes */ - a = insert_bezt_fcurve(fcu, &beztr, flag); - BKE_fcurve_active_keyframe_set(fcu, &fcu->bezt[a]); - - /* what if 'a' is a negative index? - * for now, just exit to prevent any segfaults - */ - if (a < 0) { - return -1; - } - - /* Set handle-type and interpolation. */ - if ((fcu->totvert > 2) && (flag & INSERTKEY_REPLACE) == 0) { - BezTriple *bezt = (fcu->bezt + a); - - /* Set interpolation from previous (if available), - * but only if we didn't just replace some keyframe: - * - Replacement is indicated by no-change in number of verts. - * - When replacing, the user may have specified some interpolation that should be kept. - */ - if (fcu->totvert > oldTot) { - if (a > 0) { - bezt->ipo = (bezt - 1)->ipo; - } - else if (a < fcu->totvert - 1) { - bezt->ipo = (bezt + 1)->ipo; - } - - if (0 < a && a < (fcu->totvert - 1) && (flag & INSERTKEY_OVERWRITE_FULL) == 0) { - subdivide_nonauto_handles(fcu, bezt, bezt - 1, bezt + 1); - } - } - } - - /* don't recalculate handles if fast is set - * - this is a hack to make importers faster - * - we may calculate twice (due to auto-handle needing to be calculated twice) - */ - if ((flag & INSERTKEY_FAST) == 0) { - BKE_fcurve_handles_recalc(fcu); - } - - /* return the index at which the keyframe was added */ - return a; -} - /* ------------------------- Insert Key API ------------------------- */ void ED_keyframes_add(FCurve *fcu, int num_keys_to_add) @@ -893,14 +628,14 @@ static int clear_anim_v3d_exec(bContext *C, wmOperator * /*op*/) /* delete F-Curve completely */ if (can_delete) { - ANIM_fcurve_delete_from_animdata(nullptr, adt, fcu); + blender::animrig::animdata_fcurve_delete(nullptr, adt, fcu); DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM); changed = true; } } /* Delete the action itself if it is empty. */ - if (ANIM_remove_empty_action_from_animdata(adt)) { + if (blender::animrig::animdata_remove_empty_action(adt)) { changed = true; } } diff --git a/source/blender/editors/animation/keyingsets.cc b/source/blender/editors/animation/keyingsets.cc index e63aa354c1e..f90a435a69b 100644 --- a/source/blender/editors/animation/keyingsets.cc +++ b/source/blender/editors/animation/keyingsets.cc @@ -876,7 +876,7 @@ KeyingSet *ANIM_keyingset_get_from_idname(Scene *scene, const char *idname) bool ANIM_keyingset_context_ok_poll(bContext *C, KeyingSet *ks) { - if ((ks->flag & KEYINGSET_ABSOLUTE)) { + if (ks->flag & KEYINGSET_ABSOLUTE) { return true; } @@ -940,7 +940,7 @@ eModifyKey_Returns ANIM_validate_keyingset(bContext *C, } /* if relative Keying Sets, poll and build up the paths */ - if ((ks->flag & KEYINGSET_ABSOLUTE)) { + if (ks->flag & KEYINGSET_ABSOLUTE) { return MODIFYKEY_SUCCESS; } diff --git a/source/blender/editors/animation/time_scrub_ui.cc b/source/blender/editors/animation/time_scrub_ui.cc index f50ca97a1ba..d151d0d34ce 100644 --- a/source/blender/editors/animation/time_scrub_ui.cc +++ b/source/blender/editors/animation/time_scrub_ui.cc @@ -84,7 +84,7 @@ static void draw_current_frame(const Scene *scene, char frame_str[64]; get_current_time_str(scene, display_seconds, current_frame, frame_str, sizeof(frame_str)); float text_width = UI_fontstyle_string_width(fstyle, frame_str); - float box_width = MAX2(text_width + 8 * UI_SCALE_FAC, 24 * UI_SCALE_FAC); + float box_width = std::max(text_width + 8 * UI_SCALE_FAC, 24 * UI_SCALE_FAC); float box_padding = 3 * UI_SCALE_FAC; const int line_outline = max_ii(1, round_fl_to_int(1 * UI_SCALE_FAC)); diff --git a/source/blender/editors/armature/pose_slide.cc b/source/blender/editors/armature/pose_slide.cc index 038b60acd6b..7d8aba50f47 100644 --- a/source/blender/editors/armature/pose_slide.cc +++ b/source/blender/editors/armature/pose_slide.cc @@ -67,13 +67,14 @@ #include "ED_armature.hh" #include "ED_keyframes_edit.hh" #include "ED_keyframes_keylist.hh" -#include "ED_keyframing.hh" #include "ED_markers.hh" #include "ED_numinput.hh" #include "ED_screen.hh" #include "ED_space_api.hh" #include "ED_util.hh" +#include "ANIM_fcurve.hh" + #include "GPU_immediate.h" #include "GPU_immediate_util.h" #include "GPU_matrix.h" @@ -1740,7 +1741,7 @@ static void propagate_curve_values(ListBase /*tPChanFCurveLink*/ *pflinks, FCurve *fcu = (FCurve *)ld->data; const float current_fcu_value = evaluate_fcurve(fcu, source_frame); LISTBASE_FOREACH (FrameLink *, target_frame, target_frames) { - insert_vert_fcurve( + blender::animrig::insert_vert_fcurve( fcu, target_frame->frame, current_fcu_value, BEZT_KEYTYPE_KEYFRAME, INSERTKEY_NEEDED); } } diff --git a/source/blender/editors/geometry/geometry_attributes.cc b/source/blender/editors/geometry/geometry_attributes.cc index 708403ab679..12603f2fd0a 100644 --- a/source/blender/editors/geometry/geometry_attributes.cc +++ b/source/blender/editors/geometry/geometry_attributes.cc @@ -24,6 +24,10 @@ #include "BKE_paint.hh" #include "BKE_report.h" +#include "BLI_string.h" + +#include "BLT_translation.h" + #include "RNA_access.hh" #include "RNA_define.hh" #include "RNA_enum_types.hh" @@ -241,6 +245,16 @@ static int geometry_attribute_add_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } +static int geometry_attribute_add_invoke(bContext *C, wmOperator *op, const wmEvent *event) +{ + PropertyRNA *prop; + prop = RNA_struct_find_property(op->ptr, "name"); + if (!RNA_property_is_set(op->ptr, prop)) { + RNA_property_string_set(op->ptr, prop, DATA_("Attribute")); + } + return WM_operator_props_popup_confirm(C, op, event); +} + void GEOMETRY_OT_attribute_add(wmOperatorType *ot) { /* identifiers */ @@ -251,7 +265,7 @@ void GEOMETRY_OT_attribute_add(wmOperatorType *ot) /* api callbacks */ ot->poll = geometry_attributes_poll; ot->exec = geometry_attribute_add_exec; - ot->invoke = WM_operator_props_popup_confirm; + ot->invoke = geometry_attribute_add_invoke; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -259,7 +273,10 @@ void GEOMETRY_OT_attribute_add(wmOperatorType *ot) /* properties */ PropertyRNA *prop; - prop = RNA_def_string(ot->srna, "name", "Attribute", MAX_NAME, "Name", "Name of new attribute"); + /* The default name of the new attribute can be translated if new data translation is enabled, + * but since the user can choose it at invoke time, the translation happens in the invoke + * callback instead of here. */ + prop = RNA_def_string(ot->srna, "name", nullptr, MAX_NAME, "Name", "Name of new attribute"); RNA_def_property_flag(prop, PROP_SKIP_SAVE); prop = RNA_def_enum(ot->srna, @@ -348,6 +365,16 @@ static int geometry_color_attribute_add_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } +static int geometry_color_attribute_add_invoke(bContext *C, wmOperator *op, const wmEvent *event) +{ + PropertyRNA *prop; + prop = RNA_struct_find_property(op->ptr, "name"); + if (!RNA_property_is_set(op->ptr, prop)) { + RNA_property_string_set(op->ptr, prop, DATA_("Color")); + } + return WM_operator_props_popup_confirm(C, op, event); +} + enum class ConvertAttributeMode { Generic, VertexGroup, @@ -454,7 +481,7 @@ void GEOMETRY_OT_color_attribute_add(wmOperatorType *ot) /* api callbacks */ ot->poll = geometry_attributes_poll; ot->exec = geometry_color_attribute_add_exec; - ot->invoke = WM_operator_props_popup_confirm; + ot->invoke = geometry_color_attribute_add_invoke; ot->ui = geometry_color_attribute_add_ui; /* flags */ @@ -463,8 +490,11 @@ void GEOMETRY_OT_color_attribute_add(wmOperatorType *ot) /* properties */ PropertyRNA *prop; + /* The default name of the new attribute can be translated if new data translation is enabled, + * but since the user can choose it at invoke time, the translation happens in the invoke + * callback instead of here. */ prop = RNA_def_string( - ot->srna, "name", "Color", MAX_NAME, "Name", "Name of new color attribute"); + ot->srna, "name", nullptr, MAX_NAME, "Name", "Name of new color attribute"); RNA_def_property_flag(prop, PROP_SKIP_SAVE); prop = RNA_def_enum(ot->srna, diff --git a/source/blender/editors/gizmo_library/gizmo_types/snap3d_gizmo.cc b/source/blender/editors/gizmo_library/gizmo_types/snap3d_gizmo.cc index 7e204d0ac3d..590b4d08fbb 100644 --- a/source/blender/editors/gizmo_library/gizmo_types/snap3d_gizmo.cc +++ b/source/blender/editors/gizmo_library/gizmo_types/snap3d_gizmo.cc @@ -174,7 +174,7 @@ static void gizmo_snap_rna_snap_elem_index_get_fn(PointerRNA * /*ptr*/, static int gizmo_snap_rna_snap_srouce_type_get_fn(PointerRNA * /*ptr*/, PropertyRNA * /*prop*/) { V3DSnapCursorData *snap_data = ED_view3d_cursor_snap_data_get(); - return (int)snap_data->type_source; + return int(snap_data->type_source); } static void gizmo_snap_rna_snap_srouce_type_set_fn(PointerRNA * /*ptr*/, diff --git a/source/blender/editors/gpencil_legacy/gpencil_convert.cc b/source/blender/editors/gpencil_legacy/gpencil_convert.cc index 4b69ebd5684..62813c39b86 100644 --- a/source/blender/editors/gpencil_legacy/gpencil_convert.cc +++ b/source/blender/editors/gpencil_legacy/gpencil_convert.cc @@ -66,7 +66,7 @@ #include "UI_resources.hh" #include "UI_view2d.hh" -#include "ANIM_fcurve.hh" +#include "ANIM_action.hh" #include "ANIM_keyframing.hh" #include "ED_clip.hh" diff --git a/source/blender/editors/gpencil_legacy/gpencil_merge.cc b/source/blender/editors/gpencil_legacy/gpencil_merge.cc index 16ac2029c8e..61654bfd217 100644 --- a/source/blender/editors/gpencil_legacy/gpencil_merge.cc +++ b/source/blender/editors/gpencil_legacy/gpencil_merge.cc @@ -119,7 +119,7 @@ static bGPDstroke *gpencil_prepare_stroke(bContext *C, wmOperator *op, int totpo gpl, scene->r.cfra, eGP_GetFrame_Mode(add_frame_mode)); /* stroke */ - bGPDstroke *gps = BKE_gpencil_stroke_new(MAX2(ob->actcol - 1, 0), totpoints, brush->size); + bGPDstroke *gps = BKE_gpencil_stroke_new(std::max(ob->actcol - 1, 0), totpoints, brush->size); gps->flag |= GP_STROKE_SELECT; BKE_gpencil_stroke_select_index_set(gpd, gps); diff --git a/source/blender/editors/gpencil_legacy/gpencil_paint.cc b/source/blender/editors/gpencil_legacy/gpencil_paint.cc index d3e4170fc08..38718a84954 100644 --- a/source/blender/editors/gpencil_legacy/gpencil_paint.cc +++ b/source/blender/editors/gpencil_legacy/gpencil_paint.cc @@ -828,7 +828,7 @@ static short gpencil_stroke_addpoint(tGPsdata *p, /* color strength */ if (brush_settings->flag & GP_BRUSH_USE_STRENGTH_PRESSURE) { pt->strength *= BKE_curvemapping_evaluateF(brush_settings->curve_strength, 0, pressure); - CLAMP(pt->strength, MIN2(GPENCIL_STRENGTH_MIN, brush_settings->draw_strength), 1.0f); + CLAMP(pt->strength, std::min(GPENCIL_STRENGTH_MIN, brush_settings->draw_strength), 1.0f); } /* Set vertex colors for buffer. */ @@ -1090,7 +1090,7 @@ static void gpencil_stroke_newfrombuffer(tGPsdata *p) /* copy pressure and time */ pt->pressure = ptc->pressure; pt->strength = ptc->strength; - CLAMP(pt->strength, MIN2(GPENCIL_STRENGTH_MIN, brush_settings->draw_strength), 1.0f); + CLAMP(pt->strength, std::min(GPENCIL_STRENGTH_MIN, brush_settings->draw_strength), 1.0f); copy_v4_v4(pt->vert_color, ptc->vert_color); pt->time = ptc->time; /* Apply the vertex color to point. */ @@ -1124,7 +1124,7 @@ static void gpencil_stroke_newfrombuffer(tGPsdata *p) /* copy pressure and time */ pt->pressure = ptc->pressure; pt->strength = ptc->strength; - CLAMP(pt->strength, MIN2(GPENCIL_STRENGTH_MIN, brush_settings->draw_strength), 1.0f); + CLAMP(pt->strength, std::min(GPENCIL_STRENGTH_MIN, brush_settings->draw_strength), 1.0f); pt->time = ptc->time; /* Apply the vertex color to point. */ ED_gpencil_point_vertex_color_set(ts, brush, pt, ptc); @@ -1256,7 +1256,7 @@ static void gpencil_stroke_newfrombuffer(tGPsdata *p) /* copy pressure and time */ pt->pressure = ptc->pressure; pt->strength = ptc->strength; - CLAMP(pt->strength, MIN2(GPENCIL_STRENGTH_MIN, brush_settings->draw_strength), 1.0f); + CLAMP(pt->strength, std::min(GPENCIL_STRENGTH_MIN, brush_settings->draw_strength), 1.0f); copy_v4_v4(pt->vert_color, ptc->vert_color); pt->time = ptc->time; pt->uv_fac = ptc->uv_fac; diff --git a/source/blender/editors/gpencil_legacy/gpencil_utils.cc b/source/blender/editors/gpencil_legacy/gpencil_utils.cc index 26bb1e261fa..94328d66699 100644 --- a/source/blender/editors/gpencil_legacy/gpencil_utils.cc +++ b/source/blender/editors/gpencil_legacy/gpencil_utils.cc @@ -1774,7 +1774,7 @@ float ED_gpencil_cursor_radius(bContext *C, int x, int y) float brush_size = float(brush->size); bGPDlayer *gpl = BKE_gpencil_layer_active_get(gpd); if (gpl != nullptr) { - brush_size = MAX2(1.0f, brush_size + gpl->line_change); + brush_size = std::max(1.0f, brush_size + gpl->line_change); } /* Convert the 3D offset distance to a brush radius. */ diff --git a/source/blender/editors/grease_pencil/intern/grease_pencil_geom.cc b/source/blender/editors/grease_pencil/intern/grease_pencil_geom.cc index 6e219be13bb..2e1ee0f2c8f 100644 --- a/source/blender/editors/grease_pencil/intern/grease_pencil_geom.cc +++ b/source/blender/editors/grease_pencil/intern/grease_pencil_geom.cc @@ -1,4 +1,4 @@ -/* SPDX-FileCopyrightText: 2023 Blender Foundation +/* SPDX-FileCopyrightText: 2023 Blender Authors * * SPDX-License-Identifier: GPL-2.0-or-later */ diff --git a/source/blender/editors/grease_pencil/intern/grease_pencil_utils.cc b/source/blender/editors/grease_pencil/intern/grease_pencil_utils.cc index c599d329742..fc96a5b83ad 100644 --- a/source/blender/editors/grease_pencil/intern/grease_pencil_utils.cc +++ b/source/blender/editors/grease_pencil/intern/grease_pencil_utils.cc @@ -1,4 +1,4 @@ -/* SPDX-FileCopyrightText: 2023 Blender Foundation +/* SPDX-FileCopyrightText: 2023 Blender Authors * * SPDX-License-Identifier: GPL-2.0-or-later */ diff --git a/source/blender/editors/include/ED_anim_api.hh b/source/blender/editors/include/ED_anim_api.hh index 7ef2f2158d3..bfec6e8d9da 100644 --- a/source/blender/editors/include/ED_anim_api.hh +++ b/source/blender/editors/include/ED_anim_api.hh @@ -718,20 +718,6 @@ void ANIM_set_active_channel(bAnimContext *ac, */ bool ANIM_is_active_channel(bAnimListElem *ale); -/** - * Delete the F-Curve from the given AnimData block (if possible), - * as appropriate according to animation context. - */ -void ANIM_fcurve_delete_from_animdata(bAnimContext *ac, AnimData *adt, FCurve *fcu); - -/** - * Unlink the action from animdata if it's empty. - * - * If the action has no F-Curves, unlink it from AnimData if it did not - * come from a NLA Strip being tweaked. - */ -bool ANIM_remove_empty_action_from_animdata(AnimData *adt); - /* ************************************************ */ /* DRAWING API */ /* `anim_draw.cc` */ diff --git a/source/blender/editors/include/ED_keyframing.hh b/source/blender/editors/include/ED_keyframing.hh index 5a78a358170..4c3d9b365b9 100644 --- a/source/blender/editors/include/ED_keyframing.hh +++ b/source/blender/editors/include/ED_keyframing.hh @@ -67,38 +67,6 @@ void update_autoflags_fcurve_direct(FCurve *fcu, PropertyRNA *prop); /* -------- */ -/** - * \brief Lesser Key-framing API call. - * - * Use this when validation of necessary animation data isn't necessary as it already - * exists, and there is a #BezTriple that can be directly copied into the array. - * - * This function adds a given #BezTriple to an F-Curve. It will allocate - * memory for the array if needed, and will insert the #BezTriple into a - * suitable place in chronological order. - * - * \note any recalculate of the F-Curve that needs to be done will need to be done by the caller. - */ -int insert_bezt_fcurve(FCurve *fcu, const BezTriple *bezt, eInsertKeyFlags flag); - -/** - * \brief Main Key-framing API call. - * - * Use this when validation of necessary animation data isn't necessary as it - * already exists. It will insert a keyframe using the current value being keyframed. - * Returns the index at which a keyframe was added (or -1 if failed). - * - * This function is a wrapper for #insert_bezt_fcurve(), and should be used when - * adding a new keyframe to a curve, when the keyframe doesn't exist anywhere else yet. - * It returns the index at which the keyframe was added. - * - * \param keyframe_type: The type of keyframe (#eBezTriple_KeyframeType). - * \param flag: Optional flags (#eInsertKeyFlags) for controlling how keys get added - * and/or whether updates get done. - */ -int insert_vert_fcurve( - FCurve *fcu, float x, float y, eBezTriple_KeyframeType keyframe_type, eInsertKeyFlags flag); - /** * Add the given number of keyframes to the FCurve. Their coordinates are * uninitialized, so the curve should not be used without further attention. diff --git a/source/blender/editors/interface/interface.cc b/source/blender/editors/interface/interface.cc index 8fc9166190f..b2524a48416 100644 --- a/source/blender/editors/interface/interface.cc +++ b/source/blender/editors/interface/interface.cc @@ -540,8 +540,8 @@ static void ui_block_bounds_calc_popup( const int height = BLI_rctf_size_y(&block->rect); /* avoid divide by zero below, caused by calling with no UI, but better not crash */ - oldwidth = oldwidth > 0 ? oldwidth : MAX2(1, width); - oldheight = oldheight > 0 ? oldheight : MAX2(1, height); + oldwidth = oldwidth > 0 ? oldwidth : std::max(1, width); + oldheight = oldheight > 0 ? oldheight : std::max(1, height); /* offset block based on mouse position, user offset is scaled * along in case we resized the block in ui_block_bounds_calc_text */ @@ -2452,6 +2452,9 @@ bool ui_but_is_bool(const uiBut *but) UI_BTYPE_TOGGLE_N, UI_BTYPE_ICON_TOGGLE, UI_BTYPE_ICON_TOGGLE_N, + UI_BTYPE_CHECKBOX, + UI_BTYPE_CHECKBOX_N, + UI_BTYPE_BUT_TOGGLE, UI_BTYPE_TAB)) { return true; @@ -2932,7 +2935,7 @@ void ui_but_string_get_ex(uiBut *but, BLI_snprintf(str, str_maxncpy, "%.*f", prec, value); } else { - BLI_snprintf(str, str_maxncpy, "%.*f", MAX2(0, prec - 2), value * 100); + BLI_snprintf(str, str_maxncpy, "%.*f", std::max(0, prec - 2), value * 100); } } else { @@ -3756,7 +3759,7 @@ static void ui_but_build_drawstr_float(uiBut *but, double value) STR_CONCATF(but->drawstr, slen, "%.*f", precision, value); } else { - STR_CONCATF(but->drawstr, slen, "%.*f%%", MAX2(0, precision - 2), value * 100); + STR_CONCATF(but->drawstr, slen, "%.*f%%", std::max(0, precision - 2), value * 100); } } else if (ui_but_is_unit(but)) { diff --git a/source/blender/editors/interface/interface_context_menu.cc b/source/blender/editors/interface/interface_context_menu.cc index 686ed8b1620..e5e7a91dd2d 100644 --- a/source/blender/editors/interface/interface_context_menu.cc +++ b/source/blender/editors/interface/interface_context_menu.cc @@ -983,10 +983,16 @@ bool ui_popup_context_menu_for_button(bContext *C, uiBut *but, const wmEvent *ev * which isn't cheap to check. */ uiLayout *sub = uiLayoutColumn(layout, true); uiLayoutSetEnabled(sub, !id->asset_data); - uiItemO(sub, IFACE_("Mark as Asset"), ICON_ASSET_MANAGER, "ASSET_OT_mark_single"); + uiItemO(sub, + CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Mark as Asset"), + ICON_ASSET_MANAGER, + "ASSET_OT_mark_single"); sub = uiLayoutColumn(layout, true); uiLayoutSetEnabled(sub, id->asset_data); - uiItemO(sub, IFACE_("Clear Asset"), ICON_NONE, "ASSET_OT_clear_single"); + uiItemO(sub, + CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Clear Asset"), + ICON_NONE, + "ASSET_OT_clear_single"); uiItemS(layout); } diff --git a/source/blender/editors/interface/interface_draw.cc b/source/blender/editors/interface/interface_draw.cc index c470f47c61a..2ddfdd74a7b 100644 --- a/source/blender/editors/interface/interface_draw.cc +++ b/source/blender/editors/interface/interface_draw.cc @@ -1121,10 +1121,11 @@ static void ui_draw_colorband_handle(uint shdr_pos, GPU_blend(GPU_BLEND_ALPHA); /* Allow the lines to decrease as we get really small. */ - float line_width = MAX2(MIN2(U.pixelsize / 5.0f * fabs(half_width - 4.0f), U.pixelsize), 0.5f); + float line_width = std::max(std::min(U.pixelsize / 5.0f * fabs(half_width - 4.0f), U.pixelsize), + 0.5f); /* Make things transparent as we get tiny. */ - uchar alpha = MIN2(int(fabs(half_width - 2.0f) * 50.0f), 255); + uchar alpha = std::min(int(fabs(half_width - 2.0f) * 50.0f), 255); immBindBuiltinProgram(GPU_SHADER_3D_LINE_DASHED_UNIFORM_COLOR); diff --git a/source/blender/editors/interface/interface_handlers.cc b/source/blender/editors/interface/interface_handlers.cc index b3d02351e3f..2fdcf6c3f0b 100644 --- a/source/blender/editors/interface/interface_handlers.cc +++ b/source/blender/editors/interface/interface_handlers.cc @@ -4418,7 +4418,7 @@ static uiBut *ui_but_list_row_text_activate(bContext *C, const wmEvent *event, uiButtonActivateType activate_type) { - ARegion *region = CTX_wm_region(C); + ARegion *region = data->region; uiBut *labelbut = ui_but_find_mouse_over_ex(region, event->xy, true, false, nullptr, nullptr); if (labelbut && labelbut->type == UI_BTYPE_TEXT && !(labelbut->flag & UI_BUT_DISABLED)) { @@ -8053,16 +8053,15 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, const wmEvent * (event->modifier & (KM_SHIFT | KM_CTRL | KM_ALT | KM_OSKEY)) == 0 && (event->val == KM_PRESS)) { - ARegion *region = CTX_wm_region(C); /* For some button types that are typically representing entire sets of data, right-clicking * to spawn the context menu should also activate the item. This makes it clear which item * will be operated on. * Apply the button immediately, so context menu polls get the right active item. */ uiBut *clicked_view_item_but = but->type == UI_BTYPE_VIEW_ITEM ? but : - ui_view_item_find_mouse_over(region, event->xy); + ui_view_item_find_mouse_over(data->region, event->xy); if (clicked_view_item_but) { - UI_but_execute(C, region, clicked_view_item_but); + UI_but_execute(C, data->region, clicked_view_item_but); } /* RMB has two options now */ diff --git a/source/blender/editors/interface/interface_icons.cc b/source/blender/editors/interface/interface_icons.cc index 4c8f63eaed8..fed3a8f0d91 100644 --- a/source/blender/editors/interface/interface_icons.cc +++ b/source/blender/editors/interface/interface_icons.cc @@ -797,10 +797,10 @@ static ImBuf *create_mono_icon_with_border(ImBuf *buf, /* blur the alpha channel and store it in blurred_alpha_buffer */ const int blur_size = 2 / resolution_divider; for (int bx = 0; bx < icon_width; bx++) { - const int asx = MAX2(bx - blur_size, 0); + const int asx = std::max(bx - blur_size, 0); const int aex = MIN2(bx + blur_size + 1, icon_width); for (int by = 0; by < icon_height; by++) { - const int asy = MAX2(by - blur_size, 0); + const int asy = std::max(by - blur_size, 0); const int aey = MIN2(by + blur_size + 1, icon_height); /* blur alpha channel */ @@ -827,7 +827,7 @@ static ImBuf *create_mono_icon_with_border(ImBuf *buf, const int offset_write = (sy + by) * buf->x + (sx + bx); const float blurred_alpha = blurred_alpha_buffer[blurred_alpha_offset]; const float border_srgb[4] = { - 0, 0, 0, MIN2(1.0f, blurred_alpha * border_sharpness) * border_intensity}; + 0, 0, 0, std::min(1.0f, blurred_alpha * border_sharpness) * border_intensity}; const uint color_read = buf_rect[offset_write]; const uchar *orig_color = (uchar *)&color_read; diff --git a/source/blender/editors/interface/interface_layout.cc b/source/blender/editors/interface/interface_layout.cc index c7e11106fbb..3a1c38c4fb9 100644 --- a/source/blender/editors/interface/interface_layout.cc +++ b/source/blender/editors/interface/interface_layout.cc @@ -2818,7 +2818,7 @@ uiBut *ui_but_add_search(uiBut *but, search_but->rnasearchprop = searchprop; } - but->hardmax = MAX2(but->hardmax, 256.0f); + but->hardmax = std::max(but->hardmax, 256.0f); but->drawflag |= UI_BUT_ICON_LEFT | UI_BUT_TEXT_LEFT; if (RNA_property_is_unlink(prop)) { but->flag |= UI_BUT_VALUE_CLEAR; @@ -3773,7 +3773,7 @@ static void ui_litem_estimate_row(uiLayout *litem) min_size_flag = min_size_flag && (item->flag & UI_ITEM_FIXED_SIZE); litem->w += itemw; - litem->h = MAX2(itemh, litem->h); + litem->h = std::max(itemh, litem->h); if (item->next) { litem->w += litem->space; @@ -3787,7 +3787,7 @@ static void ui_litem_estimate_row(uiLayout *litem) static int ui_litem_min_width(int itemw) { - return MIN2(2 * UI_UNIT_X, itemw); + return std::min(2 * UI_UNIT_X, itemw); } static void ui_litem_layout_row(uiLayout *litem) @@ -3954,7 +3954,7 @@ static void ui_litem_estimate_column(uiLayout *litem, bool is_box) min_size_flag = min_size_flag && (item->flag & UI_ITEM_FIXED_SIZE); - litem->w = MAX2(litem->w, itemw); + litem->w = std::max(litem->w, itemw); litem->h += itemh; if (item->next && (!is_box || item != litem->items.first)) { @@ -4692,8 +4692,8 @@ static void ui_litem_estimate_absolute(uiLayout *litem) minx = min_ii(minx, itemx); miny = min_ii(miny, itemy); - litem->w = MAX2(litem->w, itemx + itemw); - litem->h = MAX2(litem->h, itemy + itemh); + litem->w = std::max(litem->w, itemx + itemw); + litem->h = std::max(litem->h, itemy + itemh); } litem->w -= minx; @@ -4783,7 +4783,7 @@ static void ui_litem_layout_split(uiLayout *litem) const int w = (litem->w - (tot - 1) * litem->space); int colw = w * percentage; - colw = MAX2(colw, 0); + colw = std::max(colw, 0); LISTBASE_FOREACH (uiItem *, item, &litem->items) { int itemh; @@ -4796,7 +4796,7 @@ static void ui_litem_layout_split(uiLayout *litem) const float width = extra_pixel + (w - int(w * percentage)) / (float(tot) - 1); extra_pixel = width - int(width); colw = int(width); - colw = MAX2(colw, 0); + colw = std::max(colw, 0); x += litem->space; } @@ -4818,8 +4818,8 @@ static void ui_litem_estimate_overlap(uiLayout *litem) int itemw, itemh; ui_item_size(item, &itemw, &itemh); - litem->w = MAX2(itemw, litem->w); - litem->h = MAX2(itemh, litem->h); + litem->w = std::max(itemw, litem->w); + litem->h = std::max(itemh, litem->h); } } @@ -4834,7 +4834,7 @@ static void ui_litem_layout_overlap(uiLayout *litem) ui_item_size(item, &itemw, &itemh); ui_item_position(item, x, y - itemh, litem->w, itemh); - litem->h = MAX2(litem->h, itemh); + litem->h = std::max(litem->h, itemh); } litem->x = x; diff --git a/source/blender/editors/interface/interface_region_popover.cc b/source/blender/editors/interface/interface_region_popover.cc index 98625513e3d..00edbde2fb9 100644 --- a/source/blender/editors/interface/interface_region_popover.cc +++ b/source/blender/editors/interface/interface_region_popover.cc @@ -255,7 +255,7 @@ uiPopupBlockHandle *ui_popover_panel_create( const int ui_units_x = (panel_type->ui_units_x == 0) ? UI_POPOVER_WIDTH_UNITS : panel_type->ui_units_x; /* Scale width by changes to Text Style point size. */ - const int text_points_max = MAX2(style->widget.points, style->widgetlabel.points); + const int text_points_max = std::max(style->widget.points, style->widgetlabel.points); pup->ui_size_x = ui_units_x * U.widget_unit * (text_points_max / float(UI_DEFAULT_TEXT_POINTS)); } diff --git a/source/blender/editors/interface/interface_style.cc b/source/blender/editors/interface/interface_style.cc index c7a602e7380..5b0be9f2abc 100644 --- a/source/blender/editors/interface/interface_style.cc +++ b/source/blender/editors/interface/interface_style.cc @@ -179,8 +179,8 @@ void UI_fontstyle_draw_ex(const uiFontStyle *fs, xofs = BLI_rcti_size_x(rect) - BLF_width(fs->uifont_id, str, str_len); } - yofs = MAX2(0, yofs); - xofs = MAX2(0, xofs); + yofs = std::max(0, yofs); + xofs = std::max(0, xofs); BLF_clipping(fs->uifont_id, rect->xmin, rect->ymin, rect->xmax, rect->ymax); BLF_position(fs->uifont_id, rect->xmin + xofs, rect->ymin + yofs, 0.0f); diff --git a/source/blender/editors/interface/interface_template_node_tree_interface.cc b/source/blender/editors/interface/interface_template_node_tree_interface.cc index 32551388f5d..d5ef7d3fc5f 100644 --- a/source/blender/editors/interface/interface_template_node_tree_interface.cc +++ b/source/blender/editors/interface/interface_template_node_tree_interface.cc @@ -1,4 +1,4 @@ -/* SPDX-FileCopyrightText: 2023 Blender Foundation +/* SPDX-FileCopyrightText: 2023 Blender Authors * * SPDX-License-Identifier: GPL-2.0-or-later */ diff --git a/source/blender/editors/interface/interface_templates.cc b/source/blender/editors/interface/interface_templates.cc index 16717b611eb..1144df8028a 100644 --- a/source/blender/editors/interface/interface_templates.cc +++ b/source/blender/editors/interface/interface_templates.cc @@ -3713,7 +3713,7 @@ static void colorband_buttons_layout(uiLayout *layout, UI_UNIT_Y, &coba->cur, 0.0, - float(MAX2(0, coba->tot - 1)), + float(std::max(0, coba->tot - 1)), 0, 0, TIP_("Choose active color stop")); @@ -3740,7 +3740,7 @@ static void colorband_buttons_layout(uiLayout *layout, UI_UNIT_Y, &coba->cur, 0.0, - float(MAX2(0, coba->tot - 1)), + float(std::max(0, coba->tot - 1)), 0, 0, TIP_("Choose active color stop")); @@ -5840,7 +5840,7 @@ void uiTemplatePalette(uiLayout *layout, PointerRNA *ptr, const char *propname, PropertyRNA *prop = RNA_struct_find_property(ptr, propname); uiBut *but = nullptr; - const int cols_per_row = MAX2(uiLayoutGetWidth(layout) / UI_UNIT_X, 1); + const int cols_per_row = std::max(uiLayoutGetWidth(layout) / UI_UNIT_X, 1); if (!prop) { RNA_warning("property not found: %s.%s", RNA_struct_identifier(ptr->type), propname); diff --git a/source/blender/editors/interface/interface_widgets.cc b/source/blender/editors/interface/interface_widgets.cc index 99640f5cf14..334cfcad7dc 100644 --- a/source/blender/editors/interface/interface_widgets.cc +++ b/source/blender/editors/interface/interface_widgets.cc @@ -1327,7 +1327,7 @@ static void widget_draw_preview(BIFIconID icon, float alpha, const rcti *rect) const int w = BLI_rcti_size_x(rect); const int h = BLI_rcti_size_y(rect); - const int size = MIN2(w, h) - PREVIEW_PAD * 2; + const int size = std::min(w, h) - PREVIEW_PAD * 2; if (size > 0) { const int x = rect->xmin + w / 2 - size / 2; @@ -3741,7 +3741,7 @@ static void widget_progress_type_bar(uiButProgress *but_progress, float w = factor * BLI_rcti_size_x(&rect_prog); /* Ensure minimum size. */ - w = MAX2(w, ofs); + w = std::max(w, ofs); rect_bar.xmax = rect_bar.xmin + w; diff --git a/source/blender/editors/mesh/editmesh_knife.cc b/source/blender/editors/mesh/editmesh_knife.cc index dc755a97bbc..8cc1bc0e142 100644 --- a/source/blender/editors/mesh/editmesh_knife.cc +++ b/source/blender/editors/mesh/editmesh_knife.cc @@ -4965,7 +4965,7 @@ static bool edbm_mesh_knife_point_isect(LinkNode *polys, const float cent_ss[2]) while (p) { const float(*mval_fl)[2] = static_cast(p->link); const int mval_tot = MEM_allocN_len(mval_fl) / sizeof(*mval_fl); - isect += int(isect_point_poly_v2(cent_ss, mval_fl, mval_tot - 1, false)); + isect += int(isect_point_poly_v2(cent_ss, mval_fl, mval_tot - 1)); p = p->next; } diff --git a/source/blender/editors/object/object_constraint.cc b/source/blender/editors/object/object_constraint.cc index 919ee96023b..7dca19c619b 100644 --- a/source/blender/editors/object/object_constraint.cc +++ b/source/blender/editors/object/object_constraint.cc @@ -60,7 +60,7 @@ #include "ED_object.hh" #include "ED_screen.hh" -#include "ANIM_fcurve.hh" +#include "ANIM_action.hh" #include "UI_interface.hh" #include "UI_resources.hh" diff --git a/source/blender/editors/object/object_gpencil_modifier.cc b/source/blender/editors/object/object_gpencil_modifier.cc index 244beea8983..6b648cc9fb5 100644 --- a/source/blender/editors/object/object_gpencil_modifier.cc +++ b/source/blender/editors/object/object_gpencil_modifier.cc @@ -1056,7 +1056,7 @@ static int time_segment_remove_exec(bContext *C, wmOperator *op) MEM_freeN(gpmd->segments); gpmd->segments = new_segments; - gpmd->segment_active_index = MAX2(gpmd->segment_active_index - 1, 0); + gpmd->segment_active_index = std::max(gpmd->segment_active_index - 1, 0); } gpmd->segments_len--; @@ -1300,7 +1300,7 @@ static int dash_segment_remove_exec(bContext *C, wmOperator *op) MEM_freeN(dmd->segments); dmd->segments = new_segments; - dmd->segment_active_index = MAX2(dmd->segment_active_index - 1, 0); + dmd->segment_active_index = std::max(dmd->segment_active_index - 1, 0); } dmd->segments_len--; diff --git a/source/blender/editors/object/object_relations.cc b/source/blender/editors/object/object_relations.cc index f7acd16c951..968711d0d74 100644 --- a/source/blender/editors/object/object_relations.cc +++ b/source/blender/editors/object/object_relations.cc @@ -103,7 +103,7 @@ #include "ED_screen.hh" #include "ED_view3d.hh" -#include "ANIM_fcurve.hh" +#include "ANIM_action.hh" #include "MOD_nodes.hh" diff --git a/source/blender/editors/screen/screen_draw.cc b/source/blender/editors/screen/screen_draw.cc index af9fc9b4be6..e0d13a3a8a7 100644 --- a/source/blender/editors/screen/screen_draw.cc +++ b/source/blender/editors/screen/screen_draw.cc @@ -226,14 +226,14 @@ void screen_draw_join_highlight(ScrArea *sa1, ScrArea *sa2) /* Rect of the combined areas. */ const bool vertical = SCREEN_DIR_IS_VERTICAL(dir); rctf combined{}; - combined.xmin = vertical ? MAX2(sa1->totrct.xmin, sa2->totrct.xmin) : - MIN2(sa1->totrct.xmin, sa2->totrct.xmin); - combined.xmax = vertical ? MIN2(sa1->totrct.xmax, sa2->totrct.xmax) : - MAX2(sa1->totrct.xmax, sa2->totrct.xmax); - combined.ymin = vertical ? MIN2(sa1->totrct.ymin, sa2->totrct.ymin) : - MAX2(sa1->totrct.ymin, sa2->totrct.ymin); - combined.ymax = vertical ? MAX2(sa1->totrct.ymax, sa2->totrct.ymax) : - MIN2(sa1->totrct.ymax, sa2->totrct.ymax); + combined.xmin = vertical ? std::max(sa1->totrct.xmin, sa2->totrct.xmin) : + std::min(sa1->totrct.xmin, sa2->totrct.xmin); + combined.xmax = vertical ? std::min(sa1->totrct.xmax, sa2->totrct.xmax) : + std::max(sa1->totrct.xmax, sa2->totrct.xmax); + combined.ymin = vertical ? std::min(sa1->totrct.ymin, sa2->totrct.ymin) : + std::max(sa1->totrct.ymin, sa2->totrct.ymin); + combined.ymax = vertical ? std::max(sa1->totrct.ymax, sa2->totrct.ymax) : + std::min(sa1->totrct.ymax, sa2->totrct.ymax); uint pos_id = GPU_vertformat_attr_add( immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); @@ -243,18 +243,18 @@ void screen_draw_join_highlight(ScrArea *sa1, ScrArea *sa2) /* Highlight source (sa1) within combined area. */ immUniformColor4fv(blender::float4{1.0f, 1.0f, 1.0f, 0.10f}); immRectf(pos_id, - MAX2(sa1->totrct.xmin, combined.xmin), - MAX2(sa1->totrct.ymin, combined.ymin), - MIN2(sa1->totrct.xmax, combined.xmax), - MIN2(sa1->totrct.ymax, combined.ymax)); + std::max(float(sa1->totrct.xmin), combined.xmin), + std::max(float(sa1->totrct.ymin), combined.ymin), + std::min(float(sa1->totrct.xmax), combined.xmax), + std::min(float(sa1->totrct.ymax), combined.ymax)); /* Highlight destination (sa2) within combined area. */ immUniformColor4fv(blender::float4{0.0f, 0.0f, 0.0f, 0.25f}); immRectf(pos_id, - MAX2(sa2->totrct.xmin, combined.xmin), - MAX2(sa2->totrct.ymin, combined.ymin), - MIN2(sa2->totrct.xmax, combined.xmax), - MIN2(sa2->totrct.ymax, combined.ymax)); + std::max(float(sa2->totrct.xmin), combined.xmin), + std::max(float(sa2->totrct.ymin), combined.ymin), + std::min(float(sa2->totrct.xmax), combined.xmax), + std::min(float(sa2->totrct.ymax), combined.ymax)); int offset1; int offset2; diff --git a/source/blender/editors/screen/screen_edit.cc b/source/blender/editors/screen/screen_edit.cc index fab0ca57336..9c71265b0a4 100644 --- a/source/blender/editors/screen/screen_edit.cc +++ b/source/blender/editors/screen/screen_edit.cc @@ -281,8 +281,8 @@ eScreenDir area_getorientation(ScrArea *sa_a, ScrArea *sa_b) short bottom_b = sa_b->v1->vec.y; /* How much these areas share a common edge. */ - short overlapx = MIN2(right_a, right_b) - MAX2(left_a, left_b); - short overlapy = MIN2(top_a, top_b) - MAX2(bottom_a, bottom_b); + short overlapx = std::min(right_a, right_b) - std::max(left_a, left_b); + short overlapy = std::min(top_a, top_b) - std::max(bottom_a, bottom_b); /* Minimum overlap required. */ const short minx = MIN3(AREAJOINTOLERANCEX, right_a - left_a, right_b - left_b); @@ -381,8 +381,8 @@ static bool screen_areas_can_align(bScreen *screen, ScrArea *sa1, ScrArea *sa2, /* Areas that are _smaller_ than minimum sizes, sharing an edge to be moved. See #100772. */ if (SCREEN_DIR_IS_VERTICAL(dir)) { - const short xmin = MIN2(sa1->v1->vec.x, sa2->v1->vec.x); - const short xmax = MAX2(sa1->v3->vec.x, sa2->v3->vec.x); + const short xmin = std::min(sa1->v1->vec.x, sa2->v1->vec.x); + const short xmax = std::max(sa1->v3->vec.x, sa2->v3->vec.x); LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) { if (ELEM(area, sa1, sa2)) { continue; @@ -396,8 +396,8 @@ static bool screen_areas_can_align(bScreen *screen, ScrArea *sa1, ScrArea *sa2, } } else { - const short ymin = MIN2(sa1->v1->vec.y, sa2->v1->vec.y); - const short ymax = MAX2(sa1->v3->vec.y, sa2->v3->vec.y); + const short ymin = std::min(sa1->v1->vec.y, sa2->v1->vec.y); + const short ymax = std::max(sa1->v3->vec.y, sa2->v3->vec.y); LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) { if (ELEM(area, sa1, sa2)) { continue; @@ -581,7 +581,7 @@ bool screen_area_close(bContext *C, bScreen *screen, ScrArea *area) const int ar_length = vertical ? (neighbor->v3->vec.x - neighbor->v1->vec.x) : (neighbor->v3->vec.y - neighbor->v1->vec.y); /* Calculate the ratio of the lengths of the shared edges. */ - float alignment = MIN2(area_length, ar_length) / float(MAX2(area_length, ar_length)); + float alignment = std::min(area_length, ar_length) / float(std::max(area_length, ar_length)); if (alignment > best_alignment) { best_alignment = alignment; sa2 = neighbor; diff --git a/source/blender/editors/screen/screen_geometry.cc b/source/blender/editors/screen/screen_geometry.cc index cdef6ec1a5c..712d9efa671 100644 --- a/source/blender/editors/screen/screen_geometry.cc +++ b/source/blender/editors/screen/screen_geometry.cc @@ -85,7 +85,7 @@ ScrEdge *screen_geom_area_map_find_active_scredge(const ScrAreaMap *area_map, if ((se->v1->vec.y > bounds_rect->ymin) && (se->v1->vec.y < (bounds_rect->ymax - 1))) { short min, max; min = MIN2(se->v1->vec.x, se->v2->vec.x); - max = MAX2(se->v1->vec.x, se->v2->vec.x); + max = std::max(se->v1->vec.x, se->v2->vec.x); if (abs(my - se->v1->vec.y) <= safety && mx >= min && mx <= max) { return se; @@ -96,7 +96,7 @@ ScrEdge *screen_geom_area_map_find_active_scredge(const ScrAreaMap *area_map, if ((se->v1->vec.x > bounds_rect->xmin) && (se->v1->vec.x < (bounds_rect->xmax - 1))) { short min, max; min = MIN2(se->v1->vec.y, se->v2->vec.y); - max = MAX2(se->v1->vec.y, se->v2->vec.y); + max = std::max(se->v1->vec.y, se->v2->vec.y); if (abs(mx - se->v1->vec.x) <= safety && my >= min && my <= max) { return se; diff --git a/source/blender/editors/sculpt_paint/paint_cursor.cc b/source/blender/editors/sculpt_paint/paint_cursor.cc index ee588755dbc..4b9a9f6e26e 100644 --- a/source/blender/editors/sculpt_paint/paint_cursor.cc +++ b/source/blender/editors/sculpt_paint/paint_cursor.cc @@ -1472,7 +1472,7 @@ static void paint_draw_2D_view_brush_cursor_default(PaintCursorContext *pcontext static void grease_pencil_eraser_draw(PaintCursorContext *pcontext) { - float radius = static_cast(BKE_brush_size_get(pcontext->scene, pcontext->brush)); + float radius = float(BKE_brush_size_get(pcontext->scene, pcontext->brush)); /* Red-ish color with alpha. */ immUniformColor4ub(255, 100, 100, 20); diff --git a/source/blender/editors/sculpt_paint/paint_weight.cc b/source/blender/editors/sculpt_paint/paint_weight.cc index 9c8cc8e3a97..4445af648f1 100644 --- a/source/blender/editors/sculpt_paint/paint_weight.cc +++ b/source/blender/editors/sculpt_paint/paint_weight.cc @@ -220,10 +220,10 @@ static float wpaint_blend(const VPaint *wp, static float wpaint_clamp_monotonic(float oldval, float curval, float newval) { if (newval < oldval) { - return MIN2(newval, curval); + return std::min(newval, curval); } if (newval > oldval) { - return MAX2(newval, curval); + return std::max(newval, curval); } return newval; } diff --git a/source/blender/editors/sculpt_paint/sculpt_pose.cc b/source/blender/editors/sculpt_paint/sculpt_pose.cc index f5266fc5037..892d54f5dc5 100644 --- a/source/blender/editors/sculpt_paint/sculpt_pose.cc +++ b/source/blender/editors/sculpt_paint/sculpt_pose.cc @@ -220,7 +220,7 @@ static void pose_brush_grow_factor_task(Object *ob, /* Grow the factor. */ SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, vd.vertex, ni) { float vmask_f = prev_mask[ni.index]; - max = MAX2(vmask_f, max); + max = std::max(vmask_f, max); } SCULPT_VERTEX_NEIGHBORS_ITER_END(ni); diff --git a/source/blender/editors/sound/sound_ops.cc b/source/blender/editors/sound/sound_ops.cc index b9cc586b64c..05341a7b409 100644 --- a/source/blender/editors/sound/sound_ops.cc +++ b/source/blender/editors/sound/sound_ops.cc @@ -357,7 +357,7 @@ static int sound_mixdown_exec(bContext *C, wmOperator *op) BLI_path_abs(filepath, BKE_main_blendfile_path(bmain)); - const double fps = (double(scene_eval->r.frs_sec) / double(scene_eval->r.frs_sec_base)); + const double fps = double(scene_eval->r.frs_sec) / double(scene_eval->r.frs_sec_base); const int start_frame = scene_eval->r.sfra; const int end_frame = scene_eval->r.efra; diff --git a/source/blender/editors/space_action/action_draw.cc b/source/blender/editors/space_action/action_draw.cc index 124d5facc36..90a9627d5c6 100644 --- a/source/blender/editors/space_action/action_draw.cc +++ b/source/blender/editors/space_action/action_draw.cc @@ -280,7 +280,7 @@ static void draw_backdrops(bAnimContext *ac, ListBase &anim_data, View2D *v2d, u immRectf(pos, ac->scene->r.sfra, ymin, ac->scene->r.efra, ymax); /* Color overlay outside the start/end frame range get a more transparent overlay. */ - immUniformColor3ubvAlpha(color, MIN2(255, color[3] / 2)); + immUniformColor3ubvAlpha(color, std::min(255, color[3] / 2)); immRectf(pos, v2d->cur.xmin, ymin, ac->scene->r.sfra, ymax); immRectf(pos, ac->scene->r.efra, ymin, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymax); } @@ -299,7 +299,7 @@ static void draw_backdrops(bAnimContext *ac, ListBase &anim_data, View2D *v2d, u immRectf(pos, ac->scene->r.sfra, ymin, ac->scene->r.efra, ymax); /* Color overlay outside the start/end frame range get a more transparent overlay. */ - immUniformColor3ubvAlpha(color, MIN2(255, color[3] / 2)); + immUniformColor3ubvAlpha(color, std::min(255, color[3] / 2)); immRectf(pos, v2d->cur.xmin, ymin, ac->scene->r.sfra, ymax); immRectf(pos, ac->scene->r.efra, ymin, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymax); } diff --git a/source/blender/editors/space_action/action_edit.cc b/source/blender/editors/space_action/action_edit.cc index 92a6fe790e4..ee06603dd72 100644 --- a/source/blender/editors/space_action/action_edit.cc +++ b/source/blender/editors/space_action/action_edit.cc @@ -43,6 +43,8 @@ #include "UI_view2d.hh" +#include "ANIM_animdata.hh" +#include "ANIM_fcurve.hh" #include "ANIM_keyframing.hh" #include "ED_anim_api.hh" #include "ED_gpencil_legacy.hh" @@ -794,7 +796,7 @@ static void insert_grease_pencil_key(bAnimContext *ac, bool changed = false; if (hold_previous) { const FramesMapKey active_frame_number = layer->frame_key_at(current_frame_number); - if ((active_frame_number == -1) || (layer->frames().lookup(active_frame_number).is_null())) { + if ((active_frame_number == -1) || layer->frames().lookup(active_frame_number).is_null()) { /* There is no active frame to hold to, or it's a null frame. Therefore just insert a blank * frame. */ changed = grease_pencil->insert_blank_frame( @@ -859,7 +861,7 @@ static void insert_fcurve_key(bAnimContext *ac, } const float curval = evaluate_fcurve(fcu, cfra); - insert_vert_fcurve( + blender::animrig::insert_vert_fcurve( fcu, cfra, curval, eBezTriple_KeyframeType(ts->keyframe_type), eInsertKeyFlags(0)); } @@ -1109,7 +1111,7 @@ static bool delete_action_keys(bAnimContext *ac) /* Only delete curve too if it won't be doing anything anymore */ if (BKE_fcurve_is_empty(fcu)) { - ANIM_fcurve_delete_from_animdata(ac, adt, fcu); + blender::animrig::animdata_fcurve_delete(ac, adt, fcu); ale->key_data = nullptr; } } diff --git a/source/blender/editors/space_clip/tracking_ops_track.cc b/source/blender/editors/space_clip/tracking_ops_track.cc index 75f57f57de7..29b78c253a6 100644 --- a/source/blender/editors/space_clip/tracking_ops_track.cc +++ b/source/blender/editors/space_clip/tracking_ops_track.cc @@ -153,10 +153,10 @@ static bool track_markers_initjob(bContext *C, TrackMarkersJob *tmj, bool backwa /* Limit frames to be tracked by user setting. */ if (frames_limit) { if (backwards) { - tmj->efra = MAX2(tmj->efra, tmj->sfra - frames_limit); + tmj->efra = std::max(tmj->efra, tmj->sfra - frames_limit); } else { - tmj->efra = MIN2(tmj->efra, tmj->sfra + frames_limit); + tmj->efra = std::min(tmj->efra, tmj->sfra + frames_limit); } } diff --git a/source/blender/editors/space_file/file_draw.cc b/source/blender/editors/space_file/file_draw.cc index 3d93b535245..ff350b48602 100644 --- a/source/blender/editors/space_file/file_draw.cc +++ b/source/blender/editors/space_file/file_draw.cc @@ -925,7 +925,7 @@ void file_draw_list(const bContext *C, ARegion *region) bool do_drag; uchar text_col[4]; const bool draw_columnheader = (params->display == FILE_VERTICALDISPLAY); - const float thumb_icon_aspect = MIN2(64.0f / float(params->thumbnail_size), 1.0f); + const float thumb_icon_aspect = std::min(64.0f / float(params->thumbnail_size), 1.0f); numfiles = filelist_files_ensure(files); diff --git a/source/blender/editors/space_file/filelist.cc b/source/blender/editors/space_file/filelist.cc index 3d2d471dd5a..21de331c44b 100644 --- a/source/blender/editors/space_file/filelist.cc +++ b/source/blender/editors/space_file/filelist.cc @@ -4131,7 +4131,7 @@ static void filelist_readjob_update(void *flrjv) /* if no new_entries_num, this is NOP */ BLI_movelisttolist(&fl_intern->entries, &new_entries); - flrj->filelist->filelist.entries_num = MAX2(entries_num, 0) + new_entries_num; + flrj->filelist->filelist.entries_num = std::max(entries_num, 0) + new_entries_num; } static void filelist_readjob_endjob(void *flrjv) diff --git a/source/blender/editors/space_file/filesel.cc b/source/blender/editors/space_file/filesel.cc index 8ddd88c5af0..7f96f4dd4aa 100644 --- a/source/blender/editors/space_file/filesel.cc +++ b/source/blender/editors/space_file/filesel.cc @@ -1086,7 +1086,7 @@ void ED_fileselect_init_layout(SpaceFile *sfile, ARegion *region) (layout->tile_h + 2 * layout->tile_border_y); file_attribute_columns_init(params, layout); - layout->rows = MAX2(rowcount, numfiles); + layout->rows = std::max(rowcount, numfiles); BLI_assert(layout->rows != 0); layout->height = sfile->layout->rows * (layout->tile_h + 2 * layout->tile_border_y) + layout->tile_border_y * 2 + layout->offset_top; diff --git a/source/blender/editors/space_graph/graph_edit.cc b/source/blender/editors/space_graph/graph_edit.cc index a901686b1f2..4caa05c7d82 100644 --- a/source/blender/editors/space_graph/graph_edit.cc +++ b/source/blender/editors/space_graph/graph_edit.cc @@ -47,6 +47,8 @@ #include "UI_interface.hh" #include "UI_view2d.hh" +#include "ANIM_animdata.hh" +#include "ANIM_fcurve.hh" #include "ANIM_keyframing.hh" #include "ED_anim_api.hh" #include "ED_keyframes_edit.hh" @@ -179,7 +181,7 @@ static void insert_graph_keys(bAnimContext *ac, eGraphKeys_InsertKey_Types mode) } /* Insert keyframe directly into the F-Curve. */ - insert_vert_fcurve( + blender::animrig::insert_vert_fcurve( fcu, x, y, eBezTriple_KeyframeType(ts->keyframe_type), eInsertKeyFlags(0)); ale->update |= ANIM_UPDATE_DEFAULT; @@ -228,7 +230,7 @@ static void insert_graph_keys(bAnimContext *ac, eGraphKeys_InsertKey_Types mode) } const float curval = evaluate_fcurve_only_curve(fcu, cfra); - insert_vert_fcurve( + blender::animrig::insert_vert_fcurve( fcu, cfra, curval, eBezTriple_KeyframeType(ts->keyframe_type), eInsertKeyFlags(0)); } @@ -345,7 +347,7 @@ static int graphkeys_click_insert_exec(bContext *C, wmOperator *op) val = val * scale - offset; /* Insert keyframe on the specified frame + value. */ - insert_vert_fcurve( + blender::animrig::insert_vert_fcurve( fcu, frame, val, eBezTriple_KeyframeType(ts->keyframe_type), eInsertKeyFlags(0)); ale->update |= ANIM_UPDATE_DEPS; @@ -764,7 +766,7 @@ static bool delete_graph_keys(bAnimContext *ac) /* Only delete curve too if it won't be doing anything anymore. */ if (BKE_fcurve_is_empty(fcu)) { - ANIM_fcurve_delete_from_animdata(ac, adt, fcu); + blender::animrig::animdata_fcurve_delete(ac, adt, fcu); ale->key_data = nullptr; } } diff --git a/source/blender/editors/space_info/info_stats.cc b/source/blender/editors/space_info/info_stats.cc index 74024f75da8..49a27d62c4f 100644 --- a/source/blender/editors/space_info/info_stats.cc +++ b/source/blender/editors/space_info/info_stats.cc @@ -870,7 +870,7 @@ void ED_info_draw_stats( else if ((ob) && (ob->type == OB_LAMP)) { stats_row(col1, labels[LIGHTS], col2, stats_fmt.totlampsel, stats_fmt.totlamp, y, height); } - else if ((object_mode == OB_MODE_OBJECT) && ob && (ELEM(ob->type, OB_MESH, OB_FONT))) { + else if ((object_mode == OB_MODE_OBJECT) && ob && ELEM(ob->type, OB_MESH, OB_FONT)) { /* Object mode with the active object a mesh or text object. */ stats_row(col1, labels[VERTS], col2, stats_fmt.totvertsel, stats_fmt.totvert, y, height); stats_row(col1, labels[EDGES], col2, stats_fmt.totedgesel, stats_fmt.totedge, y, height); diff --git a/source/blender/editors/space_info/textview.cc b/source/blender/editors/space_info/textview.cc index 5680b36aec1..60171eb6e33 100644 --- a/source/blender/editors/space_info/textview.cc +++ b/source/blender/editors/space_info/textview.cc @@ -99,14 +99,14 @@ static int textview_wrap_offsets( int i, end; /* Offset as unicode code-point. */ int j; /* Offset as bytes. */ const int tab_columns = TVC_TAB_COLUMNS; - const int column_width_max = MAX2(tab_columns, BLI_UTF8_WIDTH_MAX); + const int column_width_max = std::max(tab_columns, BLI_UTF8_WIDTH_MAX); *r_lines = 1; - *r_offsets = static_cast( - MEM_callocN(sizeof(**r_offsets) * - (str_len * column_width_max / MAX2(1, width - (column_width_max - 1)) + 1), - __func__)); + *r_offsets = static_cast(MEM_callocN( + sizeof(**r_offsets) * + (str_len * column_width_max / std::max(1, width - (column_width_max - 1)) + 1), + __func__)); (*r_offsets)[0] = 0; for (i = 0, end = width, j = 0; j < str_len && str[j]; j += BLI_str_utf8_size_safe(str + j)) { @@ -158,7 +158,7 @@ static bool textview_draw_string(TextViewDrawState *tds, /* Wrap. */ if (tot_lines > 1) { int iofs = int(float(y_next - tds->mval[1]) / tds->lheight); - ofs += offsets[MIN2(iofs, tot_lines - 1)]; + ofs += offsets[std::min(iofs, tot_lines - 1)]; } /* Last part. */ diff --git a/source/blender/editors/space_node/node_draw.cc b/source/blender/editors/space_node/node_draw.cc index f8250f2651e..43d1fd29211 100644 --- a/source/blender/editors/space_node/node_draw.cc +++ b/source/blender/editors/space_node/node_draw.cc @@ -2228,6 +2228,7 @@ static void node_draw_panels(bNodeTree &ntree, const bNode &node, uiBlock &block 0.0f, 0.0f, ""); + UI_but_func_pushed_state_set(but, [&state](const uiBut &) { return state.is_collapsed(); }); UI_but_func_set( but, node_panel_toggle_button_cb, const_cast(&state), &ntree); diff --git a/source/blender/editors/space_node/node_edit.cc b/source/blender/editors/space_node/node_edit.cc index 1c818c1b7bc..a107531d01c 100644 --- a/source/blender/editors/space_node/node_edit.cc +++ b/source/blender/editors/space_node/node_edit.cc @@ -1133,7 +1133,7 @@ bool node_is_previewable(const SpaceNode &snode, const bNodeTree &ntree, const b return false; } if (ntree.type == NTREE_SHADER) { - return U.experimental.use_shader_node_previews && !(node.is_frame()); + return U.experimental.use_shader_node_previews && !node.is_frame(); } return node.typeinfo->flag & NODE_PREVIEW; } diff --git a/source/blender/editors/space_node/node_shader_preview.cc b/source/blender/editors/space_node/node_shader_preview.cc index 5de59f3d948..9735881d895 100644 --- a/source/blender/editors/space_node/node_shader_preview.cc +++ b/source/blender/editors/space_node/node_shader_preview.cc @@ -261,7 +261,7 @@ static bNodeSocket *node_find_preview_socket(bNodeTree &ntree, bNode &node) if (socket == nullptr) { socket = get_main_socket(ntree, node, SOCK_IN); if (socket != nullptr && socket->link == nullptr) { - if (!(ELEM(socket->type, SOCK_FLOAT, SOCK_VECTOR, SOCK_RGBA))) { + if (!ELEM(socket->type, SOCK_FLOAT, SOCK_VECTOR, SOCK_RGBA)) { /* We can not preview a socket with no link and no manual value. */ return nullptr; } diff --git a/source/blender/editors/space_outliner/outliner_draw.cc b/source/blender/editors/space_outliner/outliner_draw.cc index b264043cb49..c7eda9afa82 100644 --- a/source/blender/editors/space_outliner/outliner_draw.cc +++ b/source/blender/editors/space_outliner/outliner_draw.cc @@ -3249,7 +3249,7 @@ static void outliner_draw_iconrow(bContext *C, if ((merged->tree_element[index] == nullptr) || (active > merged->active[index])) { merged->tree_element[index] = te; } - merged->active[index] = MAX2(active, merged->active[index]); + merged->active[index] = std::max(active, merged->active[index]); } } diff --git a/source/blender/editors/space_outliner/tree/tree_element_linked_object.cc b/source/blender/editors/space_outliner/tree/tree_element_linked_object.cc index 83b51b82356..036f7b62b83 100644 --- a/source/blender/editors/space_outliner/tree/tree_element_linked_object.cc +++ b/source/blender/editors/space_outliner/tree/tree_element_linked_object.cc @@ -1,4 +1,4 @@ -/* SPDX-FileCopyrightText: 2023 Blender Foundation +/* SPDX-FileCopyrightText: 2023 Blender Authors * * SPDX-License-Identifier: GPL-2.0-or-later */ diff --git a/source/blender/editors/space_outliner/tree/tree_element_linked_object.hh b/source/blender/editors/space_outliner/tree/tree_element_linked_object.hh index 6128aa1f32f..0eac37d1ade 100644 --- a/source/blender/editors/space_outliner/tree/tree_element_linked_object.hh +++ b/source/blender/editors/space_outliner/tree/tree_element_linked_object.hh @@ -1,4 +1,4 @@ -/* SPDX-FileCopyrightText: 2023 Blender Foundation +/* SPDX-FileCopyrightText: 2023 Blender Authors * * SPDX-License-Identifier: GPL-2.0-or-later */ diff --git a/source/blender/editors/space_outliner/tree/tree_element_modifier.cc b/source/blender/editors/space_outliner/tree/tree_element_modifier.cc index 6f4b74ec953..234aa98df29 100644 --- a/source/blender/editors/space_outliner/tree/tree_element_modifier.cc +++ b/source/blender/editors/space_outliner/tree/tree_element_modifier.cc @@ -1,4 +1,4 @@ -/* SPDX-FileCopyrightText: 2023 Blender Foundation +/* SPDX-FileCopyrightText: 2023 Blender Authors * * SPDX-License-Identifier: GPL-2.0-or-later */ diff --git a/source/blender/editors/space_outliner/tree/tree_element_modifier.hh b/source/blender/editors/space_outliner/tree/tree_element_modifier.hh index 4183b7bf921..1b2be7206e8 100644 --- a/source/blender/editors/space_outliner/tree/tree_element_modifier.hh +++ b/source/blender/editors/space_outliner/tree/tree_element_modifier.hh @@ -1,4 +1,4 @@ -/* SPDX-FileCopyrightText: 2023 Blender Foundation +/* SPDX-FileCopyrightText: 2023 Blender Authors * * SPDX-License-Identifier: GPL-2.0-or-later */ diff --git a/source/blender/editors/space_text/text_draw.cc b/source/blender/editors/space_text/text_draw.cc index d0353e6ba69..0c9cc2dab29 100644 --- a/source/blender/editors/space_text/text_draw.cc +++ b/source/blender/editors/space_text/text_draw.cc @@ -821,7 +821,7 @@ int text_get_visible_lines(const SpaceText *st, ARegion *region, const char *str while (chars--) { if (i + columns - start > max) { lines++; - start = MIN2(end, i); + start = std::min(end, i); end += max; } else if (ELEM(ch, ' ', '-')) { @@ -927,7 +927,7 @@ static void calc_text_rcts(SpaceText *st, ARegion *region, rcti *scroll, rcti *b sell_off = text_get_span_wrap( st, region, static_cast(st->text->lines.first), st->text->sell); lhlstart = MIN2(curl_off, sell_off); - lhlend = MAX2(curl_off, sell_off); + lhlend = std::max(curl_off, sell_off); if (ltexth > 0) { hlstart = (lhlstart * pix_available) / ltexth; @@ -1085,7 +1085,7 @@ static void draw_suggestion_list(const SpaceText *st, const TextDrawContext *tdc boxh = SUGG_LIST_SIZE * lheight + 8; if (x + boxw > region->winx) { - x = MAX2(0, region->winx - boxw); + x = std::max(0, region->winx - boxw); } /* not needed but stands out nicer */ diff --git a/source/blender/editors/space_view3d/view3d_draw.cc b/source/blender/editors/space_view3d/view3d_draw.cc index a379a113ab7..d82cb16c13b 100644 --- a/source/blender/editors/space_view3d/view3d_draw.cc +++ b/source/blender/editors/space_view3d/view3d_draw.cc @@ -177,7 +177,7 @@ void ED_view3d_update_viewmat(Depsgraph *depsgraph, len_sc = float(max_ii(BLI_rcti_size_x(rect), BLI_rcti_size_y(rect))); } else { - len_sc = float(MAX2(region->winx, region->winy)); + len_sc = float(std::max(region->winx, region->winy)); } rv3d->pixsize = len_px / len_sc; diff --git a/source/blender/editors/space_view3d/view3d_gizmo_ruler.cc b/source/blender/editors/space_view3d/view3d_gizmo_ruler.cc index b37045a46d8..c8c6321933e 100644 --- a/source/blender/editors/space_view3d/view3d_gizmo_ruler.cc +++ b/source/blender/editors/space_view3d/view3d_gizmo_ruler.cc @@ -963,7 +963,7 @@ static void gizmo_ruler_draw(const bContext *C, wmGizmo *gz) ((len < (numstr_size[0] + bg_margin + bg_margin)) && (fabs(rot_90_vec[0]) < 0.5f))) { /* Super short, or quite short and also shallow angle. Position below line. */ - posit[1] = MIN2(co_ss[0][1], co_ss[2][1]) - numstr_size[1] - bg_margin - bg_margin; + posit[1] = std::min(co_ss[0][1], co_ss[2][1]) - numstr_size[1] - bg_margin - bg_margin; } else if (fabs(rot_90_vec[0]) < 0.2f) { /* Very shallow angle. Shift down by text height. */ diff --git a/source/blender/editors/transform/transform.cc b/source/blender/editors/transform/transform.cc index afaa51c98ab..d1aa543f64c 100644 --- a/source/blender/editors/transform/transform.cc +++ b/source/blender/editors/transform/transform.cc @@ -1533,7 +1533,7 @@ static void drawAutoKeyWarning(TransInfo *t, ARegion *region) offset = U.gizmo_size_navigate_v3d; break; case USER_MINI_AXIS_TYPE_MINIMAL: - offset = U.rvisize * MIN2((U.pixelsize / U.scale_factor), 1.0f) * 2.5f; + offset = U.rvisize * std::min((U.pixelsize / U.scale_factor), 1.0f) * 2.5f; break; case USER_MINI_AXIS_TYPE_NONE: offset = U.rvisize; diff --git a/source/blender/editors/transform/transform_convert_action.cc b/source/blender/editors/transform/transform_convert_action.cc index 69d2c647858..e5ceb3cec8e 100644 --- a/source/blender/editors/transform/transform_convert_action.cc +++ b/source/blender/editors/transform/transform_convert_action.cc @@ -498,7 +498,7 @@ static int GreasePencilLayerToTransData(TransData *td, }; const blender::Map &frame_map = - duplicate ? (layer->runtime->trans_data_.temp_frames_buffer) : (layer->frames()); + duplicate ? (layer->runtime->trans_data_.temp_frames_buffer) : layer->frames(); for (const auto [frame_number, frame] : frame_map.items()) { grease_pencil_frame_to_trans_data(frame_number, frame.is_selected()); diff --git a/source/blender/editors/transform/transform_convert_mesh.cc b/source/blender/editors/transform/transform_convert_mesh.cc index 4f356774dd1..aecefe6938e 100644 --- a/source/blender/editors/transform/transform_convert_mesh.cc +++ b/source/blender/editors/transform/transform_convert_mesh.cc @@ -1964,10 +1964,10 @@ static void mesh_partial_update(TransInfo *t, /* Promote the partial update types based on the previous state * so the values that no longer modified are reset before being left as-is. * Needed for translation which can toggle snap-to-normal during transform. */ - const enum ePartialType partial_for_looptri = MAX2(partial_state->for_looptri, - partial_state_prev->for_looptri); - const enum ePartialType partial_for_normals = MAX2(partial_state->for_normals, - partial_state_prev->for_normals); + const enum ePartialType partial_for_looptri = std::max(partial_state->for_looptri, + partial_state_prev->for_looptri); + const enum ePartialType partial_for_normals = std::max(partial_state->for_normals, + partial_state_prev->for_normals); if ((partial_for_looptri == PARTIAL_TYPE_ALL) && (partial_for_normals == PARTIAL_TYPE_ALL) && (em->bm->totvert == em->bm->totvertsel)) diff --git a/source/blender/editors/uvedit/uvedit_smart_stitch.cc b/source/blender/editors/uvedit/uvedit_smart_stitch.cc index 9e38cb3f5b7..756b8207832 100644 --- a/source/blender/editors/uvedit/uvedit_smart_stitch.cc +++ b/source/blender/editors/uvedit/uvedit_smart_stitch.cc @@ -2580,7 +2580,7 @@ static int stitch_modal(bContext *C, wmOperator *op, const wmEvent *event) case WHEELDOWNMOUSE: if ((event->val == KM_PRESS) && (event->modifier & KM_ALT)) { ssc->limit_dist -= 0.01f; - ssc->limit_dist = MAX2(0.01f, ssc->limit_dist); + ssc->limit_dist = std::max(0.01f, ssc->limit_dist); if (!stitch_process_data(ssc, active_state, scene, false)) { stitch_cancel(C, op); return OPERATOR_CANCELLED; diff --git a/source/blender/gpencil_modifiers_legacy/intern/MOD_gpencil_legacy_build.cc b/source/blender/gpencil_modifiers_legacy/intern/MOD_gpencil_legacy_build.cc index 16988f0a31b..31f4f5dc983 100644 --- a/source/blender/gpencil_modifiers_legacy/intern/MOD_gpencil_legacy_build.cc +++ b/source/blender/gpencil_modifiers_legacy/intern/MOD_gpencil_legacy_build.cc @@ -6,6 +6,7 @@ * \ingroup modifiers */ +#include /* For `min/max`. */ #include #include #include @@ -358,7 +359,7 @@ static void build_sequential(Object *ob, float curgps_delay = fabs(cell->gps->inittime - (cell - 1)->gps->inittime) - last_pointtime; if (0 < curgps_delay) { - sumtime += MIN2(curgps_delay, GP_BUILD_MAXGAP); + sumtime += std::min(curgps_delay, GP_BUILD_MAXGAP); } } } @@ -634,7 +635,7 @@ static void build_concurrent(BuildGpencilModifierData *mmd, case GP_BUILD_TIMEALIGN_START: /* all start on frame 1 */ { /* Scale fac to fit relative_len */ - const float scaled_fac = use_fac / MAX2(relative_len, PSEUDOINVERSE_EPSILON); + const float scaled_fac = use_fac / std::max(relative_len, PSEUDOINVERSE_EPSILON); if (reverse) { points_num = int(roundf((1.0f - scaled_fac) * gps->totpoints)); @@ -651,7 +652,8 @@ static void build_concurrent(BuildGpencilModifierData *mmd, */ const float start_fac = 1.0f - relative_len; - const float scaled_fac = (use_fac - start_fac) / MAX2(relative_len, PSEUDOINVERSE_EPSILON); + const float scaled_fac = (use_fac - start_fac) / + std::max(relative_len, PSEUDOINVERSE_EPSILON); if (reverse) { points_num = int(roundf((1.0f - scaled_fac) * gps->totpoints)); diff --git a/source/blender/gpencil_modifiers_legacy/intern/MOD_gpencil_legacy_lineart.cc b/source/blender/gpencil_modifiers_legacy/intern/MOD_gpencil_legacy_lineart.cc index a57283cf6f6..25620d44fda 100644 --- a/source/blender/gpencil_modifiers_legacy/intern/MOD_gpencil_legacy_lineart.cc +++ b/source/blender/gpencil_modifiers_legacy/intern/MOD_gpencil_legacy_lineart.cc @@ -545,7 +545,7 @@ static bool anything_showing_through(PointerRNA *ptr) const int level_start = RNA_int_get(ptr, "level_start"); const int level_end = RNA_int_get(ptr, "level_end"); if (use_multiple_levels) { - return (MAX2(level_start, level_end) > 0); + return (std::max(level_start, level_end) > 0); } return (level_start > 0); } diff --git a/source/blender/gpencil_modifiers_legacy/intern/lineart/lineart_chain.cc b/source/blender/gpencil_modifiers_legacy/intern/lineart/lineart_chain.cc index 8b224ad0a0e..a631e2b03f5 100644 --- a/source/blender/gpencil_modifiers_legacy/intern/lineart/lineart_chain.cc +++ b/source/blender/gpencil_modifiers_legacy/intern/lineart/lineart_chain.cc @@ -14,6 +14,7 @@ #include "lineart_intern.h" +#include /* For `min/max`. */ #include #define LRT_OTHER_VERT(e, vt) ((vt) == (e)->v1 ? (e)->v2 : ((vt) == (e)->v2 ? (e)->v1 : nullptr)) @@ -1380,7 +1381,7 @@ void MOD_lineart_chain_offset_towards_camera(LineartData *ld, float dist, bool u sub_v3_v3v3(dir, cam, eci->gpos); float len_lim = dot_v3v3(view, dir) - ld->conf.near_clip; normalize_v3_v3(view_clamp, view); - mul_v3_fl(view_clamp, MIN2(dist, len_lim)); + mul_v3_fl(view_clamp, std::min(dist, len_lim)); add_v3_v3(eci->gpos, view_clamp); } } diff --git a/source/blender/gpencil_modifiers_legacy/intern/lineart/lineart_cpu.cc b/source/blender/gpencil_modifiers_legacy/intern/lineart/lineart_cpu.cc index 37423c2e60d..fb4bb3936c4 100644 --- a/source/blender/gpencil_modifiers_legacy/intern/lineart/lineart_cpu.cc +++ b/source/blender/gpencil_modifiers_legacy/intern/lineart/lineart_cpu.cc @@ -57,6 +57,8 @@ #include "lineart_intern.h" +#include /* For `min/max`. */ + struct LineartIsecSingle { double v1[3], v2[3]; LineartTriangle *tri1, *tri2; @@ -443,7 +445,7 @@ static int lineart_occlusion_make_task_info(LineartData *ld, LineartRenderTaskIn else { rti->pending_edges.array = &ld->pending_edges.array[starting_index]; int remaining = ld->pending_edges.next - starting_index; - rti->pending_edges.max = MIN2(remaining, LRT_THREAD_EDGE_COUNT); + rti->pending_edges.max = std::min(remaining, LRT_THREAD_EDGE_COUNT); res = 1; } @@ -3070,7 +3072,7 @@ static bool lineart_triangle_edge_image_space_occlusion(const LineartTriangle *t return true; } if (dot_1f >= 0 && dot_2f <= 0 && (dot_v1 || dot_v2)) { - *from = MAX2(cut, cross_ratios[cross_v1]); + *from = std::max(cut, cross_ratios[cross_v1]); *to = MIN2(1, cross_ratios[cross_v2]); if (*from >= *to) { return false; @@ -3079,7 +3081,7 @@ static bool lineart_triangle_edge_image_space_occlusion(const LineartTriangle *t } if (dot_1f <= 0 && dot_2f >= 0 && (dot_v1 || dot_v2)) { *from = MAX2(0, cross_ratios[cross_v1]); - *to = MIN2(cut, cross_ratios[cross_v2]); + *to = std::min(cut, cross_ratios[cross_v2]); if (*from >= *to) { return false; } @@ -3616,7 +3618,7 @@ static LineartData *lineart_create_render_buffer(Scene *scene, ld->qtree.recursive_level = LRT_TILE_RECURSIVE_ORTHO; } - double asp = (double(ld->w) / double(ld->h)); + double asp = double(ld->w) / double(ld->h); int fit = BKE_camera_sensor_fit(c->sensor_fit, ld->w, ld->h); ld->conf.shift_x = fit == CAMERA_SENSOR_FIT_HOR ? c->shiftx : c->shiftx / asp; ld->conf.shift_y = fit == CAMERA_SENSOR_FIT_VERT ? c->shifty : c->shifty * asp; @@ -4064,7 +4066,8 @@ static bool lineart_bounding_area_edge_intersect(LineartData * /*fb*/, double c1, c; if (((converted[0] = ba->l) > MAX2(l[0], r[0])) || ((converted[1] = ba->r) < MIN2(l[0], r[0])) || - ((converted[2] = ba->b) > MAX2(l[1], r[1])) || ((converted[3] = ba->u) < MIN2(l[1], r[1]))) + ((converted[2] = ba->b) > MAX2(l[1], r[1])) || + ((converted[3] = ba->u) < std::min(l[1], r[1]))) { return false; } @@ -4444,9 +4447,9 @@ static bool lineart_get_edge_bounding_areas( } b[0] = MIN2(e->v1->fbcoord[0], e->v2->fbcoord[0]); - b[1] = MAX2(e->v1->fbcoord[0], e->v2->fbcoord[0]); + b[1] = std::max(e->v1->fbcoord[0], e->v2->fbcoord[0]); b[2] = MIN2(e->v1->fbcoord[1], e->v2->fbcoord[1]); - b[3] = MAX2(e->v1->fbcoord[1], e->v2->fbcoord[1]); + b[3] = std::max(e->v1->fbcoord[1], e->v2->fbcoord[1]); if (b[0] > 1 || b[1] < -1 || b[2] > 1 || b[3] < -1) { return false; @@ -5382,7 +5385,7 @@ static void lineart_gpencil_generate(LineartCache *cache, if (invert_input) { use_weight = 1 - use_weight; } - gdw->weight = MAX2(use_weight, gdw->weight); + gdw->weight = std::max(use_weight, gdw->weight); sindex++; } diff --git a/source/blender/gpu/GPU_material.h b/source/blender/gpu/GPU_material.h index 33e41aee344..3d9a984575e 100644 --- a/source/blender/gpu/GPU_material.h +++ b/source/blender/gpu/GPU_material.h @@ -320,6 +320,7 @@ struct GPUUniformBuf *GPU_material_create_sss_profile_ubo(void); bool GPU_material_has_surface_output(GPUMaterial *mat); bool GPU_material_has_volume_output(GPUMaterial *mat); +bool GPU_material_has_displacement_output(GPUMaterial *mat); void GPU_material_flag_set(GPUMaterial *mat, eGPUMaterialFlag flag); bool GPU_material_flag_get(const GPUMaterial *mat, eGPUMaterialFlag flag); diff --git a/source/blender/gpu/intern/gpu_index_buffer.cc b/source/blender/gpu/intern/gpu_index_buffer.cc index 05e23033eb1..4b3103dbbe1 100644 --- a/source/blender/gpu/intern/gpu_index_buffer.cc +++ b/source/blender/gpu/intern/gpu_index_buffer.cc @@ -19,6 +19,7 @@ #include "GPU_platform.h" +#include /* For `min/max`. */ #include #define KEEP_SINGLE_COPY 1 @@ -109,8 +110,8 @@ void GPU_indexbuf_add_generic_vert(GPUIndexBufBuilder *builder, uint v) assert(v <= builder->max_allowed_index); #endif builder->data[builder->index_len++] = v; - builder->index_min = MIN2(builder->index_min, v); - builder->index_max = MAX2(builder->index_max, v); + builder->index_min = std::min(builder->index_min, v); + builder->index_max = std::max(builder->index_max, v); } void GPU_indexbuf_add_primitive_restart(GPUIndexBufBuilder *builder) @@ -170,9 +171,9 @@ void GPU_indexbuf_set_point_vert(GPUIndexBufBuilder *builder, uint elem, uint v1 BLI_assert(builder->prim_type == GPU_PRIM_POINTS); BLI_assert(elem < builder->max_index_len); builder->data[elem++] = v1; - builder->index_min = MIN2(builder->index_min, v1); - builder->index_max = MAX2(builder->index_max, v1); - builder->index_len = MAX2(builder->index_len, elem); + builder->index_min = std::min(builder->index_min, v1); + builder->index_max = std::max(builder->index_max, v1); + builder->index_len = std::max(builder->index_len, elem); } void GPU_indexbuf_set_line_verts(GPUIndexBufBuilder *builder, uint elem, uint v1, uint v2) @@ -187,7 +188,7 @@ void GPU_indexbuf_set_line_verts(GPUIndexBufBuilder *builder, uint elem, uint v1 builder->data[idx++] = v2; builder->index_min = MIN3(builder->index_min, v1, v2); builder->index_max = MAX3(builder->index_max, v1, v2); - builder->index_len = MAX2(builder->index_len, idx); + builder->index_len = std::max(builder->index_len, idx); } void GPU_indexbuf_set_tri_verts(GPUIndexBufBuilder *builder, uint elem, uint v1, uint v2, uint v3) @@ -205,7 +206,7 @@ void GPU_indexbuf_set_tri_verts(GPUIndexBufBuilder *builder, uint elem, uint v1, builder->index_min = MIN4(builder->index_min, v1, v2, v3); builder->index_max = MAX4(builder->index_max, v1, v2, v3); - builder->index_len = MAX2(builder->index_len, idx); + builder->index_len = std::max(builder->index_len, idx); } void GPU_indexbuf_set_point_restart(GPUIndexBufBuilder *builder, uint elem) @@ -213,7 +214,7 @@ void GPU_indexbuf_set_point_restart(GPUIndexBufBuilder *builder, uint elem) BLI_assert(builder->prim_type == GPU_PRIM_POINTS); BLI_assert(elem < builder->max_index_len); builder->data[elem++] = builder->restart_index_value; - builder->index_len = MAX2(builder->index_len, elem); + builder->index_len = std::max(builder->index_len, elem); builder->uses_restart_indices = true; } @@ -224,7 +225,7 @@ void GPU_indexbuf_set_line_restart(GPUIndexBufBuilder *builder, uint elem) uint idx = elem * 2; builder->data[idx++] = builder->restart_index_value; builder->data[idx++] = builder->restart_index_value; - builder->index_len = MAX2(builder->index_len, idx); + builder->index_len = std::max(builder->index_len, idx); builder->uses_restart_indices = true; } @@ -236,7 +237,7 @@ void GPU_indexbuf_set_tri_restart(GPUIndexBufBuilder *builder, uint elem) builder->data[idx++] = builder->restart_index_value; builder->data[idx++] = builder->restart_index_value; builder->data[idx++] = builder->restart_index_value; - builder->index_len = MAX2(builder->index_len, idx); + builder->index_len = std::max(builder->index_len, idx); builder->uses_restart_indices = true; } diff --git a/source/blender/gpu/intern/gpu_material.cc b/source/blender/gpu/intern/gpu_material.cc index 97fcd273ce2..b50ff574b0c 100644 --- a/source/blender/gpu/intern/gpu_material.cc +++ b/source/blender/gpu/intern/gpu_material.cc @@ -130,6 +130,7 @@ struct GPUMaterial { /** DEPRECATED: To remove. */ bool has_surface_output; bool has_volume_output; + bool has_displacement_output; /** DEPRECATED: To remove. */ GPUUniformBuf *sss_profile; /* UBO containing SSS profile. */ GPUTexture *sss_tex_profile; /* Texture containing SSS profile. */ @@ -433,7 +434,7 @@ static void compute_sss_kernel(GPUSssKernelData *kd, const float radii[3], int s /* Minimum radius */ rad[0] = MAX2(radii[0], 1e-15f); rad[1] = MAX2(radii[1], 1e-15f); - rad[2] = MAX2(radii[2], 1e-15f); + rad[2] = std::max(radii[2], 1e-15f); kd->avg_inv_radius = 3.0f / (rad[0] + rad[1] + rad[2]); @@ -662,6 +663,7 @@ void GPU_material_output_displacement(GPUMaterial *material, GPUNodeLink *link) { if (!material->graph.outlink_displacement) { material->graph.outlink_displacement = link; + material->has_displacement_output = true; } } @@ -779,6 +781,11 @@ bool GPU_material_has_volume_output(GPUMaterial *mat) return mat->has_volume_output; } +bool GPU_material_has_displacement_output(GPUMaterial *mat) +{ + return mat->has_displacement_output; +} + void GPU_material_flag_set(GPUMaterial *mat, eGPUMaterialFlag flag) { mat->flag |= flag; diff --git a/source/blender/gpu/metal/mtl_memory.mm b/source/blender/gpu/metal/mtl_memory.mm index b2ddefe13fa..c95c6a6f113 100644 --- a/source/blender/gpu/metal/mtl_memory.mm +++ b/source/blender/gpu/metal/mtl_memory.mm @@ -70,10 +70,17 @@ void MTLBufferPool::free() delete completed_safelist_queue_[safe_pool_free_index]; } completed_safelist_queue_.clear(); + + safelist_lock_.lock(); if (current_free_list_ != nullptr) { delete current_free_list_; current_free_list_ = nullptr; } + if (prev_free_buffer_list_ != nullptr) { + delete prev_free_buffer_list_; + prev_free_buffer_list_ = nullptr; + } + safelist_lock_.unlock(); /* Clear and release memory pools. */ for (std::multiset *buffer_pool : diff --git a/source/blender/gpu/metal/mtl_shader_generator.mm b/source/blender/gpu/metal/mtl_shader_generator.mm index 3e99a6d9cb8..cfdbfc3566a 100644 --- a/source/blender/gpu/metal/mtl_shader_generator.mm +++ b/source/blender/gpu/metal/mtl_shader_generator.mm @@ -622,7 +622,7 @@ void extract_shared_memory_blocks(MSLGeneratorInterface &msl_iface, } int len = c_next_space - c; BLI_assert(len < 256); - BLI_strncpy(buf, c, len); + BLI_strncpy(buf, c, len + 1); new_shared_block.type_name = std::string(buf); /* Read var-name. @@ -662,13 +662,13 @@ void extract_shared_memory_blocks(MSLGeneratorInterface &msl_iface, } len = varname_end - c; BLI_assert(len < 256); - BLI_strncpy(buf, c, len); + BLI_strncpy(buf, c, len + 1); new_shared_block.varname = std::string(buf); /* Determine if array. */ if (new_shared_block.is_array) { int len = c_expr_end - c_array_begin; - BLI_strncpy(buf, c_array_begin, len); + BLI_strncpy(buf, c_array_begin, len + 1); new_shared_block.array_decl = std::string(buf); } diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_principled.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_principled.glsl index 2978d7e9b87..c1a95d5ad82 100644 --- a/source/blender/gpu/shaders/material/gpu_shader_material_principled.glsl +++ b/source/blender/gpu/shaders/material/gpu_shader_material_principled.glsl @@ -224,7 +224,8 @@ void node_bsdf_principled(vec4 base_color, /* Diffuse component */ if (true) { - diffuse_data.sss_radius = max(subsurface_radius * subsurface_scale, vec3(0.0)); + diffuse_data.sss_radius = subsurface_weight * + max(subsurface_radius * subsurface_scale, vec3(0.0)); diffuse_data.sss_id = uint(do_sss); diffuse_data.color += weight * diffuse_sss_base_color.rgb * coat_tint.rgb; } diff --git a/source/blender/gpu/vulkan/vk_backend.cc b/source/blender/gpu/vulkan/vk_backend.cc index a354994c7f6..e28f42eebab 100644 --- a/source/blender/gpu/vulkan/vk_backend.cc +++ b/source/blender/gpu/vulkan/vk_backend.cc @@ -92,6 +92,7 @@ void VKBackend::detect_workarounds(VKDevice &device) workarounds.shader_output_layer = true; workarounds.shader_output_viewport_index = true; + device.workarounds_ = workarounds; return; } diff --git a/source/blender/imbuf/intern/format_svg.cc b/source/blender/imbuf/intern/format_svg.cc index c14cdfe7ce9..eb51ca5de6f 100644 --- a/source/blender/imbuf/intern/format_svg.cc +++ b/source/blender/imbuf/intern/format_svg.cc @@ -50,9 +50,9 @@ ImBuf *imb_load_filepath_thumbnail_svg(const char *filepath, colorspace_set_default_role(colorspace, IM_MAX_SPACE, COLOR_ROLE_DEFAULT_BYTE); - const float scale = float(max_thumb_size) / MAX2(w, h); - const int dest_w = MAX2(int(w * scale), 1); - const int dest_h = MAX2(int(h * scale), 1); + const float scale = float(max_thumb_size) / std::max(w, h); + const int dest_w = std::max(int(w * scale), 1); + const int dest_h = std::max(int(h * scale), 1); ImBuf *ibuf = IMB_allocImBuf(dest_w, dest_h, 32, IB_rect); if (ibuf != nullptr) { diff --git a/source/blender/imbuf/intern/jpeg.cc b/source/blender/imbuf/intern/jpeg.cc index b266a98b44b..3d6503d920f 100644 --- a/source/blender/imbuf/intern/jpeg.cc +++ b/source/blender/imbuf/intern/jpeg.cc @@ -278,7 +278,7 @@ static ImBuf *ibJpegImageFromCinfo( if (max_size > 0) { /* `libjpeg` can more quickly decompress while scaling down to 1/2, 1/4, 1/8, * while `libjpeg-turbo` can also do 3/8, 5/8, etc. But max is 1/8. */ - float scale = float(max_size) / MAX2(cinfo->image_width, cinfo->image_height); + float scale = float(max_size) / std::max(cinfo->image_width, cinfo->image_height); cinfo->scale_denom = 8; cinfo->scale_num = max_uu(1, min_uu(8, ceill(scale * float(cinfo->scale_denom)))); cinfo->dct_method = JDCT_FASTEST; diff --git a/source/blender/imbuf/intern/openexr/openexr_api.cpp b/source/blender/imbuf/intern/openexr/openexr_api.cpp index 397676e17d8..01f39b38c47 100644 --- a/source/blender/imbuf/intern/openexr/openexr_api.cpp +++ b/source/blender/imbuf/intern/openexr/openexr_api.cpp @@ -1793,7 +1793,7 @@ static int exr_has_rgb(MultiPartInputFile &file, const char *rgb_channels[3]) std::transform(lower_case_name.begin(), lower_case_name.end(), lower_case_name.begin(), - [](unsigned char c) { return std::tolower(c); }); + [](uchar c) { return std::tolower(c); }); if (header.channels().findChannel(channel_names[i]) || header.channels().findChannel(lower_case_name)) @@ -2202,10 +2202,10 @@ ImBuf *imb_load_filepath_thumbnail_openexr(const char *filepath, colorspace_set_default_role(colorspace, IM_MAX_SPACE, COLOR_ROLE_DEFAULT_FLOAT); } - float scale_factor = MIN2(float(max_thumb_size) / float(source_w), - float(max_thumb_size) / float(source_h)); - int dest_w = MAX2(int(source_w * scale_factor), 1); - int dest_h = MAX2(int(source_h * scale_factor), 1); + float scale_factor = std::min(float(max_thumb_size) / float(source_w), + float(max_thumb_size) / float(source_h)); + int dest_w = std::max(int(source_w * scale_factor), 1); + int dest_h = std::max(int(source_h * scale_factor), 1); ImBuf *ibuf = IMB_allocImBuf(dest_w, dest_h, 32, IB_rectfloat); diff --git a/source/blender/imbuf/intern/stereoimbuf.cc b/source/blender/imbuf/intern/stereoimbuf.cc index ac50bec7987..69110102656 100644 --- a/source/blender/imbuf/intern/stereoimbuf.cc +++ b/source/blender/imbuf/intern/stereoimbuf.cc @@ -137,7 +137,7 @@ static void imb_stereo3d_write_anaglyph(const Stereo3DData *s3d, enum eStereo3dA to[0] = from[r][0]; to[1] = from[g][1]; to[2] = from[b][2]; - to[3] = MAX2(from[0][3], from[1][3]); + to[3] = std::max(from[0][3], from[1][3]); } } } diff --git a/source/blender/imbuf/intern/webp.cc b/source/blender/imbuf/intern/webp.cc index 8fbe95b32c0..56c164a2b8f 100644 --- a/source/blender/imbuf/intern/webp.cc +++ b/source/blender/imbuf/intern/webp.cc @@ -114,9 +114,9 @@ ImBuf *imb_load_filepath_thumbnail_webp(const char *filepath, *r_width = size_t(config.input.width); *r_height = size_t(config.input.height); - const float scale = float(max_thumb_size) / MAX2(config.input.width, config.input.height); - const int dest_w = MAX2(int(config.input.width * scale), 1); - const int dest_h = MAX2(int(config.input.height * scale), 1); + const float scale = float(max_thumb_size) / std::max(config.input.width, config.input.height); + const int dest_w = std::max(int(config.input.width * scale), 1); + const int dest_h = std::max(int(config.input.height * scale), 1); colorspace_set_default_role(colorspace, IM_MAX_SPACE, COLOR_ROLE_DEFAULT_BYTE); ImBuf *ibuf = IMB_allocImBuf(dest_w, dest_h, 32, IB_rect); diff --git a/source/blender/io/collada/AnimationImporter.cpp b/source/blender/io/collada/AnimationImporter.cpp index 80a49af58d8..5ed8026c697 100644 --- a/source/blender/io/collada/AnimationImporter.cpp +++ b/source/blender/io/collada/AnimationImporter.cpp @@ -15,6 +15,8 @@ #include "ED_keyframing.hh" +#include "ANIM_fcurve.hh" + #include "BLI_listbase.h" #include "BLI_math_matrix.h" #include "BLI_string.h" @@ -65,7 +67,7 @@ void AnimationImporter::add_bezt(FCurve *fcu, bez.ipo = ipo; /* use default interpolation mode here... */ bez.f1 = bez.f2 = bez.f3 = SELECT; bez.h1 = bez.h2 = HD_AUTO; - insert_bezt_fcurve(fcu, &bez, INSERTKEY_NOFLAGS); + blender::animrig::insert_bezt_fcurve(fcu, &bez, INSERTKEY_NOFLAGS); BKE_fcurve_handles_recalc(fcu); } @@ -132,7 +134,7 @@ void AnimationImporter::animation_to_fcurves(COLLADAFW::AnimationCurve *curve) #endif bez.f1 = bez.f2 = bez.f3 = SELECT; - insert_bezt_fcurve(fcu, &bez, INSERTKEY_NOFLAGS); + blender::animrig::insert_bezt_fcurve(fcu, &bez, INSERTKEY_NOFLAGS); } BKE_fcurve_handles_recalc(fcu); diff --git a/source/blender/io/collada/BCAnimationCurve.cpp b/source/blender/io/collada/BCAnimationCurve.cpp index a2cdd5df67f..cebab12a580 100644 --- a/source/blender/io/collada/BCAnimationCurve.cpp +++ b/source/blender/io/collada/BCAnimationCurve.cpp @@ -103,7 +103,7 @@ void BCAnimationCurve::create_bezt(float frame, float output) bez.ipo = U.ipo_new; /* use default interpolation mode here... */ bez.f1 = bez.f2 = bez.f3 = SELECT; bez.h1 = bez.h2 = HD_AUTO; - insert_bezt_fcurve(fcu, &bez, INSERTKEY_NOFLAGS); + blender::animrig::insert_bezt_fcurve(fcu, &bez, INSERTKEY_NOFLAGS); BKE_fcurve_handles_recalc(fcu); } @@ -315,7 +315,8 @@ void BCAnimationCurve::clean_handles() BezTriple *bezt = &old_bezts[i]; float x = bezt->vec[1][0]; float y = bezt->vec[1][1]; - insert_vert_fcurve(fcurve, x, y, (eBezTriple_KeyframeType)BEZKEYTYPE(bezt), INSERTKEY_NOFLAGS); + blender::animrig::insert_vert_fcurve( + fcurve, x, y, (eBezTriple_KeyframeType)BEZKEYTYPE(bezt), INSERTKEY_NOFLAGS); BezTriple *lastb = fcurve->bezt + (fcurve->totvert - 1); lastb->f1 = lastb->f2 = lastb->f3 = 0; } @@ -380,7 +381,8 @@ void BCAnimationCurve::add_value(const float val, const int frame_index) { FCurve *fcu = get_edit_fcurve(); fcu->auto_smoothing = U.auto_smoothing_new; - insert_vert_fcurve(fcu, frame_index, val, BEZT_KEYTYPE_KEYFRAME, INSERTKEY_NOFLAGS); + blender::animrig::insert_vert_fcurve( + fcu, frame_index, val, BEZT_KEYTYPE_KEYFRAME, INSERTKEY_NOFLAGS); if (fcu->totvert == 1) { init_range(val); diff --git a/source/blender/io/collada/BCAnimationCurve.h b/source/blender/io/collada/BCAnimationCurve.h index 919ba71fc64..0f552b0e954 100644 --- a/source/blender/io/collada/BCAnimationCurve.h +++ b/source/blender/io/collada/BCAnimationCurve.h @@ -15,7 +15,8 @@ #include "ED_anim_api.hh" #include "ED_keyframes_edit.hh" -#include "ED_keyframing.hh" + +#include "ANIM_fcurve.hh" typedef float(TangentPoint)[2]; diff --git a/source/blender/io/gpencil/intern/gpencil_io_base.cc b/source/blender/io/gpencil/intern/gpencil_io_base.cc index 791947bf058..ea1716a5096 100644 --- a/source/blender/io/gpencil/intern/gpencil_io_base.cc +++ b/source/blender/io/gpencil/intern/gpencil_io_base.cc @@ -268,7 +268,7 @@ float GpencilIO::stroke_point_radius_get(bGPDlayer *gpl, bGPDstroke *gps) float radius = math::length(v1); BKE_gpencil_free_stroke(gps_perimeter); - return MAX2(radius, 1.0f); + return std::max(radius, 1.0f); } void GpencilIO::prepare_layer_export_matrix(Object *ob, bGPDlayer *gpl) 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 daa602097c3..c8afb6d031e 100644 --- a/source/blender/io/gpencil/intern/gpencil_io_export_pdf.cc +++ b/source/blender/io/gpencil/intern/gpencil_io_export_pdf.cc @@ -247,7 +247,7 @@ void GpencilExporterPDF::export_stroke_to_polyline(bGPDlayer *gpl, const float estimated_width = (radius * 2.0f) + gpl->line_change; const float final_width = (avg_pressure == 1.0f) ? MAX2(defined_width, estimated_width) : estimated_width; - HPDF_Page_SetLineWidth(page_, MAX2(final_width, 1.0f)); + HPDF_Page_SetLineWidth(page_, std::max(final_width, 1.0f)); } /* Loop all points. */ 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 c9146d26a56..c7471f4bd97 100644 --- a/source/blender/io/gpencil/intern/gpencil_io_export_svg.cc +++ b/source/blender/io/gpencil/intern/gpencil_io_export_svg.cc @@ -315,7 +315,7 @@ void GpencilExporterSVG::export_stroke_to_polyline(bGPDlayer *gpl, const float estimated_width = (radius * 2.0f) + gpl->line_change; const float final_width = (avg_pressure == 1.0f) ? MAX2(defined_width, estimated_width) : estimated_width; - node_gps.append_attribute("stroke-width").set_value(MAX2(final_width, 1.0f)); + node_gps.append_attribute("stroke-width").set_value(std::max(final_width, 1.0f)); } std::string txt; diff --git a/source/blender/io/usd/CMakeLists.txt b/source/blender/io/usd/CMakeLists.txt index fa20dc94941..172bb37d1d7 100644 --- a/source/blender/io/usd/CMakeLists.txt +++ b/source/blender/io/usd/CMakeLists.txt @@ -186,6 +186,7 @@ set(LIB bf_blenkernel PRIVATE bf::blenlib PRIVATE bf::dna + PRIVATE bf::animrig bf_imbuf PRIVATE bf::intern::guardedalloc bf_io_common diff --git a/source/blender/io/usd/intern/usd_skel_convert.cc b/source/blender/io/usd/intern/usd_skel_convert.cc index de60076a648..6642376cdf0 100644 --- a/source/blender/io/usd/intern/usd_skel_convert.cc +++ b/source/blender/io/usd/intern/usd_skel_convert.cc @@ -41,6 +41,8 @@ #include "ED_keyframing.hh" #include "ED_mesh.hh" +#include "ANIM_fcurve.hh" + #include "WM_api.hh" #include @@ -93,7 +95,7 @@ void add_bezt(FCurve *fcu, bez.ipo = ipo; /* use default interpolation mode here... */ bez.f1 = bez.f2 = bez.f3 = SELECT; bez.h1 = bez.h2 = HD_AUTO; - insert_bezt_fcurve(fcu, &bez, INSERTKEY_NOFLAGS); + blender::animrig::insert_bezt_fcurve(fcu, &bez, INSERTKEY_NOFLAGS); } /** diff --git a/source/blender/makesdna/DNA_material_defaults.h b/source/blender/makesdna/DNA_material_defaults.h index f25cff9a56e..0759bb28c39 100644 --- a/source/blender/makesdna/DNA_material_defaults.h +++ b/source/blender/makesdna/DNA_material_defaults.h @@ -35,6 +35,9 @@ .blend_shadow = MA_BS_SOLID, \ .light_group_bits = {0,0,0,1}, \ .light_group_shadow_bits = {0,0,0,1},\ + \ + .blend_flag = MA_BL_TRANSPARENT_SHADOW,\ + \ .lineart.mat_occlusion = 1, \ } diff --git a/source/blender/makesdna/DNA_material_types.h b/source/blender/makesdna/DNA_material_types.h index 1f6998f296c..acf5124dcfa 100644 --- a/source/blender/makesdna/DNA_material_types.h +++ b/source/blender/makesdna/DNA_material_types.h @@ -225,7 +225,9 @@ typedef struct Material { /* Volume. */ char volume_intersection_method; - char _pad3[7]; + char _pad3[3]; + /* Displacement*/ + float inflate_bounds; /** * Cached slots for texture painting, must be refreshed in * refresh_texpaint_image_cache before using. @@ -367,6 +369,7 @@ enum { MA_BL_TRANSLUCENCY = (1 << 3), MA_BL_LIGHTPROBE_VOLUME_DOUBLE_SIDED = (1 << 4), MA_BL_CULL_BACKFACE_SHADOW = (1 << 5), + MA_BL_TRANSPARENT_SHADOW = (1 << 6), }; /** #Material::blend_shadow */ diff --git a/source/blender/makesrna/RNA_access.hh b/source/blender/makesrna/RNA_access.hh index 9939af9c949..a6ffdd8d401 100644 --- a/source/blender/makesrna/RNA_access.hh +++ b/source/blender/makesrna/RNA_access.hh @@ -451,10 +451,8 @@ int RNA_property_collection_assign_int(PointerRNA *ptr, bool RNA_property_collection_type_get(PointerRNA *ptr, PropertyRNA *prop, PointerRNA *r_ptr); /* efficient functions to set properties for arrays */ -int RNA_property_collection_raw_array(PointerRNA *ptr, - PropertyRNA *prop, - PropertyRNA *itemprop, - RawArray *array); +int RNA_property_collection_raw_array( + PointerRNA *ptr, PropertyRNA *prop, PropertyRNA *itemprop, bool set, RawArray *array); int RNA_property_collection_raw_get(struct ReportList *reports, PointerRNA *ptr, PropertyRNA *prop, diff --git a/source/blender/makesrna/intern/rna_access.cc b/source/blender/makesrna/intern/rna_access.cc index 4b5c644f8c9..0d83c973dbb 100644 --- a/source/blender/makesrna/intern/rna_access.cc +++ b/source/blender/makesrna/intern/rna_access.cc @@ -2281,7 +2281,7 @@ static void rna_property_boolean_fill_default_array_values( const bool *defarr, int defarr_length, bool defvalue, int out_length, bool *r_values) { if (defarr && defarr_length > 0) { - defarr_length = MIN2(defarr_length, out_length); + defarr_length = std::min(defarr_length, out_length); memcpy(r_values, defarr, sizeof(bool) * defarr_length); } else { @@ -2297,7 +2297,7 @@ static void rna_property_boolean_fill_default_array_values_from_ints( const int *defarr, int defarr_length, bool defvalue, int out_length, bool *r_values) { if (defarr && defarr_length > 0) { - defarr_length = MIN2(defarr_length, out_length); + defarr_length = std::min(defarr_length, out_length); for (int i = 0; i < defarr_length; i++) { r_values[i] = defarr[i] != 0; } @@ -2650,7 +2650,7 @@ static void rna_property_int_fill_default_array_values( const int *defarr, int defarr_length, int defvalue, int out_length, int *r_values) { if (defarr && defarr_length > 0) { - defarr_length = MIN2(defarr_length, out_length); + defarr_length = std::min(defarr_length, out_length); memcpy(r_values, defarr, sizeof(int) * defarr_length); } else { @@ -2732,8 +2732,8 @@ void RNA_property_int_get_array_range(PointerRNA *ptr, PropertyRNA *prop, int va RNA_property_int_get_array(ptr, prop, arr); values[0] = values[1] = arr[0]; for (i = 1; i < array_len; i++) { - values[0] = MIN2(values[0], arr[i]); - values[1] = MAX2(values[1], arr[i]); + values[0] = std::min(values[0], arr[i]); + values[1] = std::max(values[1], arr[i]); } if (arr != arr_stack) { @@ -2997,7 +2997,7 @@ static void rna_property_float_fill_default_array_values( const float *defarr, int defarr_length, float defvalue, int out_length, float *r_values) { if (defarr && defarr_length > 0) { - defarr_length = MIN2(defarr_length, out_length); + defarr_length = std::min(defarr_length, out_length); memcpy(r_values, defarr, sizeof(float) * defarr_length); } else { @@ -3018,7 +3018,7 @@ static void rna_property_float_fill_default_array_values_double(const double *de const int out_length, float *r_values) { - const int array_copy_len = MIN2(out_length, default_array_len); + const int array_copy_len = std::min(out_length, default_array_len); for (int i = 0; i < array_copy_len; i++) { r_values[i] = float(default_array[i]); @@ -3105,8 +3105,8 @@ void RNA_property_float_get_array_range(PointerRNA *ptr, PropertyRNA *prop, floa RNA_property_float_get_array(ptr, prop, arr); values[0] = values[1] = arr[0]; for (i = 1; i < array_len; i++) { - values[0] = MIN2(values[0], arr[i]); - values[1] = MAX2(values[1], arr[i]); + values[0] = std::min(values[0], arr[i]); + values[1] = std::max(values[1], arr[i]); } if (arr != arr_stack) { @@ -4405,10 +4405,8 @@ bool RNA_property_collection_type_get(PointerRNA *ptr, PropertyRNA *prop, Pointe return ((r_ptr->type = rna_ensure_property(prop)->srna) ? 1 : 0); } -int RNA_property_collection_raw_array(PointerRNA *ptr, - PropertyRNA *prop, - PropertyRNA *itemprop, - RawArray *array) +int RNA_property_collection_raw_array( + PointerRNA *ptr, PropertyRNA *prop, PropertyRNA *itemprop, bool set, RawArray *array) { CollectionPropertyIterator iter; ArrayIterator *internal; @@ -4429,7 +4427,7 @@ int RNA_property_collection_raw_array(PointerRNA *ptr, internal = &iter.internal.array; arrayp = (iter.valid) ? static_cast(iter.ptr.data) : nullptr; - if (internal->skip || !RNA_property_editable(&iter.ptr, itemprop)) { + if (internal->skip || (set && !RNA_property_editable(&iter.ptr, itemprop))) { /* we might skip some items, so it's not a proper array */ RNA_property_collection_end(&iter); return 0; @@ -4587,7 +4585,7 @@ static int rna_raw_access(ReportList *reports, itemprop = nullptr; } /* try to access as raw array */ - else if (RNA_property_collection_raw_array(ptr, prop, itemprop, &out)) { + else if (RNA_property_collection_raw_array(ptr, prop, itemprop, set, &out)) { int arraylen = (itemlen == 0) ? 1 : itemlen; if (in.len != arraylen * out.len) { BKE_reportf(reports, diff --git a/source/blender/makesrna/intern/rna_action.cc b/source/blender/makesrna/intern/rna_action.cc index 7fe8664ab81..fddf3f048eb 100644 --- a/source/blender/makesrna/intern/rna_action.cc +++ b/source/blender/makesrna/intern/rna_action.cc @@ -36,7 +36,7 @@ # include "DEG_depsgraph.hh" -# include "ANIM_fcurve.hh" +# include "ANIM_action.hh" # include "WM_api.hh" diff --git a/source/blender/makesrna/intern/rna_color.cc b/source/blender/makesrna/intern/rna_color.cc index 1e4929b03eb..e1b8eb57c4d 100644 --- a/source/blender/makesrna/intern/rna_color.cc +++ b/source/blender/makesrna/intern/rna_color.cc @@ -1285,7 +1285,7 @@ static void rna_def_colormanage(BlenderRNA *brna) "High Dynamic Range", "Enable high dynamic range display in rendered viewport, uncapping display brightness. This " "requires a monitor with HDR support and a view transform designed for HDR. " - "'Filmic' does not generate HDR colors"); + "'Filmic' and 'AgX' do not generate HDR colors"); RNA_def_property_update(prop, NC_WINDOW, "rna_ColorManagedColorspaceSettings_reload_update"); /* ** Color-space ** */ diff --git a/source/blender/makesrna/intern/rna_define.cc b/source/blender/makesrna/intern/rna_define.cc index 4acf47801c7..ee7bc3274a0 100644 --- a/source/blender/makesrna/intern/rna_define.cc +++ b/source/blender/makesrna/intern/rna_define.cc @@ -1784,16 +1784,16 @@ void RNA_def_property_range(PropertyRNA *prop, double min, double max) IntPropertyRNA *iprop = (IntPropertyRNA *)prop; iprop->hardmin = int(min); iprop->hardmax = int(max); - iprop->softmin = MAX2(int(min), iprop->hardmin); - iprop->softmax = MIN2(int(max), iprop->hardmax); + iprop->softmin = std::max(int(min), iprop->hardmin); + iprop->softmax = std::min(int(max), iprop->hardmax); break; } case PROP_FLOAT: { FloatPropertyRNA *fprop = (FloatPropertyRNA *)prop; fprop->hardmin = float(min); fprop->hardmax = float(max); - fprop->softmin = MAX2(float(min), fprop->hardmin); - fprop->softmax = MIN2(float(max), fprop->hardmax); + fprop->softmin = std::max(float(min), fprop->hardmin); + fprop->softmax = std::min(float(max), fprop->hardmax); break; } default: @@ -2539,7 +2539,7 @@ void RNA_def_property_int_sdna(PropertyRNA *prop, const char *structname, const } else if (STREQ(dp->dnatype, "int")) { int *defaultarray = static_cast(rna_calloc(size_final)); - memcpy(defaultarray, default_data, MIN2(size_final, dp->dnasize)); + memcpy(defaultarray, default_data, std::min(size_final, dp->dnasize)); iprop->defaultarray = defaultarray; } else { @@ -2650,7 +2650,7 @@ void RNA_def_property_float_sdna(PropertyRNA *prop, const char *structname, cons if (STREQ(dp->dnatype, "float")) { const int size_final = sizeof(float) * prop->totarraylength; float *defaultarray = static_cast(rna_calloc(size_final)); - memcpy(defaultarray, default_data, MIN2(size_final, dp->dnasize)); + memcpy(defaultarray, default_data, std::min(size_final, dp->dnasize)); fprop->defaultarray = defaultarray; } else { diff --git a/source/blender/makesrna/intern/rna_fcurve.cc b/source/blender/makesrna/intern/rna_fcurve.cc index 372ba22c972..c0588deff63 100644 --- a/source/blender/makesrna/intern/rna_fcurve.cc +++ b/source/blender/makesrna/intern/rna_fcurve.cc @@ -30,6 +30,10 @@ #include "ED_keyframes_edit.hh" #include "ED_keyframing.hh" +#ifdef RNA_RUNTIME +# include "ANIM_fcurve.hh" +#endif + const EnumPropertyItem rna_enum_fmodifier_type_items[] = { {FMODIFIER_TYPE_NULL, "nullptr", 0, "Invalid", ""}, {FMODIFIER_TYPE_GENERATOR, @@ -1051,11 +1055,11 @@ static void rna_FModifierStepped_frame_end_set(PointerRNA *ptr, float value) static BezTriple *rna_FKeyframe_points_insert( ID *id, FCurve *fcu, Main *bmain, float frame, float value, int keyframe_type, int flag) { - int index = insert_vert_fcurve(fcu, - frame, - value, - eBezTriple_KeyframeType(keyframe_type), - eInsertKeyFlags(flag) | INSERTKEY_NO_USERPREF); + int index = blender::animrig::insert_vert_fcurve(fcu, + frame, + value, + eBezTriple_KeyframeType(keyframe_type), + eInsertKeyFlags(flag) | INSERTKEY_NO_USERPREF); if ((fcu->bezt) && (index >= 0)) { rna_tag_animation_update(bmain, id); diff --git a/source/blender/makesrna/intern/rna_material.cc b/source/blender/makesrna/intern/rna_material.cc index 53f97e8ad91..854cce18e8f 100644 --- a/source/blender/makesrna/intern/rna_material.cc +++ b/source/blender/makesrna/intern/rna_material.cc @@ -909,6 +909,15 @@ void RNA_def_material(BlenderRNA *brna) prop, "Shadow Backface Culling", "Use back face culling when casting shadows"); RNA_def_property_update(prop, 0, "rna_Material_draw_update"); + prop = RNA_def_property(srna, "use_transparent_shadow", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, nullptr, "blend_flag", MA_BL_TRANSPARENT_SHADOW); + RNA_def_property_ui_text( + prop, + "Transparent Shadows", + "Use transparent shadows for this material if it contains a Transparent BSDF, " + "disabling will render faster but not give accurate shadows"); + RNA_def_property_update(prop, 0, "rna_Material_draw_update"); + prop = RNA_def_property(srna, "lightprobe_volume_single_sided", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_negative_sdna( prop, nullptr, "blend_flag", MA_BL_LIGHTPROBE_VOLUME_DOUBLE_SIDED); @@ -955,6 +964,15 @@ void RNA_def_material(BlenderRNA *brna) "Determines which inner part of the mesh will produce volumetric effect"); RNA_def_property_update(prop, 0, "rna_Material_draw_update"); + prop = RNA_def_property(srna, "max_vertex_displacement", PROP_FLOAT, PROP_DISTANCE); + RNA_def_property_float_sdna(prop, nullptr, "inflate_bounds"); + RNA_def_property_range(prop, 0.0f, FLT_MAX); + RNA_def_property_ui_text(prop, + "Max Vertex Displacement", + "The max distance a vertex can be displaced." + "Displacements over this threshold may cause visibility issues"); + RNA_def_property_update(prop, 0, "rna_Material_draw_update"); + prop = RNA_def_property(srna, "light_group_bits", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "light_group_bits"); RNA_def_property_array(prop, 4); diff --git a/source/blender/makesrna/intern/rna_node_tree_interface.cc b/source/blender/makesrna/intern/rna_node_tree_interface.cc index a124f475292..18fedf45d80 100644 --- a/source/blender/makesrna/intern/rna_node_tree_interface.cc +++ b/source/blender/makesrna/intern/rna_node_tree_interface.cc @@ -1,4 +1,4 @@ -/* SPDX-FileCopyrightText: 2023 Blender Foundation +/* SPDX-FileCopyrightText: 2023 Blender Authors * * SPDX-License-Identifier: GPL-2.0-or-later */ diff --git a/source/blender/makesrna/intern/rna_scene.cc b/source/blender/makesrna/intern/rna_scene.cc index 183035cf243..98c1ab25b9d 100644 --- a/source/blender/makesrna/intern/rna_scene.cc +++ b/source/blender/makesrna/intern/rna_scene.cc @@ -3485,6 +3485,7 @@ static void rna_def_tool_settings(BlenderRNA *brna) RNA_def_property_enum_bitflag_sdna(prop, nullptr, "snap_anim_mode"); RNA_def_property_enum_items(prop, rna_enum_snap_animation_element_items); RNA_def_property_ui_text(prop, "Snap Anim Element", "Type of element to snap to"); + RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_UNIT); RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, nullptr); /* header redraw */ /* image editor uses own set of snap modes */ diff --git a/source/blender/modifiers/intern/MOD_correctivesmooth.cc b/source/blender/modifiers/intern/MOD_correctivesmooth.cc index 10bb74dd4e1..814b4157d24 100644 --- a/source/blender/modifiers/intern/MOD_correctivesmooth.cc +++ b/source/blender/modifiers/intern/MOD_correctivesmooth.cc @@ -8,6 +8,7 @@ * Method of smoothing deformation, also known as 'delta-mush'. */ +#include "BLI_math_base.hh" #include "BLI_math_matrix.h" #include "BLI_math_vector.h" #include "BLI_utildefines.h" @@ -470,7 +471,8 @@ static void calc_tangent_spaces(const Mesh *mesh, if (calc_tangent_loop(v_dir_prev, v_dir_next, ts)) { if (r_tangent_weights != nullptr) { - const float weight = fabsf(acosf(dot_v3v3(v_dir_next, v_dir_prev))); + const float weight = fabsf( + blender::math::safe_acos_approx(dot_v3v3(v_dir_next, v_dir_prev))); r_tangent_weights[curr_corner] = weight; r_tangent_weights_per_vertex[corner_verts[curr_corner]] += weight; } diff --git a/source/blender/modifiers/intern/MOD_nodes.cc b/source/blender/modifiers/intern/MOD_nodes.cc index f523eb826c6..78a920df007 100644 --- a/source/blender/modifiers/intern/MOD_nodes.cc +++ b/source/blender/modifiers/intern/MOD_nodes.cc @@ -1437,7 +1437,7 @@ static void add_attribute_search_or_value_buttons(const bContext &C, uiItemL(name_row, "", ICON_NONE); } else { - uiItemL(name_row, socket.name ? socket.name : "", ICON_NONE); + uiItemL(name_row, socket.name ? IFACE_(socket.name) : "", ICON_NONE); } uiLayout *prop_row = uiLayoutRow(split, true); @@ -1451,7 +1451,7 @@ static void add_attribute_search_or_value_buttons(const bContext &C, uiItemL(layout, "", ICON_BLANK1); } else { - const char *name = type == SOCK_BOOLEAN ? (socket.name ? socket.name : "") : ""; + const char *name = type == SOCK_BOOLEAN ? (socket.name ? IFACE_(socket.name) : "") : ""; uiItemR(prop_row, md_ptr, rna_path.c_str(), UI_ITEM_NONE, name, ICON_NONE); uiItemDecoratorR(layout, md_ptr, rna_path.c_str(), -1); } @@ -1504,7 +1504,7 @@ static void draw_property_for_socket(const bContext &C, * pointer IDProperties contain no information about their type. */ const bNodeSocketType *typeinfo = socket.socket_typeinfo(); const eNodeSocketDatatype type = typeinfo ? eNodeSocketDatatype(typeinfo->type) : SOCK_CUSTOM; - const char *name = socket.name ? socket.name : ""; + const char *name = socket.name ? IFACE_(socket.name) : ""; switch (type) { case SOCK_OBJECT: { uiItemPointerR(row, md_ptr, rna_path, bmain_ptr, "objects", name, ICON_OBJECT_DATA); diff --git a/source/blender/modifiers/intern/MOD_subsurf.cc b/source/blender/modifiers/intern/MOD_subsurf.cc index 0e99ea09560..76373451f21 100644 --- a/source/blender/modifiers/intern/MOD_subsurf.cc +++ b/source/blender/modifiers/intern/MOD_subsurf.cc @@ -386,12 +386,12 @@ static void panel_draw(const bContext *C, Panel *panel) } if (ob_use_adaptive_subdivision && show_adaptive_options) { uiItemR(layout, &ob_cycles_ptr, "dicing_rate", UI_ITEM_NONE, nullptr, ICON_NONE); - float render = MAX2(RNA_float_get(&cycles_ptr, "dicing_rate") * - RNA_float_get(&ob_cycles_ptr, "dicing_rate"), - 0.1f); - float preview = MAX2(RNA_float_get(&cycles_ptr, "preview_dicing_rate") * - RNA_float_get(&ob_cycles_ptr, "dicing_rate"), - 0.1f); + float render = std::max(RNA_float_get(&cycles_ptr, "dicing_rate") * + RNA_float_get(&ob_cycles_ptr, "dicing_rate"), + 0.1f); + float preview = std::max(RNA_float_get(&cycles_ptr, "preview_dicing_rate") * + RNA_float_get(&ob_cycles_ptr, "dicing_rate"), + 0.1f); char output[256]; SNPRINTF(output, TIP_("Final Scale: Render %.2f px, Viewport %.2f px"), render, preview); uiItemL(layout, output, ICON_NONE); diff --git a/source/blender/modifiers/intern/MOD_surfacedeform.cc b/source/blender/modifiers/intern/MOD_surfacedeform.cc index d73e09a3a9b..6a48ecde160 100644 --- a/source/blender/modifiers/intern/MOD_surfacedeform.cc +++ b/source/blender/modifiers/intern/MOD_surfacedeform.cc @@ -606,7 +606,7 @@ BLI_INLINE SDefBindWeightData *computeBindWeights(SDefBindCalcData *const data, return nullptr; } - bpoly->inside = isect_point_poly_v2(bpoly->point_v2, bpoly->coords_v2, face.size(), false); + bpoly->inside = isect_point_poly_v2(bpoly->point_v2, bpoly->coords_v2, face.size()); /* Initialize weight components */ bpoly->weight_angular = 1.0f; diff --git a/source/blender/modifiers/intern/MOD_wireframe.cc b/source/blender/modifiers/intern/MOD_wireframe.cc index e9df4da1e3f..52fab6f3f68 100644 --- a/source/blender/modifiers/intern/MOD_wireframe.cc +++ b/source/blender/modifiers/intern/MOD_wireframe.cc @@ -91,7 +91,7 @@ static Mesh *WireframeModifier_do(WireframeModifierData *wmd, Object *ob, Mesh * defgrp_index, (wmd->flag & MOD_WIREFRAME_INVERT_VGROUP) != 0, wmd->mat_ofs, - MAX2(ob->totcol - 1, 0), + std::max(ob->totcol - 1, 0), false); result = BKE_mesh_from_bmesh_for_eval_nomain(bm, nullptr, mesh); diff --git a/source/blender/nodes/composite/nodes/node_composite_image.cc b/source/blender/nodes/composite/nodes/node_composite_image.cc index 73ebe92e1bd..239fe265317 100644 --- a/source/blender/nodes/composite/nodes/node_composite_image.cc +++ b/source/blender/nodes/composite/nodes/node_composite_image.cc @@ -23,6 +23,7 @@ #include "DEG_depsgraph_query.hh" +#include "DNA_image_types.h" #include "DNA_scene_types.h" #include "DNA_vec_types.h" @@ -519,6 +520,10 @@ class ImageOperation : public NodeOperation { const int2 lower_bound = int2(0); GPU_shader_uniform_2iv(shader, "lower_bound", lower_bound); + if (result.type() == ResultType::Color) { + GPU_shader_uniform_1b(shader, "premultiply_alpha", should_premultiply_alpha(image_user)); + } + const int input_unit = GPU_shader_get_sampler_binding(shader, "input_tx"); GPU_texture_bind(image_texture, input_unit); @@ -570,6 +575,29 @@ class ImageOperation : public NodeOperation { } } + /* Compositor image inputs are expected to be always pre-multiplied, so identify if the GPU + * texture returned by the image module is straight and needs to be pre-multiplied. An exception + * is when the image has an alpha mode of channel packed or alpha ignore, in which case, we + * always ignore pre-multiplication. */ + bool should_premultiply_alpha(ImageUser &image_user) + { + Image *image = get_image(); + if (ELEM(image->alpha_mode, IMA_ALPHA_CHANNEL_PACKED, IMA_ALPHA_IGNORE)) { + return false; + } + + ImBuf *image_buffer = BKE_image_acquire_ibuf(image, &image_user, nullptr); + if (!image_buffer) { + return false; + } + + const bool has_premultiplied_alpha = BKE_image_has_gpu_texture_premultiplied_alpha( + image, image_buffer); + BKE_image_release_ibuf(image, image_buffer, nullptr); + + return !has_premultiplied_alpha; + } + Image *get_image() { return (Image *)bnode().id; diff --git a/source/blender/nodes/function/nodes/node_fn_axis_angle_to_rotation.cc b/source/blender/nodes/function/nodes/node_fn_axis_angle_to_rotation.cc index 08bc7aa270c..fd56f847f2d 100644 --- a/source/blender/nodes/function/nodes/node_fn_axis_angle_to_rotation.cc +++ b/source/blender/nodes/function/nodes/node_fn_axis_angle_to_rotation.cc @@ -1,4 +1,4 @@ -/* SPDX-FileCopyrightText: 2023 Blender Foundation +/* SPDX-FileCopyrightText: 2023 Blender Authors * * SPDX-License-Identifier: GPL-2.0-or-later */ diff --git a/source/blender/nodes/function/nodes/node_fn_euler_to_rotation.cc b/source/blender/nodes/function/nodes/node_fn_euler_to_rotation.cc index ff6768342d3..8636b079bff 100644 --- a/source/blender/nodes/function/nodes/node_fn_euler_to_rotation.cc +++ b/source/blender/nodes/function/nodes/node_fn_euler_to_rotation.cc @@ -1,4 +1,4 @@ -/* SPDX-FileCopyrightText: 2023 Blender Foundation +/* SPDX-FileCopyrightText: 2023 Blender Authors * * SPDX-License-Identifier: GPL-2.0-or-later */ diff --git a/source/blender/nodes/function/nodes/node_fn_invert_rotation.cc b/source/blender/nodes/function/nodes/node_fn_invert_rotation.cc index bdcd236146e..36b8e3ac700 100644 --- a/source/blender/nodes/function/nodes/node_fn_invert_rotation.cc +++ b/source/blender/nodes/function/nodes/node_fn_invert_rotation.cc @@ -1,4 +1,4 @@ -/* SPDX-FileCopyrightText: 2023 Blender Foundation +/* SPDX-FileCopyrightText: 2023 Blender Authors * * SPDX-License-Identifier: GPL-2.0-or-later */ diff --git a/source/blender/nodes/function/nodes/node_fn_quaternion_to_rotation.cc b/source/blender/nodes/function/nodes/node_fn_quaternion_to_rotation.cc index 15c492de796..113180d646c 100644 --- a/source/blender/nodes/function/nodes/node_fn_quaternion_to_rotation.cc +++ b/source/blender/nodes/function/nodes/node_fn_quaternion_to_rotation.cc @@ -1,4 +1,4 @@ -/* SPDX-FileCopyrightText: 2023 Blender Foundation +/* SPDX-FileCopyrightText: 2023 Blender Authors * * SPDX-License-Identifier: GPL-2.0-or-later */ diff --git a/source/blender/nodes/function/nodes/node_fn_rotate_vector.cc b/source/blender/nodes/function/nodes/node_fn_rotate_vector.cc index d86bbbaf73a..15d6b47f0fa 100644 --- a/source/blender/nodes/function/nodes/node_fn_rotate_vector.cc +++ b/source/blender/nodes/function/nodes/node_fn_rotate_vector.cc @@ -1,4 +1,4 @@ -/* SPDX-FileCopyrightText: 2023 Blender Foundation +/* SPDX-FileCopyrightText: 2023 Blender Authors * * SPDX-License-Identifier: GPL-2.0-or-later */ diff --git a/source/blender/nodes/function/nodes/node_fn_rotation_to_axis_angle.cc b/source/blender/nodes/function/nodes/node_fn_rotation_to_axis_angle.cc index adffb7f2154..529130785ab 100644 --- a/source/blender/nodes/function/nodes/node_fn_rotation_to_axis_angle.cc +++ b/source/blender/nodes/function/nodes/node_fn_rotation_to_axis_angle.cc @@ -1,4 +1,4 @@ -/* SPDX-FileCopyrightText: 2023 Blender Foundation +/* SPDX-FileCopyrightText: 2023 Blender Authors * * SPDX-License-Identifier: GPL-2.0-or-later */ diff --git a/source/blender/nodes/function/nodes/node_fn_rotation_to_euler.cc b/source/blender/nodes/function/nodes/node_fn_rotation_to_euler.cc index d47230ddaf9..7c6938f3db9 100644 --- a/source/blender/nodes/function/nodes/node_fn_rotation_to_euler.cc +++ b/source/blender/nodes/function/nodes/node_fn_rotation_to_euler.cc @@ -1,4 +1,4 @@ -/* SPDX-FileCopyrightText: 2023 Blender Foundation +/* SPDX-FileCopyrightText: 2023 Blender Authors * * SPDX-License-Identifier: GPL-2.0-or-later */ diff --git a/source/blender/nodes/function/nodes/node_fn_rotation_to_quaternion.cc b/source/blender/nodes/function/nodes/node_fn_rotation_to_quaternion.cc index be381f6b40a..399d773ca1e 100644 --- a/source/blender/nodes/function/nodes/node_fn_rotation_to_quaternion.cc +++ b/source/blender/nodes/function/nodes/node_fn_rotation_to_quaternion.cc @@ -1,4 +1,4 @@ -/* SPDX-FileCopyrightText: 2023 Blender Foundation +/* SPDX-FileCopyrightText: 2023 Blender Authors * * SPDX-License-Identifier: GPL-2.0-or-later */ diff --git a/source/blender/nodes/geometry/nodes/node_geo_input_scene_time.cc b/source/blender/nodes/geometry/nodes/node_geo_input_scene_time.cc index 28313bd40a2..e7a9fda657a 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_input_scene_time.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_input_scene_time.cc @@ -20,7 +20,7 @@ static void node_exec(GeoNodeExecParams params) { const Scene *scene = DEG_get_input_scene(params.depsgraph()); const float scene_ctime = BKE_scene_ctime_get(scene); - const double frame_rate = (double(scene->r.frs_sec) / double(scene->r.frs_sec_base)); + const double frame_rate = double(scene->r.frs_sec) / double(scene->r.frs_sec_base); params.set_output("Seconds", float(scene_ctime / frame_rate)); params.set_output("Frame", scene_ctime); } diff --git a/source/blender/nodes/geometry/nodes/node_geo_points_to_curves.cc b/source/blender/nodes/geometry/nodes/node_geo_points_to_curves.cc index b422db14a29..97fe596f92b 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_points_to_curves.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_points_to_curves.cc @@ -1,4 +1,4 @@ -/* SPDX-FileCopyrightText: 2023 Blender Foundation +/* SPDX-FileCopyrightText: 2023 Blender Authors * * SPDX-License-Identifier: GPL-2.0-or-later */ diff --git a/source/blender/nodes/shader/CMakeLists.txt b/source/blender/nodes/shader/CMakeLists.txt index cdb728a0217..bc0437e9117 100644 --- a/source/blender/nodes/shader/CMakeLists.txt +++ b/source/blender/nodes/shader/CMakeLists.txt @@ -147,6 +147,10 @@ set(LIB if(WITH_MATERIALX) add_definitions(-DWITH_MATERIALX) + list(APPEND INC + ${USD_INCLUDE_DIRS} + ${BOOST_INCLUDE_DIR} + ) list(APPEND SRC materialx/group_nodes.cc materialx/material.cc diff --git a/source/blender/nodes/shader/materialx/group_nodes.cc b/source/blender/nodes/shader/materialx/group_nodes.cc index 4fbeefc4ce5..81ba769001e 100644 --- a/source/blender/nodes/shader/materialx/group_nodes.cc +++ b/source/blender/nodes/shader/materialx/group_nodes.cc @@ -1,4 +1,4 @@ -/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation +/* SPDX-FileCopyrightText: 2011-2022 Blender Authors * * SPDX-License-Identifier: GPL-2.0-or-later */ diff --git a/source/blender/nodes/shader/materialx/group_nodes.h b/source/blender/nodes/shader/materialx/group_nodes.h index 983ab5f1062..56e747464b3 100644 --- a/source/blender/nodes/shader/materialx/group_nodes.h +++ b/source/blender/nodes/shader/materialx/group_nodes.h @@ -1,4 +1,4 @@ -/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation +/* SPDX-FileCopyrightText: 2011-2022 Blender Authors * * SPDX-License-Identifier: GPL-2.0-or-later */ diff --git a/source/blender/nodes/shader/materialx/material.cc b/source/blender/nodes/shader/materialx/material.cc index 5339289e21b..4f4358ed137 100644 --- a/source/blender/nodes/shader/materialx/material.cc +++ b/source/blender/nodes/shader/materialx/material.cc @@ -1,4 +1,4 @@ -/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation +/* SPDX-FileCopyrightText: 2011-2022 Blender Authors * * SPDX-License-Identifier: GPL-2.0-or-later */ diff --git a/source/blender/nodes/shader/materialx/material.h b/source/blender/nodes/shader/materialx/material.h index d0a4a7e6a31..7c62d4fe361 100644 --- a/source/blender/nodes/shader/materialx/material.h +++ b/source/blender/nodes/shader/materialx/material.h @@ -1,4 +1,4 @@ -/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation +/* SPDX-FileCopyrightText: 2011-2022 Blender Authors * * SPDX-License-Identifier: GPL-2.0-or-later */ diff --git a/source/blender/nodes/shader/materialx/node_item.cc b/source/blender/nodes/shader/materialx/node_item.cc index d2468cff770..959fae20a04 100644 --- a/source/blender/nodes/shader/materialx/node_item.cc +++ b/source/blender/nodes/shader/materialx/node_item.cc @@ -1,4 +1,4 @@ -/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation +/* SPDX-FileCopyrightText: 2011-2022 Blender Authors * * SPDX-License-Identifier: GPL-2.0-or-later */ diff --git a/source/blender/nodes/shader/materialx/node_item.h b/source/blender/nodes/shader/materialx/node_item.h index f392a42666d..f6a98366d73 100644 --- a/source/blender/nodes/shader/materialx/node_item.h +++ b/source/blender/nodes/shader/materialx/node_item.h @@ -1,4 +1,4 @@ -/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation +/* SPDX-FileCopyrightText: 2011-2022 Blender Authors * * SPDX-License-Identifier: GPL-2.0-or-later */ diff --git a/source/blender/nodes/shader/materialx/node_parser.cc b/source/blender/nodes/shader/materialx/node_parser.cc index eeb7ae88320..2f8628270da 100644 --- a/source/blender/nodes/shader/materialx/node_parser.cc +++ b/source/blender/nodes/shader/materialx/node_parser.cc @@ -1,7 +1,9 @@ -/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation +/* SPDX-FileCopyrightText: 2011-2022 Blender Authors * * SPDX-License-Identifier: GPL-2.0-or-later */ +#include + #include "node_parser.h" #include "group_nodes.h" @@ -58,26 +60,40 @@ NodeItem NodeParser::compute_full() return res; } -std::string NodeParser::node_name() const +std::string NodeParser::node_name(bool with_out_socket) const { + auto valid_name = [](const std::string &name) { + /* Node name should suite to MatX and USD valid names. + * It shouldn't start from '_', due to error occurred in Storm delegate. */ + std::string res = MaterialX::createValidName(pxr::TfMakeValidIdentifier(name)); + if (res[0] == '_') { + res = "node" + res; + } + return res; + }; + std::string name = node_->name; - if (node_->output_sockets().size() > 1) { - name += std::string("_") + socket_out_->name; - } - if (ELEM(to_type_, NodeItem::Type::BSDF, NodeItem::Type::EDF, NodeItem::Type::SurfaceOpacity)) { - name += "_" + NodeItem::type(to_type_); + if (with_out_socket) { + if (node_->output_sockets().size() > 1) { + name += std::string("_") + socket_out_->name; + } + if (ELEM(to_type_, NodeItem::Type::BSDF, NodeItem::Type::EDF, NodeItem::Type::SurfaceOpacity)) + { + name += "_" + NodeItem::type(to_type_); + } } #ifdef USE_MATERIALX_NODEGRAPH - return MaterialX::createValidName(name); + return valid_name(name); #else + std::string prefix; GroupNodeParser *gr = group_parser_; while (gr) { const bNodeTree *ngroup = reinterpret_cast(gr->node_->id); - prefix = MaterialX::createValidName(ngroup->id.name) + "_" + prefix; + prefix = valid_name(ngroup->id.name) + "_" + prefix; gr = gr->group_parser_; } - return prefix + MaterialX::createValidName(name); + return prefix + valid_name(name); #endif } diff --git a/source/blender/nodes/shader/materialx/node_parser.h b/source/blender/nodes/shader/materialx/node_parser.h index 6fca45a02af..5f76b8caaf2 100644 --- a/source/blender/nodes/shader/materialx/node_parser.h +++ b/source/blender/nodes/shader/materialx/node_parser.h @@ -1,4 +1,4 @@ -/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation +/* SPDX-FileCopyrightText: 2011-2022 Blender Authors * * SPDX-License-Identifier: GPL-2.0-or-later */ @@ -50,7 +50,7 @@ class NodeParser { virtual NodeItem compute_full(); protected: - std::string node_name() const; + std::string node_name(bool with_out_socket = true) const; NodeItem create_node(const std::string &category, NodeItem::Type type); NodeItem create_node(const std::string &category, NodeItem::Type type, diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_gradient.cc b/source/blender/nodes/shader/nodes/node_shader_tex_gradient.cc index 7dd9ad194bb..f322fc0d41c 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_gradient.cc +++ b/source/blender/nodes/shader/nodes/node_shader_tex_gradient.cc @@ -174,7 +174,7 @@ NODE_SHADER_MATERIALX_BEGIN res = (vector[0] + vector[1]) * val(0.5f); break; case SHD_BLEND_RADIAL: - res = vector[1].atan2(vector[0]) / (val(float(M_PI * 2.0f))) + val(0.5f); + res = vector[1].atan2(vector[0]) / val(float(M_PI * 2.0f)) + val(0.5f); break; case SHD_BLEND_QUADRATIC_SPHERE: res = (val(1.0f) - vector.dotproduct(vector).sqrt()).max(val(0.0f)); diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_image.cc b/source/blender/nodes/shader/nodes/node_shader_tex_image.cc index bc84d5aa917..75f3da75f67 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_image.cc +++ b/source/blender/nodes/shader/nodes/node_shader_tex_image.cc @@ -178,8 +178,7 @@ NODE_SHADER_MATERIALX_BEGIN #ifdef WITH_MATERIALX { /* Getting node name for Color output. This name will be used for node. */ - std::string image_node_name = node_name(); - image_node_name = image_node_name.substr(0, image_node_name.rfind('_')) + "_Color"; + std::string image_node_name = node_name(false) + "_Color"; NodeItem res = empty(); res.node = graph_->getNode(image_node_name); diff --git a/source/blender/nodes/texture/nodes/node_texture_math.cc b/source/blender/nodes/texture/nodes/node_texture_math.cc index 9ee5393babc..3a9992254a6 100644 --- a/source/blender/nodes/texture/nodes/node_texture_math.cc +++ b/source/blender/nodes/texture/nodes/node_texture_math.cc @@ -285,7 +285,7 @@ static void valuefn(float *out, TexParams *p, bNode *node, bNodeStack **in, shor case NODE_MATH_COMPARE: { float in2 = tex_input_value(in[2], p, thread); - *out = (fabsf(in0 - in1) <= MAX2(in2, 1e-5f)) ? 1.0f : 0.0f; + *out = (fabsf(in0 - in1) <= std::max(in2, 1e-5f)) ? 1.0f : 0.0f; break; } diff --git a/source/blender/python/generic/idprop_py_ui_api.cc b/source/blender/python/generic/idprop_py_ui_api.cc index 5c88f9e5be4..8f873ef9572 100644 --- a/source/blender/python/generic/idprop_py_ui_api.cc +++ b/source/blender/python/generic/idprop_py_ui_api.cc @@ -143,23 +143,23 @@ static bool idprop_ui_data_update_int(IDProperty *idprop, PyObject *args, PyObje if (args_contain_key(kwargs, "min")) { ui_data.min = min; - ui_data.soft_min = MAX2(ui_data.soft_min, ui_data.min); - ui_data.max = MAX2(ui_data.min, ui_data.max); + ui_data.soft_min = std::max(ui_data.soft_min, ui_data.min); + ui_data.max = std::max(ui_data.min, ui_data.max); } if (args_contain_key(kwargs, "max")) { ui_data.max = max; - ui_data.soft_max = MIN2(ui_data.soft_max, ui_data.max); - ui_data.min = MIN2(ui_data.min, ui_data.max); + ui_data.soft_max = std::min(ui_data.soft_max, ui_data.max); + ui_data.min = std::min(ui_data.min, ui_data.max); } if (args_contain_key(kwargs, "soft_min")) { ui_data.soft_min = soft_min; - ui_data.soft_min = MAX2(ui_data.soft_min, ui_data.min); - ui_data.soft_max = MAX2(ui_data.soft_min, ui_data.soft_max); + ui_data.soft_min = std::max(ui_data.soft_min, ui_data.min); + ui_data.soft_max = std::max(ui_data.soft_min, ui_data.soft_max); } if (args_contain_key(kwargs, "soft_max")) { ui_data.soft_max = soft_max; - ui_data.soft_max = MIN2(ui_data.soft_max, ui_data.max); - ui_data.soft_min = MIN2(ui_data.soft_min, ui_data.soft_max); + ui_data.soft_max = std::min(ui_data.soft_max, ui_data.max); + ui_data.soft_min = std::min(ui_data.soft_min, ui_data.soft_max); } if (args_contain_key(kwargs, "step")) { ui_data.step = step; @@ -354,23 +354,23 @@ static bool idprop_ui_data_update_float(IDProperty *idprop, PyObject *args, PyOb if (args_contain_key(kwargs, "min")) { ui_data.min = min; - ui_data.soft_min = MAX2(ui_data.soft_min, ui_data.min); - ui_data.max = MAX2(ui_data.min, ui_data.max); + ui_data.soft_min = std::max(ui_data.soft_min, ui_data.min); + ui_data.max = std::max(ui_data.min, ui_data.max); } if (args_contain_key(kwargs, "max")) { ui_data.max = max; - ui_data.soft_max = MIN2(ui_data.soft_max, ui_data.max); - ui_data.min = MIN2(ui_data.min, ui_data.max); + ui_data.soft_max = std::min(ui_data.soft_max, ui_data.max); + ui_data.min = std::min(ui_data.min, ui_data.max); } if (args_contain_key(kwargs, "soft_min")) { ui_data.soft_min = soft_min; ui_data.soft_min = MAX2(ui_data.soft_min, ui_data.min); - ui_data.soft_max = MAX2(ui_data.soft_min, ui_data.soft_max); + ui_data.soft_max = std::max(ui_data.soft_min, ui_data.soft_max); } if (args_contain_key(kwargs, "soft_max")) { ui_data.soft_max = soft_max; ui_data.soft_max = MIN2(ui_data.soft_max, ui_data.max); - ui_data.soft_min = MIN2(ui_data.soft_min, ui_data.soft_max); + ui_data.soft_min = std::min(ui_data.soft_min, ui_data.soft_max); } if (args_contain_key(kwargs, "step")) { ui_data.step = float(step); diff --git a/source/blender/python/intern/bpy_props.cc b/source/blender/python/intern/bpy_props.cc index ca63fbbb71e..668b7f18846 100644 --- a/source/blender/python/intern/bpy_props.cc +++ b/source/blender/python/intern/bpy_props.cc @@ -3262,7 +3262,7 @@ static PyObject *BPy_IntProperty(PyObject *self, PyObject *args, PyObject *kw) RNA_def_property_translation_context(prop, translation_context); } RNA_def_property_range(prop, min, max); - RNA_def_property_ui_range(prop, MAX2(soft_min, min), MIN2(soft_max, max), step, 3); + RNA_def_property_ui_range(prop, std::max(soft_min, min), MIN2(soft_max, max), step, 3); if (tags_enum.base.is_set) { RNA_def_property_tags(prop, tags_enum.base.value); @@ -3460,7 +3460,7 @@ static PyObject *BPy_IntVectorProperty(PyObject *self, PyObject *args, PyObject if (translation_context) { RNA_def_property_translation_context(prop, translation_context); } - RNA_def_property_ui_range(prop, MAX2(soft_min, min), MIN2(soft_max, max), step, 3); + RNA_def_property_ui_range(prop, std::max(soft_min, min), MIN2(soft_max, max), step, 3); if (tags_enum.base.is_set) { RNA_def_property_tags(prop, tags_enum.base.value); diff --git a/source/blender/python/mathutils/mathutils_Matrix.cc b/source/blender/python/mathutils/mathutils_Matrix.cc index f50f8816ce2..4d7a9c93250 100644 --- a/source/blender/python/mathutils/mathutils_Matrix.cc +++ b/source/blender/python/mathutils/mathutils_Matrix.cc @@ -3698,7 +3698,7 @@ static PyObject *MatrixAccess_slice(MatrixAccessObject *self, Py_ssize_t begin, end = (matrix_access_len + 1) + end; } CLAMP(end, 0, matrix_access_len); - begin = MIN2(begin, end); + begin = std::min(begin, end); tuple = PyTuple_New(end - begin); for (count = begin; count < end; count++) { diff --git a/source/blender/python/mathutils/mathutils_Vector.cc b/source/blender/python/mathutils/mathutils_Vector.cc index 83151139f8d..f20e232b815 100644 --- a/source/blender/python/mathutils/mathutils_Vector.cc +++ b/source/blender/python/mathutils/mathutils_Vector.cc @@ -694,7 +694,7 @@ static PyObject *Vector_to_3d(VectorObject *self) return nullptr; } - memcpy(tvec, self->vec, sizeof(float) * MIN2(self->vec_num, 3)); + memcpy(tvec, self->vec, sizeof(float) * std::min(self->vec_num, 3)); return Vector_CreatePyObject(tvec, 3, Py_TYPE(self)); } PyDoc_STRVAR(Vector_to_4d_doc, @@ -712,7 +712,7 @@ static PyObject *Vector_to_4d(VectorObject *self) return nullptr; } - memcpy(tvec, self->vec, sizeof(float) * MIN2(self->vec_num, 4)); + memcpy(tvec, self->vec, sizeof(float) * std::min(self->vec_num, 4)); return Vector_CreatePyObject(tvec, 4, Py_TYPE(self)); } @@ -1082,7 +1082,7 @@ PyDoc_STRVAR( " :rtype: float\n"); static PyObject *Vector_angle(VectorObject *self, PyObject *args) { - const int vec_num = MIN2(self->vec_num, 3); /* 4D angle makes no sense */ + const int vec_num = std::min(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; diff --git a/source/blender/render/intern/texture_image.cc b/source/blender/render/intern/texture_image.cc index e47774abfc0..5b3283f2a10 100644 --- a/source/blender/render/intern/texture_image.cc +++ b/source/blender/render/intern/texture_image.cc @@ -1219,7 +1219,7 @@ static int imagewraposa_aniso(Tex *tex, b = max_ff(b, 1.0f); fProbes = 2.0f * (a / b) - 1.0f; AFD.iProbes = round_fl_to_int(fProbes); - AFD.iProbes = MIN2(AFD.iProbes, tex->afmax); + AFD.iProbes = std::min(AFD.iProbes, tex->afmax); if (AFD.iProbes < fProbes) { b = 2.0f * a / float(AFD.iProbes + 1); } diff --git a/source/blender/render/intern/texture_pointdensity.cc b/source/blender/render/intern/texture_pointdensity.cc index c7ad337b81a..bebf34a13d9 100644 --- a/source/blender/render/intern/texture_pointdensity.cc +++ b/source/blender/render/intern/texture_pointdensity.cc @@ -525,7 +525,7 @@ static float density_falloff(PointDensityRangeData *pdr, int index, float square break; case TEX_PD_FALLOFF_PARTICLE_AGE: if (pdr->point_data_life) { - density = dist * MIN2(pdr->point_data_life[index], 1.0f); + density = dist * std::min(pdr->point_data_life[index], 1.0f); } else { density = dist; diff --git a/source/blender/sequencer/intern/effects.cc b/source/blender/sequencer/intern/effects.cc index 8bffd997ddf..b2da0f6f405 100644 --- a/source/blender/sequencer/intern/effects.cc +++ b/source/blender/sequencer/intern/effects.cc @@ -938,13 +938,13 @@ static void do_drop_effect_byte(float fac, int x, int y, uchar *rect2i, uchar *r for (int j = xoff; j < x; j++) { int temp_fac2 = ((temp_fac * rt2[3]) >> 8); - *(out++) = MAX2(0, *rt1 - temp_fac2); + *(out++) = std::max(0, *rt1 - temp_fac2); rt1++; - *(out++) = MAX2(0, *rt1 - temp_fac2); + *(out++) = std::max(0, *rt1 - temp_fac2); rt1++; - *(out++) = MAX2(0, *rt1 - temp_fac2); + *(out++) = std::max(0, *rt1 - temp_fac2); rt1++; - *(out++) = MAX2(0, *rt1 - temp_fac2); + *(out++) = std::max(0, *rt1 - temp_fac2); rt1++; rt2 += 4; } @@ -972,13 +972,13 @@ static void do_drop_effect_float( for (int j = xoff; j < x; j++) { float temp_fac2 = temp_fac * rt2[3]; - *(out++) = MAX2(0.0f, *rt1 - temp_fac2); + *(out++) = std::max(0.0f, *rt1 - temp_fac2); rt1++; - *(out++) = MAX2(0.0f, *rt1 - temp_fac2); + *(out++) = std::max(0.0f, *rt1 - temp_fac2); rt1++; - *(out++) = MAX2(0.0f, *rt1 - temp_fac2); + *(out++) = std::max(0.0f, *rt1 - temp_fac2); rt1++; - *(out++) = MAX2(0.0f, *rt1 - temp_fac2); + *(out++) = std::max(0.0f, *rt1 - temp_fac2); rt1++; rt2 += 4; } @@ -3251,10 +3251,19 @@ void SEQ_effect_text_font_load(TextVars *data, const bool do_id_user) else { char filepath[FILE_MAX]; STRNCPY(filepath, vfont->filepath); - BLI_assert(BLI_thread_is_main()); - BLI_path_abs(filepath, ID_BLEND_PATH_FROM_GLOBAL(&vfont->id)); + if (BLI_thread_is_main()) { + /* FIXME: This is a band-aid fix. A proper solution has to be worked on by the VSE team. + * + * This code can be called from non-main thread, e.g. when copying sequences as part of + * depsgraph CoW copy of the evaluated scene. Just skip font loading in that case, BLF code + * is not thread-safe, and if this happens from threaded context, it almost certainly means + * that a previous atempt to load the font already failed, e.g. because font filepath is + * invalid. Propoer fix would likely be to not attempt to reload a failed-to-load font every + * time. */ + BLI_path_abs(filepath, ID_BLEND_PATH_FROM_GLOBAL(&vfont->id)); - data->text_blf_id = BLF_load(filepath); + data->text_blf_id = BLF_load(filepath); + } } } diff --git a/source/blender/sequencer/intern/iterator.cc b/source/blender/sequencer/intern/iterator.cc index e8549ce0c02..e2ec62a4891 100644 --- a/source/blender/sequencer/intern/iterator.cc +++ b/source/blender/sequencer/intern/iterator.cc @@ -79,7 +79,7 @@ void SEQ_iterator_set_expand(const Scene *scene, } /* Merge all expanded results in provided VectorSet. */ - query_matches.add_multiple(query_matches); + strips.add_multiple(query_matches); } static void query_all_strips_recursive(ListBase *seqbase, VectorSet &strips) @@ -94,20 +94,14 @@ static void query_all_strips_recursive(ListBase *seqbase, VectorSet VectorSet SEQ_query_all_strips_recursive(ListBase *seqbase) { - static VectorSet strips; - LISTBASE_FOREACH (Sequence *, seq, seqbase) { - if (seq->type == SEQ_TYPE_META) { - query_all_strips_recursive(&seq->seqbase, strips); - } - strips.add(seq); - } - + VectorSet strips; + query_all_strips_recursive(seqbase, strips); return strips; } VectorSet SEQ_query_all_strips(ListBase *seqbase) { - static VectorSet strips; + VectorSet strips; LISTBASE_FOREACH (Sequence *, strip, seqbase) { strips.add(strip); } diff --git a/source/blender/sequencer/intern/strip_add.cc b/source/blender/sequencer/intern/strip_add.cc index f890963fec0..0df221f1301 100644 --- a/source/blender/sequencer/intern/strip_add.cc +++ b/source/blender/sequencer/intern/strip_add.cc @@ -490,7 +490,7 @@ Sequence *SEQ_add_movie_strip(Main *bmain, Scene *scene, ListBase *seqbase, SeqL } } - seq->len = MAX2(1, seq->len); + seq->len = std::max(1, seq->len); if (load_data->adjust_playback_rate) { seq->flag |= SEQ_AUTO_PLAYBACK_RATE; } diff --git a/source/blender/sequencer/intern/strip_retiming.cc b/source/blender/sequencer/intern/strip_retiming.cc index 27805dabe2b..abff619694a 100644 --- a/source/blender/sequencer/intern/strip_retiming.cc +++ b/source/blender/sequencer/intern/strip_retiming.cc @@ -215,7 +215,7 @@ bool SEQ_retiming_key_is_transition_start(const SeqRetimingKey *key) SeqRetimingKey *SEQ_retiming_transition_start_get(SeqRetimingKey *key) { - if ((key->flag & SEQ_SPEED_TRANSITION_OUT)) { + if (key->flag & SEQ_SPEED_TRANSITION_OUT) { return key - 1; } if (key->flag & SEQ_SPEED_TRANSITION_IN) { diff --git a/source/blender/sequencer/intern/strip_transform.cc b/source/blender/sequencer/intern/strip_transform.cc index 3ece25f9844..ea10474494b 100644 --- a/source/blender/sequencer/intern/strip_transform.cc +++ b/source/blender/sequencer/intern/strip_transform.cc @@ -36,8 +36,6 @@ #include "CLG_log.h" -static CLG_LogRef LOG = {"seq.strip_transform"}; - bool SEQ_transform_single_image_check(Sequence *seq) { return (seq->flag & SEQ_SINGLE_FRAME_CONTENT) != 0; @@ -195,7 +193,8 @@ static bool shuffle_seq_test_overlap(const Scene *scene, const Sequence *seq2, const int offset) { - return (seq1 != seq2 && seq1->machine == seq2->machine && + BLI_assert(seq1 != seq2); + return (seq1->machine == seq2->machine && ((SEQ_time_right_handle_frame_get(scene, seq1) + offset <= SEQ_time_left_handle_frame_get(scene, seq2)) || (SEQ_time_left_handle_frame_get(scene, seq1) + offset >= @@ -214,16 +213,13 @@ static int shuffle_seq_time_offset_get(const Scene *scene, all_conflicts_resolved = true; for (Sequence *seq : strips_to_shuffle) { LISTBASE_FOREACH (Sequence *, seq_other, seqbasep) { - if (!shuffle_seq_test_overlap(scene, seq, seq_other, offset)) { + if (strips_to_shuffle.contains(seq_other)) { continue; } if (SEQ_relation_is_effect_of_strip(seq_other, seq)) { continue; } - if (UNLIKELY(strips_to_shuffle.contains(seq))) { - CLOG_WARN(&LOG, - "Strip overlaps with itself or another strip, that is to be shuffled. " - "This should never happen."); + if (!shuffle_seq_test_overlap(scene, seq, seq_other, offset)) { continue; } diff --git a/source/blender/windowmanager/intern/wm_event_query.cc b/source/blender/windowmanager/intern/wm_event_query.cc index 023a5e1c72c..8b15163bbae 100644 --- a/source/blender/windowmanager/intern/wm_event_query.cc +++ b/source/blender/windowmanager/intern/wm_event_query.cc @@ -624,7 +624,7 @@ int WM_event_absolute_delta_y(const wmEvent *event) * * \note Shift is excluded from this check since it prevented typing `Shift+Space`, see: #85517. */ -bool WM_event_is_ime_switch(const struct wmEvent *event) +bool WM_event_is_ime_switch(const wmEvent *event) { return (event->val == KM_PRESS) && (event->type == EVT_SPACEKEY) && (event->modifier & (KM_CTRL | KM_OSKEY | KM_ALT)); diff --git a/source/blender/windowmanager/intern/wm_playanim.cc b/source/blender/windowmanager/intern/wm_playanim.cc index 2e32ee3fe3b..cfac309b91f 100644 --- a/source/blender/windowmanager/intern/wm_playanim.cc +++ b/source/blender/windowmanager/intern/wm_playanim.cc @@ -1521,7 +1521,7 @@ static bool ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr ps_void) zoomy = float(ps->display_ctx.size[1]) / ps->ibuf_size[1]; /* Zoom always show entire image. */ - ps->zoom = MIN2(zoomx, zoomy); + ps->zoom = std::min(zoomx, zoomy); GPU_viewport(0, 0, ps->display_ctx.size[0], ps->display_ctx.size[1]); GPU_scissor(0, 0, ps->display_ctx.size[0], ps->display_ctx.size[1]); diff --git a/source/blender/windowmanager/intern/wm_splash_screen.cc b/source/blender/windowmanager/intern/wm_splash_screen.cc index 96eda527605..f3d80299898 100644 --- a/source/blender/windowmanager/intern/wm_splash_screen.cc +++ b/source/blender/windowmanager/intern/wm_splash_screen.cc @@ -262,7 +262,7 @@ void WM_OT_splash(wmOperatorType *ot) static uiBlock *wm_block_create_about(bContext *C, ARegion *region, void * /*arg*/) { const uiStyle *style = UI_style_get_dpi(); - const int text_points_max = MAX2(style->widget.points, style->widgetlabel.points); + const int text_points_max = std::max(style->widget.points, style->widgetlabel.points); const int dialog_width = text_points_max * 42 * UI_SCALE_FAC; uiBlock *block = UI_block_begin(C, region, "about", UI_EMBOSS); diff --git a/source/blender/windowmanager/intern/wm_window.cc b/source/blender/windowmanager/intern/wm_window.cc index 70599343582..6eda9cc4147 100644 --- a/source/blender/windowmanager/intern/wm_window.cc +++ b/source/blender/windowmanager/intern/wm_window.cc @@ -1704,7 +1704,7 @@ static bool wm_window_timers_process(const bContext *C, int *sleep_us_p) * Even though using `floor` or `round` is more responsive, * it causes CPU intensive loops that may run until the timer is reached, see: #111579. */ const double microseconds = 1000000.0; - const double sleep_sec = (double(sleep_us) / microseconds); + const double sleep_sec = double(sleep_us) / microseconds; const double sleep_sec_next = ntime_min - time; if (sleep_sec_next < sleep_sec) { diff --git a/source/creator/CMakeLists.txt b/source/creator/CMakeLists.txt index 720f89af127..3ed5635eff2 100644 --- a/source/creator/CMakeLists.txt +++ b/source/creator/CMakeLists.txt @@ -693,6 +693,10 @@ file(REMOVE ${CMAKE_BINARY_DIR}/bin/lib/libglapi.so.0.0.0)\n FILES ${CMAKE_SOURCE_DIR}/release/freedesktop/blender.desktop DESTINATION "./share/applications" ) + install( + FILES ${CMAKE_SOURCE_DIR}/release/freedesktop/org.blender.Blender.metainfo.xml + DESTINATION "./share/metainfo" + ) install( FILES ${CMAKE_SOURCE_DIR}/release/freedesktop/icons/scalable/apps/blender.svg DESTINATION "./share/icons/hicolor/scalable/apps" diff --git a/tests/python/CMakeLists.txt b/tests/python/CMakeLists.txt index c0aaf587396..ae022b1462f 100644 --- a/tests/python/CMakeLists.txt +++ b/tests/python/CMakeLists.txt @@ -22,10 +22,10 @@ file(MAKE_DIRECTORY ${TEST_OUT_DIR}/blendfile_io) # endif() # Run Blender command with parameters. -function(add_blender_test testname) +function(add_blender_test_impl testname exe) add_test( NAME ${testname} - COMMAND "${TEST_BLENDER_EXE}" ${TEST_BLENDER_EXE_PARAMS} ${ARGN} + COMMAND ${exe} ${ARGN} ) # Don't fail tests on leaks since these often happen in external libraries that we can't fix. @@ -41,6 +41,68 @@ function(add_blender_test testname) endif() endfunction() +function(add_blender_test testname) + add_blender_test_impl( + "${testname}" + "${TEST_BLENDER_EXE}" + ${TEST_BLENDER_EXE_PARAMS} + ${ARGN} + ) +endfunction() + +if(WITH_UI_TESTS) + set(_blender_headless_env_vars "BLENDER_BIN=${TEST_BLENDER_EXE}") + + # Currently only WAYLAND is supported, support for others may be added later. + # In this case none of the WESTON environment variables will be used. + if(WITH_GHOST_WAYLAND) + set(_weston_bin_in_libdir OFF) + if(DEFINED LIBDIR) + set(_weston_bin_default "${LIBDIR}/wayland_weston/bin/weston") + else() + set(_weston_bin_default "weston") + endif() + set(WESTON_BIN "${_weston_bin_default}" CACHE STRING "\ +The location of weston, leave blank for the default location." + ) + mark_as_advanced(WESTON_BIN) + if((DEFINED LIBDIR) AND ("${WESTON_BIN}" STREQUAL "${_weston_bin_default}")) + set(_weston_bin_in_libdir ON) + endif() + + list(APPEND _blender_headless_env_vars + "WESTON_BIN=${WESTON_BIN}" + ) + + if(_weston_bin_in_libdir) + list(APPEND _blender_headless_env_vars + "WAYLAND_ROOT_DIR=${LIBDIR}/wayland" + "WESTON_ROOT_DIR=${LIBDIR}/wayland_weston" + ) + endif() + endif() + + function(add_blender_test_headless testname) + # Remove `--background` so headless execution uses a GUI + # (within a headless graphical environment). + set(EXE_PARAMS ${TEST_BLENDER_EXE_PARAMS}) + list(REMOVE_ITEM EXE_PARAMS --background) + add_blender_test_impl( + "${testname}" + "${TEST_PYTHON_EXE}" + "${CMAKE_SOURCE_DIR}/tests/utils/blender_headless.py" + # NOTE: attempting to maximize the window causes problems with a headless `weston`, + # while this could be investigated, use windowed mode instead. + # Use a window size that balances software GPU rendering with enough room to use the UI. + --factory-startup + -p 0 0 800 600 + "${EXE_PARAMS}" + "${ARGN}" + ) + set_tests_properties(${testname} PROPERTIES ENVIRONMENT "${_blender_headless_env_vars}") + endfunction() +endif() + # Run Python script outside Blender. function(add_python_test testname testscript) if(NOT TEST_PYTHON_EXE) @@ -315,6 +377,13 @@ add_blender_test( --testdir "${TEST_SRC_DIR}/animation" ) +add_blender_test( + bl_animation_keyframing + --python ${CMAKE_CURRENT_LIST_DIR}/bl_animation_keyframing.py + -- + --testdir "${TEST_SRC_DIR}/animation" +) + add_blender_test( bl_rigging_symmetrize --python ${CMAKE_CURRENT_LIST_DIR}/bl_rigging_symmetrize.py @@ -1000,6 +1069,42 @@ else() endif() +# ------------------------------------------------------------------------------ +# Headless GUI Tests + +if(WITH_UI_TESTS) + # This could be generated with: + # `"${TEST_PYTHON_EXE}" "${CMAKE_CURRENT_LIST_DIR}/ui_simulate/run.py" --list-tests` + # list explicitly so changes bisecting/updated are sure to re-run CMake. + set(_undo_tests + test_undo.text_editor_edit_mode_mix + test_undo.text_editor_simple + test_undo.view3d_edit_mode_multi_window + test_undo.view3d_font_edit_mode_simple + test_undo.view3d_mesh_edit_separate + test_undo.view3d_mesh_particle_edit_mode_simple + test_undo.view3d_multi_mode_multi_window + test_undo.view3d_multi_mode_select + test_undo.view3d_sculpt_dyntopo_and_edit + test_undo.view3d_sculpt_dyntopo_simple + test_undo.view3d_sculpt_with_memfile_step + test_undo.view3d_simple + test_undo.view3d_texture_paint_complex + test_undo.view3d_texture_paint_simple + ) + foreach(ui_test ${_undo_tests}) + add_blender_test_headless( + "bf_ui_${ui_test}" + --enable-event-simulate + --python "${CMAKE_CURRENT_LIST_DIR}/ui_simulate/run_blender_setup.py" + -- + --tests "${ui_test}" + ) + endforeach() + unset(_undo_tests) +endif() + + add_subdirectory(collada) # TODO: disabled for now after collection unification diff --git a/tests/python/bl_animation_keyframing.py b/tests/python/bl_animation_keyframing.py new file mode 100644 index 00000000000..5eaf3460e87 --- /dev/null +++ b/tests/python/bl_animation_keyframing.py @@ -0,0 +1,218 @@ +# SPDX-FileCopyrightText: 2020-2023 Blender Authors +# +# SPDX-License-Identifier: GPL-2.0-or-later + +import unittest +import bpy +import pathlib +import sys +from math import radians + +""" +blender -b -noaudio --factory-startup --python tests/python/bl_animation_keyframing.py -- --testdir /path/to/lib/tests/animation +""" + + +def _fcurve_paths_match(fcurves: list, expected_paths: list) -> bool: + data_paths = list(set([fcurve.data_path for fcurve in fcurves])) + return sorted(data_paths) == sorted(expected_paths) + + +def _get_view3d_context(): + ctx = bpy.context.copy() + + for area in bpy.context.window.screen.areas: + if area.type != 'VIEW_3D': + continue + + ctx['area'] = area + ctx['space'] = area.spaces.active + break + + return ctx + + +def _create_animation_object(): + anim_object = bpy.data.objects.new("anim_object", None) + # Ensure that the rotation mode is correct so we can check against rotation_euler + anim_object.rotation_mode = "XYZ" + bpy.context.scene.collection.objects.link(anim_object) + bpy.context.view_layer.objects.active = anim_object + anim_object.select_set(True) + return anim_object + + +def _insert_by_name_test(insert_key: str, expected_paths: list): + keyed_object = _create_animation_object() + with bpy.context.temp_override(**_get_view3d_context()): + bpy.ops.anim.keyframe_insert_by_name(type=insert_key) + match = _fcurve_paths_match(keyed_object.animation_data.action.fcurves, expected_paths) + bpy.data.objects.remove(keyed_object, do_unlink=True) + return match + + +def _get_keying_set(scene, name: str): + return scene.keying_sets_all[scene.keying_sets_all.find(name)] + + +def _insert_with_keying_set_test(keying_set_name: str, expected_paths: list): + scene = bpy.context.scene + keying_set = _get_keying_set(scene, keying_set_name) + scene.keying_sets.active = keying_set + keyed_object = _create_animation_object() + with bpy.context.temp_override(**_get_view3d_context()): + bpy.ops.anim.keyframe_insert() + match = _fcurve_paths_match(keyed_object.animation_data.action.fcurves, expected_paths) + bpy.data.objects.remove(keyed_object, do_unlink=True) + return match + + +class AbstractKeyframingTest: + def setUp(self): + super().setUp() + bpy.ops.wm.read_homefile(use_factory_startup=True) + + +class InsertKeyTest(AbstractKeyframingTest, unittest.TestCase): + """ Ensure keying things by name or with a keying set adds the right keys. """ + + def test_insert_by_name(self): + self.assertTrue(_insert_by_name_test("Location", ["location"])) + self.assertTrue(_insert_by_name_test("Rotation", ["rotation_euler"])) + self.assertTrue(_insert_by_name_test("Scaling", ["scale"])) + self.assertTrue(_insert_by_name_test("LocRotScale", ["location", "rotation_euler", "scale"])) + + def test_insert_with_keying_set(self): + self.assertTrue(_insert_with_keying_set_test("Location", ["location"])) + self.assertTrue(_insert_with_keying_set_test("Rotation", ["rotation_euler"])) + self.assertTrue(_insert_with_keying_set_test("Scale", ["scale"])) + self.assertTrue(_insert_with_keying_set_test("Location, Rotation & Scale", ["location", "rotation_euler", "scale"])) + + +class VisualKeyingTest(AbstractKeyframingTest, unittest.TestCase): + """ Check if visual keying produces the correct keyframe values. """ + + def test_visual_location_keying_set(self): + t_value = 1 + target = _create_animation_object() + target.location = (t_value, t_value, t_value) + constrained = _create_animation_object() + constraint = constrained.constraints.new("COPY_LOCATION") + constraint.target = target + + with bpy.context.temp_override(**_get_view3d_context()): + bpy.ops.anim.keyframe_insert_by_name(type="BUILTIN_KSI_VisualLoc") + + for fcurve in constrained.animation_data.action.fcurves: + self.assertEqual(fcurve.keyframe_points[0].co.y, t_value) + + bpy.data.objects.remove(target, do_unlink=True) + bpy.data.objects.remove(constrained, do_unlink=True) + + def test_visual_rotation_keying_set(self): + rot_value_deg = 45 + rot_value_rads = radians(rot_value_deg) + + target = _create_animation_object() + target.rotation_euler = (rot_value_rads, rot_value_rads, rot_value_rads) + constrained = _create_animation_object() + constraint = constrained.constraints.new("COPY_ROTATION") + constraint.target = target + + with bpy.context.temp_override(**_get_view3d_context()): + bpy.ops.anim.keyframe_insert_by_name(type="BUILTIN_KSI_VisualRot") + + for fcurve in constrained.animation_data.action.fcurves: + self.assertAlmostEqual(fcurve.keyframe_points[0].co.y, rot_value_rads, places=4) + + bpy.data.objects.remove(target, do_unlink=True) + bpy.data.objects.remove(constrained, do_unlink=True) + + def test_visual_location_user_pref(self): + # When enabling the user preference setting, + # the normal keying sets behave like their visual keying set counterpart. + bpy.context.preferences.edit.use_visual_keying = True + t_value = 1 + target = _create_animation_object() + target.location = (t_value, t_value, t_value) + constrained = _create_animation_object() + constraint = constrained.constraints.new("COPY_LOCATION") + constraint.target = target + + with bpy.context.temp_override(**_get_view3d_context()): + bpy.ops.anim.keyframe_insert_by_name(type="Location") + + for fcurve in constrained.animation_data.action.fcurves: + self.assertEqual(fcurve.keyframe_points[0].co.y, t_value) + + bpy.data.objects.remove(target, do_unlink=True) + bpy.data.objects.remove(constrained, do_unlink=True) + bpy.context.preferences.edit.use_visual_keying = False + + +class CycleAwareKeyingTest(AbstractKeyframingTest, unittest.TestCase): + """ Check if cycle aware keying remaps the keyframes correctly and adds fcurve modifiers. """ + + def test_insert_location_cycle_aware(self): + # In order to make cycle aware keying work, the action needs to be created and have the + # frame_range set plus the use_frame_range flag set to True. + keyed_object = _create_animation_object() + bpy.context.scene.tool_settings.use_keyframe_cycle_aware = True + + with bpy.context.temp_override(**_get_view3d_context()): + bpy.ops.anim.keyframe_insert_by_name(type="Location") + + action = keyed_object.animation_data.action + action.use_cyclic = True + action.use_frame_range = True + cyclic_range_end = 20 + action.frame_range = [1, cyclic_range_end] + + with bpy.context.temp_override(**_get_view3d_context()): + bpy.context.scene.frame_set(5) + bpy.ops.anim.keyframe_insert_by_name(type="Location") + + # Will be mapped to frame 3. + bpy.context.scene.frame_set(22) + bpy.ops.anim.keyframe_insert_by_name(type="Location") + + # Will be mapped to frame 9. + bpy.context.scene.frame_set(-10) + bpy.ops.anim.keyframe_insert_by_name(type="Location") + + # Check that only location keys have been created. + self.assertTrue(_fcurve_paths_match(action.fcurves, ["location"])) + + expected_keys = [1, 3, 5, 9, 20] + + for fcurve in action.fcurves: + self.assertEqual(len(fcurve.keyframe_points), len(expected_keys)) + key_index = 0 + for key in fcurve.keyframe_points: + self.assertEqual(key.co.x, expected_keys[key_index]) + key_index += 1 + + # All fcurves should have a cycles modifier. + self.assertTrue(fcurve.modifiers[0].type == "CYCLES") + + bpy.data.objects.remove(keyed_object, do_unlink=True) + + +def main(): + global args + import argparse + + if '--' in sys.argv: + argv = [sys.argv[0]] + sys.argv[sys.argv.index('--') + 1:] + else: + argv = sys.argv + + parser = argparse.ArgumentParser() + parser.add_argument('--testdir', required=True, type=pathlib.Path) + args, remaining = parser.parse_known_args(argv) + + unittest.main(argv=remaining) + + +if __name__ == "__main__": + main() diff --git a/tests/python/bl_node_group_compat.py b/tests/python/bl_node_group_compat.py index 7138ac621f5..3e3002618e8 100644 --- a/tests/python/bl_node_group_compat.py +++ b/tests/python/bl_node_group_compat.py @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: 2021-2023 Blender Foundation +# SPDX-FileCopyrightText: 2021-2023 Blender Authors # # SPDX-License-Identifier: GPL-2.0-or-later diff --git a/tests/python/bl_node_group_interface.py b/tests/python/bl_node_group_interface.py index 61beed4b444..7f5582507c8 100644 --- a/tests/python/bl_node_group_interface.py +++ b/tests/python/bl_node_group_interface.py @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: 2021-2023 Blender Foundation +# SPDX-FileCopyrightText: 2021-2023 Blender Authors # # SPDX-License-Identifier: GPL-2.0-or-later diff --git a/tests/python/compositor_realtime_render_tests.py b/tests/python/compositor_realtime_render_tests.py index 946cac753ac..11d92e6bd84 100644 --- a/tests/python/compositor_realtime_render_tests.py +++ b/tests/python/compositor_realtime_render_tests.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# SPDX-FileCopyrightText: 2015-2023 Blender Foundation +# SPDX-FileCopyrightText: 2015-2023 Blender Authors # # SPDX-License-Identifier: Apache-2.0 diff --git a/tests/python/ui_simulate/modules/__init__.py b/tests/python/ui_simulate/modules/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/python/ui_simulate/modules/easy_keys.py b/tests/python/ui_simulate/modules/easy_keys.py new file mode 100644 index 00000000000..dbeffae1110 --- /dev/null +++ b/tests/python/ui_simulate/modules/easy_keys.py @@ -0,0 +1,359 @@ +# SPDX-FileCopyrightText: 2019-2023 Blender Authors +# +# SPDX-License-Identifier: GPL-2.0-or-later + +import string +import bpy +event_types = tuple( + e.identifier.lower() + for e in bpy.types.Event.bl_rna.properties["type"].enum_items_static +) +del bpy + +# We don't normally care about which one. +event_types_alias = { + "ctrl": "left_ctrl", + "shift": "left_shift", + "alt": "left_alt", + + # Collides with Python keywords. + "delete": "del", +} + + +# Note, we could add support for other keys using control characters, +# for example: `\xF12` could be used for the F12 key. +# +# Besides this, we could encode symbols into a regular string using our own syntax +# which can mix regular text and key symbols. +# +# At the moment this doesn't seem necessary, no need to add it. +event_types_text = ( + ('ZERO', "0", False), + ('ONE', "1", False), + ('TWO', "2", False), + ('THREE', "3", False), + ('FOUR', "4", False), + ('FIVE', "5", False), + ('SIX', "6", False), + ('SEVEN', "7", False), + ('EIGHT', "8", False), + ('NINE', "9", False), + + ('ONE', "!", True), + ('TWO', "@", True), + ('THREE', "#", True), + ('FOUR', "$", True), + ('FIVE', "%", True), + ('SIX', "^", True), + ('SEVEN', "&", True), + ('EIGHT', "*", True), + ('NINE', "(", True), + ('ZERO', ")", True), + + ('MINUS', "-", False), + ('MINUS', "_", True), + + ('EQUAL', "=", False), + ('EQUAL', "+", True), + + ('ACCENT_GRAVE', "`", False), + ('ACCENT_GRAVE', "~", True), + + ('LEFT_BRACKET', "[", False), + ('LEFT_BRACKET', "{", True), + + ('RIGHT_BRACKET', "]", False), + ('RIGHT_BRACKET', "}", True), + + ('SEMI_COLON', ";", False), + ('SEMI_COLON', ":", True), + + ('PERIOD', ".", False), + ('PERIOD', ">", True), + + ('COMMA', ",", False), + ('COMMA', "<", True), + + ('QUOTE', "'", False), + ('QUOTE', '"', True), + + ('SLASH', "/", False), + ('SLASH', "?", True), + + ('BACK_SLASH', "\\", False), + ('BACK_SLASH', "|", True), + + + *((ch_upper, ch, False) for (ch_upper, ch) in zip(string.ascii_uppercase, string.ascii_lowercase)), + *((ch, ch, True) for ch in string.ascii_uppercase), + + ('SPACE', " ", False), + ('RET', "\n", False), + ('TAB', "\t", False), +) + +event_types_text_from_char = {ch: (ty, is_shift) for (ty, ch, is_shift) in event_types_text} +event_types_text_from_event = {(ty, is_shift): ch for (ty, ch, is_shift) in event_types_text} + + +class _EventBuilder: + __slots__ = ( + "_shared_event_gen", + "_event_type", + "_parent", + ) + + def __init__(self, event_gen, ty): + self._shared_event_gen = event_gen + self._event_type = ty + self._parent = None + + def __call__(self, count=1): + assert count >= 0 + for _ in range(count): + self.tap() + return self._shared_event_gen + + def _key_press_release(self, do_press=False, do_release=False, unicode_override=None): + assert (do_press or do_release) + keys_held = self._shared_event_gen._event_types_held + build_keys = [] + e = self + while e is not None: + build_keys.append(e._event_type.upper()) + e = e._parent + build_keys.reverse() + + events = [None, None] + for i, value in enumerate(('PRESS', 'RELEASE')): + if value == 'RELEASE': + build_keys.reverse() + for event_type in build_keys: + if value == 'PRESS': + keys_held.add(event_type) + else: + keys_held.remove(event_type) + + if (not do_press) and value == 'PRESS': + continue + if (not do_release) and value == 'RELEASE': + continue + + shift = 'LEFT_SHIFT' in keys_held or 'RIGHT_SHIFT' in keys_held + ctrl = 'LEFT_CTRL' in keys_held or 'RIGHT_CTRL' in keys_held + shift = 'LEFT_SHIFT' in keys_held or 'RIGHT_SHIFT' in keys_held + alt = 'LEFT_ALT' in keys_held or 'RIGHT_ALT' in keys_held + oskey = 'OSKEY' in keys_held + + unicode = None + if value == 'PRESS': + if ctrl is False and alt is False and oskey is False: + if unicode_override is not None: + unicode = unicode_override + else: + unicode = event_types_text_from_event.get((event_type, shift)) + if unicode is None and shift: + # Some keys don't care about shift + unicode = event_types_text_from_event.get((event_type, False)) + + event = self._shared_event_gen.window.event_simulate( + type=event_type, + value=value, + unicode=unicode, + shift=shift, + ctrl=ctrl, + alt=alt, + oskey=oskey, + x=self._shared_event_gen._mouse_co[0], + y=self._shared_event_gen._mouse_co[1], + ) + events[i] = event + return tuple(events) + + def tap(self): + return self._key_press_release(do_press=True, do_release=True) + + def press(self): + return self._key_press_release(do_press=True)[0] + + def release(self): + return self._key_press_release(do_release=True)[1] + + def cursor_motion(self, coords): + coords = list(coords) + self._shared_event_gen.cursor_position_set(*coords[0], move=True) + yield + + event = self.press() + shift = event.shift + ctrl = event.ctrl + shift = event.shift + alt = event.alt + oskey = event.oskey + yield + + for x, y in coords: + self._shared_event_gen.window.event_simulate( + type='MOUSEMOVE', + value='NOTHING', + unicode=None, + shift=shift, + ctrl=ctrl, + alt=alt, + oskey=oskey, + x=x, + y=y + ) + yield + self._shared_event_gen.cursor_position_set(x, y, move=False) + self.release() + yield + + def __getattr__(self, attr): + attr = event_types_alias.get(attr, attr) + if attr in event_types: + e = _EventBuilder(self._shared_event_gen, attr) + e._parent = self + return e + raise Exception(f"{attr!r} not found in {event_types!r}") + + +class EventGenerate: + __slots__ = ( + "window", + + "_mouse_co", + "_event_types_held", + ) + + def __init__(self, window): + self.window = window + self._mouse_co = [0, 0] + self._event_types_held = set() + + self.cursor_position_set(window.width // 2, window.height // 2) + + def cursor_position_set(self, x, y, move=False): + self._mouse_co[:] = x, y + if move: + self.window.event_simulate( + type='MOUSEMOVE', + value='NOTHING', + x=x, + y=y, + ) + + def text(self, text): + """ Type in entire phrases. """ + for ch in text: + ty, shift = event_types_text_from_char[ch] + ty = ty.lower() + if shift: + eb = getattr(_EventBuilder(self, 'left_shift'), ty) + else: + eb = _EventBuilder(self, ty) + eb.tap() + return self + + def text_unicode(self, text): + # Since the only purpose of this key-press is to enter text + # the key can be almost anything, use a key which isn't likely to be assigned ot any other action. + # + # If it were possible `EVT_UNKNOWNKEY` would be most correct + # as dead keys map to this and still enter text. + ty_dummy = 'F24' + for ch in text: + eb = _EventBuilder(self, ty_dummy) + eb._key_press_release(do_press=True, do_release=True, unicode_override=ch) + return self + + def __getattr__(self, attr): + attr = event_types_alias.get(attr, attr) + if attr in event_types: + return _EventBuilder(self, attr) + raise Exception(f"{attr!r} not found in {event_types!r}") + + def __del__(self): + if self._event_types_held: + print("'__del__' with keys held:", repr(self._event_types_held)) + + +def run( + event_iter, *, + on_error=None, + on_exit=None, + on_step_command_pre=None, + on_step_command_post=None, +): + import bpy + + TICKS = 4 # 3 works, 4 to be on the safe side. + + def event_step(): + # Run once 'TICKS' is reached. + if event_step._ticks < TICKS: + event_step._ticks += 1 + return 0.0 + event_step._ticks = 0 + + if on_step_command_pre: + if event_step.run_events.gi_frame is not None: + import shlex + import subprocess + subprocess.call( + shlex.split( + on_step_command_pre.replace( + "{file}", event_step.run_events.gi_frame.f_code.co_filename, + ).replace( + "{line}", str(event_step.run_events.gi_frame.f_lineno), + ) + ) + ) + try: + val = next(event_step.run_events, Ellipsis) + except Exception: + import traceback + traceback.print_exc() + if on_error is not None: + on_error() + if on_exit is not None: + on_exit() + return None + + if on_step_command_post: + if event_step.run_events.gi_frame is not None: + import shlex + import subprocess + subprocess.call( + shlex.split( + on_step_command_post.replace( + "{file}", event_step.run_events.gi_frame.f_code.co_filename, + ).replace( + "{line}", str(event_step.run_events.gi_frame.f_lineno), + ) + ) + ) + + if isinstance(val, EventGenerate) or val is None: + return 0.0 + elif val is Ellipsis: + if on_exit is not None: + on_exit() + return None + else: + raise Exception(f"{val!r} of type {type(val)!r} not supported") + + event_step.run_events = iter(event_iter) + event_step._ticks = 0 + + bpy.app.timers.register(event_step, first_interval=0.0) + + +def setup_default_preferences(preferences): + """ Set preferences useful for automation. + """ + preferences.view.show_splash = False + preferences.view.smooth_view = 0 + preferences.view.use_save_prompt = False + preferences.filepaths.use_auto_save_temporary_files = False diff --git a/tests/python/ui_simulate/run.py b/tests/python/ui_simulate/run.py new file mode 100755 index 00000000000..e6eb031d755 --- /dev/null +++ b/tests/python/ui_simulate/run.py @@ -0,0 +1,193 @@ +#!/usr/bin/env python3 +# SPDX-FileCopyrightText: 2019-2023 Blender Authors +# +# SPDX-License-Identifier: GPL-2.0-or-later + +""" +Run interaction tests using event simulation. + +Example usage from Blender's source dir: + +This uses ``test_undo.py``, running the ``text_editor_simple`` function. + +To run all tests: + + ./tests/python/ui_simulate/run.py --blender=blender.bin --tests '*' + +For an editor to follow the tests: + + ./tests/python/ui_simulate/run.py --blender=blender.bin --tests '*' \ + --step-command-pre='gvim --remote-silent +{line} "{file}"' + +""" + +import os +import sys + + +def create_parser(): + import argparse + parser = argparse.ArgumentParser( + description=__doc__, + formatter_class=argparse.RawTextHelpFormatter, + ) + parser.add_argument( + "--blender", + dest="blender", + required=True, + metavar="BLENDER_COMMAND", + help="Location of the blender command to run (when quoted, may include arguments).", + ) + + parser.add_argument( + "--tests", + dest="tests", + nargs='+', + required=True, + metavar="TEST_ID", + help="Names of tests to run, use '*' to run all tests.", + ) + + parser.add_argument( + "--jobs", "-j", + dest="jobs", + default=1, + type=int, + help="Number of tests (and instances of Blender) to run in parallel.", + ) + + parser.add_argument( + "--keep-open", + dest="keep_open", + default=False, + action='store_true', + required=False, + help="Keep the Blender window open after running the test.", + ) + + parser.add_argument( + "--list-tests", + dest="list_tests", + default=False, + action='store_true', + required=False, + help="Show a list of available TEST_ID.", + ) + + parser.add_argument( + "--step-command-pre", + dest="step_command_pre", + required=False, + metavar="STEP_COMMAND_PRE", + help=( + "Command to run that takes the test file and line as arguments. " + "Literals {file} and {line} will be replaced with the file and line." + "Called for every event." + "Called for every event, allows an editor to track which commands run." + ) + ) + parser.add_argument( + "--step-command-post", + dest="step_command_post", + required=False, + metavar="STEP_COMMAND_POST", + help=( + "Command to run that takes the test file and line as arguments. " + "Literals {file} and {line} will be replaced with the file and line." + "Called for every event, allows an editor to track which commands run." + ) + ) + + return parser + + +def all_test_ids(directory): + from types import FunctionType + for f in sorted(os.listdir(directory)): + if f.startswith("test_") and f.endswith(".py"): + mod = __import__(f[:-3]) + for k, v in sorted(vars(mod).items()): + if not k.startswith("_") and isinstance(v, FunctionType): + yield f.rpartition(".")[0] + "." + k + + +def list_tests(directory): + for test_id in all_test_ids(directory): + print(test_id) + sys.exit(0) + + +def _process_test_id_fn(env, args, test_id): + import subprocess + import shlex + + directory = os.path.dirname(__file__) + cmd = ( + *shlex.split(args.blender), + "--enable-event-simulate", + "--factory-startup", + "--python", os.path.join(directory, "run_blender_setup.py"), + "--", + "--tests", test_id, + *(("--keep-open",) if args.keep_open else ()), + *(("--step-command-pre", args.step_command_pre) if args.step_command_pre else ()), + *(("--step-command-post", args.step_command_post) if args.step_command_post else ()), + ) + callproc = subprocess.run(cmd, env=env) + return test_id, callproc.returncode == 0 + + +def main(): + directory = os.path.dirname(__file__) + if "--list-tests" in sys.argv: + list_tests(directory) + sys.exit(0) + + if "bpy" in sys.modules: + raise Exception("Cannot run inside Blender") + + parser = create_parser() + args = parser.parse_args() + + tests = args.tests + + # Validate tests exist + test_ids = list(all_test_ids(directory)) + if tests[0] == "*": + tests = test_ids + else: + for test_id in tests: + if test_id not in test_ids: + print(test_id, "not found in", test_ids) + return + + env = os.environ.copy() + env.update({ + "LSAN_OPTIONS": "exitcode=0", + }) + + # We could support multiple tests per Blender session. + results = [] + results_fail = 0 + if args.jobs <= 1: + for test_id in tests: + _, success = _process_test_id_fn(env, args, test_id) + results.append((test_id, success)) + if not success: + results_fail += 1 + else: + from concurrent.futures import ProcessPoolExecutor + executor = ProcessPoolExecutor(max_workers=args.jobs) + num_tests = len(tests) + for test_id, success in executor.map(_process_test_id_fn, (env,) * num_tests, (args,) * num_tests, tests): + results.append((test_id, success)) + if not success: + results_fail += 1 + + print(len(results), "tests,", results_fail, "failed") + for test_id, ok in results: + print("OK: " if ok else "FAIL:", test_id) + + +if __name__ == "__main__": + main() diff --git a/tests/python/ui_simulate/run_blender_setup.py b/tests/python/ui_simulate/run_blender_setup.py new file mode 100644 index 00000000000..49d3e65e6e7 --- /dev/null +++ b/tests/python/ui_simulate/run_blender_setup.py @@ -0,0 +1,115 @@ +# SPDX-FileCopyrightText: 2019-2023 Blender Authors +# +# SPDX-License-Identifier: GPL-2.0-or-later + +""" +Utility script, called by ``run.py`` to run inside Blender, +to avoid boiler plate code having to be added into each test. +""" + +import os +import sys + + +def create_parser(): + import argparse + parser = argparse.ArgumentParser( + description=__doc__, + formatter_class=argparse.RawTextHelpFormatter, + ) + + parser.add_argument( + "--keep-open", + dest="keep_open", + default=False, + action='store_true', + required=False, + help="Keep the Blender window open after running the test.", + ) + + parser.add_argument( + "--step-command-pre", + dest="step_command_pre", + default=None, + required=False, + help="See 'run.py'", + ) + parser.add_argument( + "--step-command-post", + dest="step_command_post", + default=None, + required=False, + help="See 'run.py'", + ) + + parser.add_argument( + "--tests", + dest="tests", + nargs='+', + required=True, + metavar="TEST_ID", + help="Names of tests to run.", + ) + + return parser + + +def main(): + directory = os.path.dirname(__file__) + sys.path.insert(0, directory) + if "bpy" not in sys.modules: + raise Exception("This must run inside Blender") + import bpy + + parser = create_parser() + args = parser.parse_args(sys.argv[sys.argv.index("--") + 1:]) + + # Check if `bpy.app.use_event_simulate` has been enabled by the test it's self. + # When writing tests, it's useful if the test can temporarily be set to keep the window open. + + def on_error(): + if not bpy.app.use_event_simulate: + args.keep_open = True + + if not args.keep_open: + sys.exit(1) + + def on_exit(): + if not bpy.app.use_event_simulate: + args.keep_open = True + + if not args.keep_open: + sys.exit(0) + else: + bpy.app.use_event_simulate = False + + is_first = True + for test_id in args.tests: + if not is_first: + bpy.ops.wm.read_homefile() + is_first = False + + mod_name, fn_name = test_id.partition(".")[0::2] + mod = __import__(mod_name) + test_fn = getattr(mod, fn_name) + + from modules import easy_keys + + # So we can get the operator ID's. + bpy.context.preferences.view.show_developer_ui = True + + # Hack back in operator search. + + easy_keys.setup_default_preferences(bpy.context.preferences) + easy_keys.run( + test_fn(), + on_error=on_error, + on_exit=on_exit, + # Optional. + on_step_command_pre=args.step_command_pre, + on_step_command_post=args.step_command_post, + ) + + +if __name__ == "__main__": + main() diff --git a/tests/python/ui_simulate/test_undo.py b/tests/python/ui_simulate/test_undo.py new file mode 100644 index 00000000000..c88362de377 --- /dev/null +++ b/tests/python/ui_simulate/test_undo.py @@ -0,0 +1,902 @@ +# SPDX-FileCopyrightText: 2019-2023 Blender Authors +# +# SPDX-License-Identifier: GPL-2.0-or-later + +""" +This file does not run anything, it's methods are accessed for tests by: ``run.py``. +""" + +# FIXME: Since 2.8 or so, there is a problem with simulated events +# where a popup needs the main-loop to cycle once before new events +# are handled. This isn't great but seems not to be a problem for users? +_MENU_CONFIRM_HACK = True + + +# ----------------------------------------------------------------------------- +# Utilities + +def _keep_open(): + """ + Only for development, handy so we can quickly keep the window open while testing. + """ + import bpy + bpy.app.use_event_simulate = False + + +def _test_window(windows_exclude=None): + import bpy + wm = bpy.data.window_managers[0] + # Use -1 so the last added window is always used. + if windows_exclude is None: + return wm.windows[0] + for window in wm.windows: + if window not in windows_exclude: + return window + return None + + +def _test_vars(window): + import unittest + from modules.easy_keys import EventGenerate + return ( + EventGenerate(window), + unittest.TestCase(), + ) + + +def _call_by_name(e, text: str): + yield e.f3() + yield e.text(text) + yield e.ret() + + +def _call_menu(e, text: str): + yield e.f3() + yield e.text_unicode(text.replace(" -> ", " \u25b8 ")) + yield e.ret() + + +def _cursor_motion_data_x(window): + size = window.width, window.height + return [ + (x, size[1] // 2) for x in + range(int(size[0] * 0.2), int(size[0] * 0.8), 80) + ] + + +def _cursor_motion_data_y(window): + size = window.width, window.height + return [ + (size[0] // 2, y) for y in + range(int(size[1] * 0.2), int(size[1] * 0.8), 80) + ] + + +def _window_area_get_by_type(window, space_type): + for area in window.screen.areas: + if area.type == space_type: + return area + + +def _cursor_position_from_area(area): + return ( + area.x + area.width // 2, + area.y + area.height // 2, + ) + + +def _cursor_position_from_spacetype(window, space_type): + area = _window_area_get_by_type(window, space_type) + if area is None: + raise Exception("Space Type %r not found" % space_type) + return _cursor_position_from_area(area) + + +def _view3d_object_calc_screen_space_location(window, name: str): + from bpy_extras.view3d_utils import location_3d_to_region_2d + + area = _window_area_get_by_type(window, 'VIEW_3D') + region = next((region for region in area.regions if region.type == 'WINDOW')) + rv3d = region.data + + ob = window.view_layer.objects[name] + co = location_3d_to_region_2d(region, rv3d, ob.matrix_world.translation) + return int(co[0]), int(co[1]) + + +def _view3d_object_select_by_name(e, name: str): + location = _view3d_object_calc_screen_space_location(e.window, name) + e.cursor_position_set(*location, move=True) + # e.shift.rightmouse.tap() # Set the cursor so it's possible to see what was selected. + yield + e.ctrl.leftmouse.tap() + yield + + +def _setup_window_areas_from_ui_types(e, ui_types): + assert len(e.window.screen.areas) == 1 + total_areas = len(ui_types) + i = 0 + while len(e.window.screen.areas) < total_areas: + areas = list(e.window.screen.areas) + for area in areas: + event_xy = _cursor_position_from_area(area) + e.cursor_position_set(x=event_xy[0], y=event_xy[1], move=True) + # areas_len_prev = len(e.window.screen.areas) + if (i % 2) == 0: + yield from _call_menu(e, "View -> Area -> Horizontal Split") + else: + yield from _call_menu(e, "View -> Area -> Vertical Split") + e.leftmouse.tap() + yield + # areas_len_curr = len(e.window.screen.areas) + # assert areas_len_curr != areas_len_prev + if len(e.window.screen.areas) >= total_areas: + break + i += 1 + + # Use direct assignment, it's possible to use shortcuts for most area types, it's tedious. + for ty, area in zip(ui_types, e.window.screen.areas, strict=True): + area.ui_type = ty + yield + + +def _print_undo_steps_and_line(): + """ + Keep even when unused, handy for tracking down problems. + """ + from inspect import currentframe + cf = currentframe() + line = cf.f_back.f_lineno + + import bpy + wm = bpy.data.window_managers[0] + print(__file__ + ":" + str(line)) + wm.print_undo_steps() + + +def _bmesh_from_object(ob): + import bmesh + return bmesh.from_edit_mesh(ob.data) + + +# ----------------------------------------------------------------------------- +# Text Editor + +def _text_editor_startup(e): + yield e.shift.f11() # Text editor. + yield e.ctrl.alt.space() # Full-screen. + yield e.alt.n() # New text. + + +def _text_editor_and_3dview_startup(e, window): + # Add text block in properties editors. + pos_text = _cursor_position_from_spacetype(window, 'PROPERTIES') + e.cursor_position_set(*pos_text, move=True) + yield e.shift.f11() # Text editor. + yield e.alt.n() # New text. + + +def text_editor_simple(): + e, t = _test_vars(_test_window()) + + import bpy + yield from _text_editor_startup(e) + text = bpy.data.texts[0] + + yield e.text("Hello\nWorld") + t.assertEqual(text.as_string(), "Hello\nWorld") + yield e.shift.home().ctrl.x().back_space() + yield e.home().ctrl.v().ret() + t.assertEqual(text.as_string(), "World\nHello") + yield e.ctrl.a().tab() + t.assertEqual(text.as_string(), " World\n Hello") + yield e.ctrl.z(5) + t.assertEqual(text.as_string(), "Hello\nWorld") + + +def text_editor_edit_mode_mix(): + # Ensure text edits and mesh edits can co-exist properly (see: T66658). + e, t = _test_vars(window := _test_window()) + + import bpy + yield from _text_editor_and_3dview_startup(e, window) + text = bpy.data.texts[0] + + pos_text = _cursor_position_from_spacetype(window, 'TEXT_EDITOR') + pos_v3d = _cursor_position_from_spacetype(window, 'VIEW_3D') + + # View 3D: edit-mode + e.cursor_position_set(*pos_v3d, move=True) + yield from _call_menu(e, "Add -> Mesh -> Cube") + + yield e.numpad_period() # View all. + yield e.tab() # Edit mode. + yield e.a() # Select all. + + # Text: add text 'AA'. + e.cursor_position_set(*pos_text, move=True) + yield e.text("AA") + t.assertEqual(text.as_string(), "AA") + + # View 3D: duplicate & move. + e.cursor_position_set(*pos_v3d, move=True) + yield e.shift.d().x().text("3").ret() + yield e.g().z().text("1").ret() + t.assertEqual(len(_bmesh_from_object(window.view_layer.objects.active).verts), 8 * 2) + e.home() + + # Text: add text 'BB' + e.cursor_position_set(*pos_text, move=True) + yield e.text("BB") + t.assertEqual(text.as_string(), "AABB") + + # View 3D: duplicate & move. + e.cursor_position_set(*pos_v3d, move=True) + yield e.shift.d().x().text("3").ret() + yield e.g().z().text("1").ret() + e.home() + t.assertEqual(len(_bmesh_from_object(window.view_layer.objects.active).verts), 8 * 3) + + # Text: add text 'CC' + e.cursor_position_set(*pos_text, move=True) + yield e.text("CC") + t.assertEqual(text.as_string(), "AABBCC") + + # View 3D: duplicate & move. + e.cursor_position_set(*pos_v3d, move=True) + yield e.shift.d().x().text("3").ret() + yield e.g().z().text("1").ret() + e.home() + t.assertEqual(len(_bmesh_from_object(window.view_layer.objects.active).verts), 8 * 4) + + # Undo and check the state is valid. + yield e.ctrl.z(4) + t.assertEqual(len(_bmesh_from_object(window.view_layer.objects.active).verts), 8 * 3) + t.assertEqual(text.as_string(), "AABB") + + yield e.ctrl.z(4) + t.assertEqual(len(_bmesh_from_object(window.view_layer.objects.active).verts), 8 * 2) + t.assertEqual(text.as_string(), "AA") + + yield e.ctrl.z(4) + t.assertEqual(len(_bmesh_from_object(window.view_layer.objects.active).verts), 8) + t.assertEqual(text.as_string(), "") + + # Finally redo all. + yield e.ctrl.shift.z(4 * 3) + t.assertEqual(len(_bmesh_from_object(window.view_layer.objects.active).verts), 8 * 4) + t.assertEqual(text.as_string(), "AABBCC") + + +# ----------------------------------------------------------------------------- +# 3D View + +def _view3d_startup_area_maximized(e): + """ + Set the 3D viewport and set the area full-screen so no other regions. + """ + yield e.shift.f5() # 3D Viewport. + yield e.ctrl.alt.space() # Full-screen. + yield e.a() # Select all. + yield e.delete().ret() # Delete all. + + +def _view3d_startup_area_single(e): + """ + Create a single area (not full screen) + this has the advantage that the window can be duplicated (not the case with a full-screened area). + """ + yield e.shift.f5() # 3D Viewport. + yield e.a() # Select all. + yield e.delete().ret() # Delete all. + + for _ in range(len(e.window.screen.areas)): + # 3D Viewport. + event_xy = _cursor_position_from_spacetype(e.window, e.window.screen.areas[0].type) + e.cursor_position_set(x=event_xy[0], y=event_xy[1], move=True) + yield e.shift.f5() + yield from _call_menu(e, "View -> Area -> Close Area") + assert len(e.window.screen.areas) == 1 + + +def view3d_simple(): + e, t = _test_vars(window := _test_window()) + yield from _view3d_startup_area_maximized(e) + + yield from _call_menu(e, "Add -> Mesh -> Plane") + # Duplicate and rotate. + for _ in range(3): + yield e.shift.d().x().text("3").ret() + yield e.r.z().text("15").ret() + t.assertEqual(len(window.view_layer.objects), 4) + yield e.a() # Select all. + yield e.numpad_7().numpad_period() # View top. + yield e.ctrl.j() # Join. + t.assertEqual(len(window.view_layer.objects), 1) + yield e.tab() # Edit mode. + yield from _call_menu(e, "Edge -> Subdivide") + yield e.tab() # Object mode. + t.assertEqual(len(window.view_layer.objects.active.data.polygons), 16) + yield e.ctrl.z(12) # Undo until start. + t.assertEqual(len(window.view_layer.objects), 0) + yield e.ctrl.shift.z(12) # Redo until end. + t.assertEqual(len(window.view_layer.objects.active.data.polygons), 16) + + +def view3d_sculpt_with_memfile_step(): + e, t = _test_vars(window := _test_window()) + yield from _view3d_startup_area_maximized(e) + + yield from _call_menu(e, "Add -> Mesh -> Torus") + + # Note: this could also be replaced by adding the multires modifier (see comment below). + yield e.tab() # Enter Edit mode. + yield e.ctrl.e().d() # Subdivide. + yield e.ctrl.e().d() # Subdivide. + yield e.tab() # Leave Edit mode. + + yield e.numpad_period() # View all. + yield e.ctrl.tab().s() # Sculpt via pie menu. + + # Add a 'memfile' undo step without leaving Sculpt mode. + yield e.f3().text("add const").ret().d() # Add 'Limit Distance' constraint. + # Note: Multires modifier exhibits even more issues with undo/redo in sculpt mode, but unfortunately geometry is not + # available from python anymore while in sculpt mode, so we cannot test/check if undo/redo steps apply properly. + # yield e.ctrl.two() # Add multires modifier. + + # Utility to extract current mesh coordinates (used to ensure undo/redo steps are applied properly). + def extract_mesh_cos(window): + # TODO: Find/add a way to get that info when there is a multires active in Sculpt mode. + window.view_layer.update() + tmp_mesh = window.view_layer.objects.active.to_mesh(preserve_all_data_layers=True) + tmp_cos = [0.0] * len(tmp_mesh.vertices) * 3 + tmp_mesh.vertices.foreach_get("co", tmp_cos) + window.view_layer.objects.active.to_mesh_clear() + return tmp_cos + + mesh_verts_cos_before_sculpt = extract_mesh_cos(window) + + # Add a first sculpt stroke. + yield from e.leftmouse.cursor_motion(_cursor_motion_data_x(window)) + mesh_verts_cos_sculpt_stroke1 = extract_mesh_cos(window) + t.assertNotEqual(mesh_verts_cos_before_sculpt, mesh_verts_cos_sculpt_stroke1) + + # Add a second sculpt stroke. + yield from e.leftmouse.cursor_motion(_cursor_motion_data_y(window)) + mesh_verts_cos_sculpt_stroke2 = extract_mesh_cos(window) + t.assertNotEqual(mesh_verts_cos_sculpt_stroke1, mesh_verts_cos_sculpt_stroke2) + + # Undo to first sculpt stroke. + yield e.ctrl.z() + mesh_verts_cos = extract_mesh_cos(window) + t.assertEqual(mesh_verts_cos, mesh_verts_cos_sculpt_stroke1) + + # Undo to memfile step (add constraint), fine here (T82532), + # but would fail if we had added a Multires modifier instead (T82851). + yield e.ctrl.z() + mesh_verts_cos = extract_mesh_cos(window) + t.assertEqual(mesh_verts_cos, mesh_verts_cos_before_sculpt) + + # Redo first sculpt stroke, would now be undone (in Multires case, T82851), + # or not redone (in constraint case, T82532). + yield e.ctrl.shift.z() + mesh_verts_cos = extract_mesh_cos(window) + t.assertEqual(mesh_verts_cos, mesh_verts_cos_sculpt_stroke1) + + # Redo second sculpt stroke, would redo properly, + # as well as part of the first one that affects the same nodes (T82851, T82532). + yield e.ctrl.shift.z() + mesh_verts_cos = extract_mesh_cos(window) + t.assertEqual(mesh_verts_cos, mesh_verts_cos_sculpt_stroke2) + + +def view3d_sculpt_dyntopo_simple(): + e, t = _test_vars(window := _test_window()) + yield from _view3d_startup_area_maximized(e) + + yield from _call_menu(e, "Add -> Mesh -> Torus") + # Avoid dynamic topology prompt. + yield from _call_by_name(e, "Remove UV Map") + if _MENU_CONFIRM_HACK: + yield + yield e.r().y().text("45").ret() # Rotate Y 45. + yield e.ctrl.a().r() # Apply rotation. + yield e.numpad_period() # View all. + yield e.ctrl.tab().s() # Sculpt via pie menu. + yield from _call_menu(e, "Sculpt -> Dynamic Topology Toggle") + # TODO: should be accessible from menu. + yield from _call_by_name(e, "Symmetrize") + yield e.ctrl.tab().o() # Object mode. + t.assertEqual(len(window.view_layer.objects.active.data.polygons), 1258) + yield e.delete() # Delete the object. + yield e.ctrl.z() # Undo... + yield e.ctrl.z() # Undo used to crash here: T60974 + t.assertEqual(len(window.view_layer.objects.active.data.polygons), 1258) + t.assertEqual(window.view_layer.objects.active.mode, 'SCULPT') + + +def view3d_sculpt_dyntopo_and_edit(): + e, t = _test_vars(window := _test_window()) + yield from _view3d_startup_area_maximized(e) + + yield from _call_menu(e, "Add -> Mesh -> Torus") + yield e.numpad_period() # View all. + yield from _call_by_name(e, "Remove UV Map") + yield e.ctrl.tab().s() # Sculpt via pie menu. + yield e.ctrl.d().ret() # Dynamic topology. + # TODO: should be accessible from menu. + yield from _call_by_name(e, "Symmetrize") + # Some painting (demo it works, not needed for the crash) + yield from e.leftmouse.cursor_motion(_cursor_motion_data_x(window)) + yield e.tab() # Edit mode. + yield e.tab() # Object mode. + yield e.ctrl.z(3) # Undo + # yield e.ctrl.z() # Undo asserts (nested undo call from dyntopo) + + +def view3d_texture_paint_simple(): + e, t = _test_vars(window := _test_window()) + yield from _view3d_startup_area_maximized(e) + + yield from _call_menu(e, "Add -> Mesh -> Monkey") + yield e.numpad_period() # View monkey + yield e.ctrl.tab().t() # Paint via pie menu. + yield from _call_by_name(e, "Add Texture Paint Slot") + yield e.ret() # Accept popup. + + yield from e.leftmouse.cursor_motion(_cursor_motion_data_x(window)) + yield e.ctrl.z(2) # Undo: initial texture paint. + t.assertEqual(window.view_layer.objects.active.mode, 'TEXTURE_PAINT') + yield e.ctrl.z() # Undo: object mode. + t.assertEqual(window.view_layer.objects.active.mode, 'OBJECT') + yield e.ctrl.shift.z(2) # Redo: initial blank canvas. + t.assertEqual(window.view_layer.objects.active.mode, 'TEXTURE_PAINT') + yield from e.leftmouse.cursor_motion(_cursor_motion_data_x(window)) + yield e.ctrl.z() # Used to crash T61172. + + +def view3d_texture_paint_complex(): + # More complex test than `view3d_texture_paint_simple`, + # including interleaved memfile steps, + # and a call to history to undo several steps at once. + e, t = _test_vars(window := _test_window()) + yield from _view3d_startup_area_maximized(e) + + yield from _call_menu(e, "Add -> Mesh -> Monkey") + yield e.numpad_period() # View monkey + yield e.ctrl.tab().t() # Paint via pie menu. + + yield from _call_by_name(e, "Add Texture Paint Slot") + yield e.ret() # Accept popup. + + yield from e.leftmouse.cursor_motion(_cursor_motion_data_x(window)) + yield from e.leftmouse.cursor_motion(_cursor_motion_data_y(window)) + + yield from _call_by_name(e, "Add Texture Paint Slot") + yield e.ret() # Accept popup. + + yield from e.leftmouse.cursor_motion(_cursor_motion_data_x(window)) + yield from e.leftmouse.cursor_motion(_cursor_motion_data_y(window)) + + yield e.ctrl.z(6) # Undo: initial texture paint. + t.assertEqual(window.view_layer.objects.active.mode, 'TEXTURE_PAINT') + yield e.ctrl.z() # Undo: object mode. + t.assertEqual(window.view_layer.objects.active.mode, 'OBJECT') + + yield e.ctrl.shift.z(2) # Redo: initial blank canvas. + t.assertEqual(window.view_layer.objects.active.mode, 'TEXTURE_PAINT') + + yield from e.leftmouse.cursor_motion(_cursor_motion_data_x(window)) + yield from e.leftmouse.cursor_motion(_cursor_motion_data_y(window)) + + yield from _call_by_name(e, "Undo History") + yield e.o() # Undo everything to Original step. + t.assertEqual(window.view_layer.objects.active.mode, 'OBJECT') + + +def view3d_mesh_edit_separate(): + e, t = _test_vars(window := _test_window()) + yield from _view3d_startup_area_maximized(e) + + yield from _call_menu(e, "Add -> Mesh -> Cube") + yield e.numpad_period() # View all. + yield e.tab() # Edit mode. + yield e.shift.d() # Duplicate... + yield e.x().text("3").ret() # Move X-3. + yield e.p().s() # Separate selection. + t.assertEqual(len(window.view_layer.objects), 2) + yield e.ctrl.z() # Undo. + t.assertEqual(len(window.view_layer.objects), 1) + yield e.tab() # Object mode. + t.assertEqual(len(window.view_layer.objects.active.data.polygons), 12) + yield e.tab() # Edit mode. + yield e.ctrl.i() # Invert selection. + yield e.p().s() # Separate selection. + yield e.tab() # Object mode. + t.assertEqual([len(ob.data.polygons) for ob in window.view_layer.objects], [6, 6]) + yield e.ctrl.z(8) # Undo until start. + t.assertEqual(len(window.view_layer.objects), 0) + yield e.ctrl.shift.z(8) # Redo until end. + t.assertEqual([len(ob.data.polygons) for ob in window.view_layer.objects], [6, 6]) + + +def view3d_mesh_particle_edit_mode_simple(): + e, t = _test_vars(window := _test_window()) + yield from _view3d_startup_area_maximized(e) + + yield from _call_menu(e, "Add -> Mesh -> Cube") + yield e.r.z().text("15").ret() # Single object-mode action (to test mixing different kinds of undo steps). + yield from _call_menu(e, "Object -> Quick Effects -> Quick Fur") + + yield e.ctrl.tab().s() # Particle sculpt mode. + t.assertEqual(window.view_layer.objects.active.mode, 'SCULPT_CURVES') + + # Brush strokes. + yield from e.leftmouse.cursor_motion(_cursor_motion_data_y(window)) + yield from e.leftmouse.cursor_motion(_cursor_motion_data_x(window)) + + # Undo and redo. + yield e.ctrl.z(5) + t.assertEqual(window.view_layer.objects.active.mode, 'OBJECT') + yield e.shift.ctrl.z(5) + + t.assertEqual(window.view_layer.objects.active.mode, 'SCULPT_CURVES') + + # Brush strokes. + yield from e.leftmouse.cursor_motion(_cursor_motion_data_y(window)) + yield from e.leftmouse.cursor_motion(_cursor_motion_data_x(window)) + + yield e.ctrl.z(7) + t.assertEqual(window.view_layer.objects.active.mode, 'OBJECT') + yield e.shift.ctrl.z(7) + + +def view3d_font_edit_mode_simple(): + e, t = _test_vars(window := _test_window()) + yield from _view3d_startup_area_maximized(e) + + yield from _call_menu(e, "Add -> Text") + yield e.numpad_period() # View all. + yield e.tab() # Edit mode. + yield e.ctrl.back_space() + yield e.text("Hello\nWorld") + yield e.tab() # Object mode. + t.assertEqual(window.view_layer.objects.active.data.body, 'Hello\nWorld') + yield e.r.x().text("90").ret() # Rotate 90, face the view. + yield e.tab() # Edit mode. + yield e.end() # Edit mode. + yield e.ctrl.back_space() + yield e.back_space() + yield e.tab() # Object mode. + t.assertEqual(window.view_layer.objects.active.data.body, 'Hello') + + yield e.ctrl.z(3) + t.assertEqual(window.view_layer.objects.active.data.body, 'Hello\nWorld') + yield e.shift.ctrl.z(3) + t.assertEqual(window.view_layer.objects.active.data.body, 'Hello') + + +def view3d_multi_mode_select(): + # Note, this test should be extended to change modes for each object type. + e, t = _test_vars(window := _test_window()) + yield from _view3d_startup_area_maximized(e) + + object_names = [] + + for i, (menu_search, ob_name) in enumerate(( + ("Add -> Armature", "Armature"), + ("Add -> Text", "Text"), + ("Add -> Mesh -> Cube", "Cube"), + ("Add -> Curve -> Bezier", "Curve"), + ("Add -> Volume -> Empty", "Volume Empty"), + ("Add -> Metaball -> Ball", "Metaball"), + ("Add -> Lattice", "Lattice"), + ("Add -> Light -> Point", "Point Light"), + ("Add -> Camera", "Camera"), + ("Add -> Empty -> Plain Axis", "Empty"), + )): + yield from _call_menu(e, menu_search) + # Single object-mode action (to test mixing different kinds of undo steps). + yield e.g.z().text(str(i * 2)).ret() + # Rename. + yield e.f2().text(ob_name).ret() + + object_names.append(window.view_layer.objects.active.name) + + yield from _call_menu(e, "View -> Frame All") + # print(object_names) + + for ob_name in object_names: + yield from _view3d_object_select_by_name(e, ob_name) + yield + # print() + # print('=' * 40) + # print(window.view_layer.objects.active.name, ob_name) + + for ob_name in reversed(object_names): + t.assertEqual(ob_name, window.view_layer.objects.active.name) + yield e.ctrl.z() + + +def view3d_multi_mode_multi_window(): + e_a, t = _test_vars(window_a := _test_window()) + yield from _call_menu(e_a, "Window -> New Main Window") + + e_b, _ = _test_vars(window_b := _test_window(windows_exclude={window_a})) + del _ + yield from _call_menu(e_b, "New Scene") + yield e_b.ret() + if _MENU_CONFIRM_HACK: + yield + + for e in (e_a, e_b): + pos_v3d = _cursor_position_from_spacetype(e.window, 'VIEW_3D') + e.cursor_position_set(x=pos_v3d[0], y=pos_v3d[1], move=True) + del pos_v3d + + yield from _view3d_startup_area_maximized(e_a) + yield from _view3d_startup_area_maximized(e_b) + + undo_current = 0 + undo_state_empty = undo_current + + yield from _call_menu(e_a, "Add -> Torus") + yield from _call_menu(e_b, "Add -> Monkey") + undo_current += 2 + + # Weight paint via pie menu. + yield e_a.ctrl.tab().w() + yield e_b.ctrl.tab().w() + undo_current += 2 + undo_state_wpaint = undo_current + + t.assertEqual(window_a.view_layer.objects.active.mode, 'WEIGHT_PAINT') + t.assertEqual(window_b.view_layer.objects.active.mode, 'WEIGHT_PAINT') + + # Object mode via pie menu. + yield e_a.ctrl.tab().o() + yield e_b.ctrl.tab().o() + undo_current += 2 + + undo_state_non_empty_start = undo_current + + # Edit mode. + yield e_a.tab() + yield e_b.tab() + undo_current += 2 + + vert_count_a_start = len(_bmesh_from_object(window_a.view_layer.objects.active).verts) + vert_count_b_start = len(_bmesh_from_object(window_b.view_layer.objects.active).verts) + + yield from _call_menu(e_a, "Edge -> Subdivide") + yield from _call_menu(e_b, "Edge -> Subdivide") + undo_current += 2 + + yield e_a.r().y().text("45").ret() # Rotate Y 45. + yield e_b.r().z().text("45").ret() # Rotate Z 45. + undo_current += 2 + + # Object mode. + yield e_a.tab() + yield e_b.tab() + undo_current += 2 + + # Object mode via pie menu. + yield e_a.ctrl.tab().s() + yield e_b.ctrl.tab().s() + undo_current += 2 + + t.assertEqual(window_a.view_layer.objects.active.mode, 'SCULPT') + t.assertEqual(window_b.view_layer.objects.active.mode, 'SCULPT') + + # Rotate 90. + yield from _call_menu(e_a, "Sculpt -> Rotate") + yield e_a.text("90").ret() + yield from _call_menu(e_b, "Sculpt -> Rotate") + yield e_b.text("90").ret() + undo_current += 2 + + # Object mode. + yield e_a.ctrl.tab().o() + yield e_b.ctrl.tab().o() + undo_current += 2 + + # Edit mode. + yield e_a.tab() + yield e_b.tab() + undo_current += 2 + + yield from _call_menu(e_a, "Edge -> Subdivide") + yield from _call_menu(e_b, "Edge -> Subdivide") + undo_current += 2 + + vert_count_a_end = len(_bmesh_from_object(window_a.view_layer.objects.active).verts) + vert_count_b_end = len(_bmesh_from_object(window_b.view_layer.objects.active).verts) + + t.assertEqual(vert_count_a_end, 9216) + t.assertEqual(vert_count_b_end, 7830) + + yield e_a.r().y().text("45").ret() # Rotate Y 45. + yield e_b.r().z().text("45").ret() # Rotate Z 45. + undo_current += 2 + + yield e_a.tab() + yield e_b.tab() + undo_current += 2 + + undo_state_final = undo_current + + undo_delta = undo_state_final - undo_state_empty + + yield e_a.ctrl.z(undo_delta) + undo_current -= undo_delta + + # Ensure scene is empty. + t.assertEqual(len(window_a.view_layer.objects), 0) + t.assertEqual(len(window_b.view_layer.objects), 0) + + undo_delta = undo_state_final - undo_state_empty + yield e_a.ctrl.shift.z(undo_delta) + undo_current += undo_delta + + t.assertEqual(window_a.view_layer.objects.active.mode, 'OBJECT') + t.assertEqual(window_b.view_layer.objects.active.mode, 'OBJECT') + + t.assertEqual(len(window_a.view_layer.objects.active.data.vertices), vert_count_a_end) + t.assertEqual(len(window_b.view_layer.objects.active.data.vertices), vert_count_b_end) + + undo_delta = undo_state_final - undo_state_wpaint + yield e_a.ctrl.z(undo_delta) + undo_current -= undo_delta + + t.assertEqual(window_a.view_layer.objects.active.mode, 'WEIGHT_PAINT') + t.assertEqual(window_b.view_layer.objects.active.mode, 'WEIGHT_PAINT') + + undo_delta = undo_state_non_empty_start - undo_state_wpaint + yield e_a.ctrl.shift.z(undo_delta) + undo_current += undo_delta + + t.assertEqual(len(window_a.view_layer.objects.active.data.vertices), vert_count_a_start) + t.assertEqual(len(window_b.view_layer.objects.active.data.vertices), vert_count_b_start) + + # Further checks could be added but this seems enough. + + +def view3d_edit_mode_multi_window(): + """ + Use undo and redo with multiple windows in edit-mode, + this test caused a crash with #110022. + """ + e_a, t = _test_vars(window_a := _test_window()) + + # Nice but slower. + use_all_area_ui_types = False + + # Use a large, single area so the window can be duplicated & split. + yield from _view3d_startup_area_single(e_a) + + yield from _call_menu(e_a, "Window -> New Main Window") + + e_b, _ = _test_vars(window_b := _test_window(windows_exclude={window_a})) + del _ + + yield from _call_menu(e_b, "New Scene") + yield e_b.ret() + if _MENU_CONFIRM_HACK: + yield + + for e in (e_a, e_b): + pos_v3d = _cursor_position_from_spacetype(e.window, 'VIEW_3D') + e.cursor_position_set(x=pos_v3d[0], y=pos_v3d[1], move=True) + del pos_v3d + + undo_current = 0 + + yield from _call_menu(e_a, "Add -> Cone") + yield from _call_menu(e_b, "Add -> Cylinder") + undo_current += 2 + + # Edit mode. + yield e_a.tab() + yield e_b.tab() + undo_current += 2 + + undo_state_edit_mode = undo_current + + vert_count_a_start = len(_bmesh_from_object(window_a.view_layer.objects.active).verts) + vert_count_b_start = len(_bmesh_from_object(window_b.view_layer.objects.active).verts) + + yield e_a.r().y().text("45").ret() # Rotate Y 45. + yield e_b.r().z().text("45").ret() # Rotate Z 45. + undo_current += 2 + + yield from _call_menu(e_a, "Face -> Poke Faces") + yield from _call_menu(e_b, "Face -> Poke Faces") + undo_current += 2 + + yield from _call_menu(e_a, "Face -> Beautify Faces") + yield from _call_menu(e_b, "Face -> Beautify Faces") + undo_current += 2 + + yield from _call_menu(e_a, "Face -> Wireframe") + yield from _call_menu(e_b, "Face -> Wireframe") + undo_current += 2 + + vert_count_a_end = len(_bmesh_from_object(window_a.view_layer.objects.active).verts) + vert_count_b_end = len(_bmesh_from_object(window_b.view_layer.objects.active).verts) + + # Object mode. + yield e_a.tab() + yield e_b.tab() + undo_current += 2 + + # Finished with edits, assert undo is working as expected. + + yield e_a.ctrl.z(undo_current - undo_state_edit_mode) + + t.assertEqual(len(_bmesh_from_object(window_a.view_layer.objects.active).verts), vert_count_a_start) + t.assertEqual(len(_bmesh_from_object(window_b.view_layer.objects.active).verts), vert_count_b_start) + t.assertEqual(window_a.view_layer.objects.active.mode, 'EDIT') + t.assertEqual(window_b.view_layer.objects.active.mode, 'EDIT') + + yield e_a.ctrl.shift.z(undo_current - undo_state_edit_mode) + + t.assertEqual(len(window_a.view_layer.objects.active.data.vertices), vert_count_a_end) + t.assertEqual(len(window_b.view_layer.objects.active.data.vertices), vert_count_b_end) + t.assertEqual(window_a.view_layer.objects.active.mode, 'OBJECT') + t.assertEqual(window_b.view_layer.objects.active.mode, 'OBJECT') + + # Delete objects. + yield e_a.delete() + yield e_b.delete() + undo_current += 2 + + yield e_b.ctrl.z(undo_current) + + # Ensure scene is empty. + t.assertEqual(len(window_a.view_layer.objects), 0) + t.assertEqual(len(window_b.view_layer.objects), 0) + + yield e_b.ctrl.shift.z(undo_current - 2) + undo_current -= 2 + + t.assertEqual(len(window_a.view_layer.objects.active.data.vertices), vert_count_a_end) + t.assertEqual(len(window_b.view_layer.objects.active.data.vertices), vert_count_b_end) + t.assertEqual(window_a.view_layer.objects.active.mode, 'OBJECT') + t.assertEqual(window_b.view_layer.objects.active.mode, 'OBJECT') + + # Second phase! + # Split windows & show space types (could be a utility function). + # Test undo / redo doesn't cause issues when showing different space types. + if use_all_area_ui_types: + # TODO: extracting the enum from an exception is not good. + # As it's a dynamic enum it can't be accessed from `bl_rna.properties`. + try: + e_a.window.screen.areas[0].ui_type = '__INVALID__' + except TypeError as ex: + ui_types = ex.args[0] + ui_types = eval(ui_types[ui_types.rfind("("):]) + else: + ui_types = ('VIEW_3D', 'PROPERTIES') + + for e in (e_a, e_b): + yield from _setup_window_areas_from_ui_types(e, ui_types) + + # Ensure each undo step redraws. + for _ in range(undo_current - undo_state_edit_mode): + yield e_b.ctrl.z() + + t.assertEqual(len(_bmesh_from_object(window_a.view_layer.objects.active).verts), vert_count_a_start) + t.assertEqual(len(_bmesh_from_object(window_b.view_layer.objects.active).verts), vert_count_b_start) + t.assertEqual(window_a.view_layer.objects.active.mode, 'EDIT') + t.assertEqual(window_b.view_layer.objects.active.mode, 'EDIT') + + # Ensure each undo step redraws. + for _ in range(undo_current - undo_state_edit_mode): + yield e_b.ctrl.shift.z() + + t.assertEqual(len(window_a.view_layer.objects.active.data.vertices), vert_count_a_end) + t.assertEqual(len(window_b.view_layer.objects.active.data.vertices), vert_count_b_end) + t.assertEqual(window_a.view_layer.objects.active.mode, 'OBJECT') + t.assertEqual(window_b.view_layer.objects.active.mode, 'OBJECT') diff --git a/tests/utils/blender_headless.py b/tests/utils/blender_headless.py index 06e140149a1..1c45c572ac3 100644 --- a/tests/utils/blender_headless.py +++ b/tests/utils/blender_headless.py @@ -287,7 +287,12 @@ class backend_wayland(backend_base): blender_env = {**os.environ, "WAYLAND_DISPLAY": socket} + # Needed so Blender can find WAYLAND libraries such as `libwayland-cursor.so`. + if weston_env is not None and "LD_LIBRARY_PATH" in weston_env: + blender_env["LD_LIBRARY_PATH"] = weston_env["LD_LIBRARY_PATH"] + cmd = [ + # "strace", # Can be useful for debugging any startup issues. BLENDER_BIN, *blender_args, ] diff --git a/tools/utils_maintenance/code_clean.py b/tools/utils_maintenance/code_clean.py index 79083346b56..42b486e5f1d 100755 --- a/tools/utils_maintenance/code_clean.py +++ b/tools/utils_maintenance/code_clean.py @@ -1076,6 +1076,41 @@ class edit_generators: return edits + class use_std_min_max(EditGenerator): + """ + Use `std::min` & `std::max` instead of `MIN2`, `MAX2` macros: + + Replace: + MAX2(a, b) + With: + std::max(a, b) + """ + is_default = True + + @staticmethod + def edit_list_from_file(source: str, data: str, _shared_edit_data: Any) -> List[Edit]: + edits: List[Edit] = [] + + # The user might include C & C++, if they forget, it is better not to operate on C. + if source.lower().endswith((".h", ".c")): + return edits + + for src, dst in ( + ("MIN2", "std::min"), + ("MAX2", "std::max"), + ): + for match in re.finditer( + (r"\b(" + src + r")\("), + data, + ): + edits.append(Edit( + span=match.span(1), + content=dst, + content_fail='__ALWAYS_FAIL__', + )) + + return edits + class use_str_sizeof_macros(EditGenerator): """ Use `STRNCPY` & `SNPRINTF` macros: